com.vmware.bdd.service.resmgmt.impl.ResourceService.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.bdd.service.resmgmt.impl.ResourceService.java

Source

/***************************************************************************
 * Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ***************************************************************************/

package com.vmware.bdd.service.resmgmt.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.vmware.aurora.global.Configuration;
import com.vmware.aurora.vc.VcCluster;
import com.vmware.aurora.vc.VcDatastore;
import com.vmware.aurora.vc.VcHost;
import com.vmware.aurora.vc.VcNetwork;
import com.vmware.aurora.vc.VcResourcePool;
import com.vmware.aurora.vc.vcservice.VcContext;
import com.vmware.aurora.vc.vcservice.VcSession;
import com.vmware.bdd.dal.IDatastoreDAO;
import com.vmware.bdd.dal.INetworkDAO;
import com.vmware.bdd.dal.IResourcePoolDAO;
import com.vmware.bdd.entity.NetworkEntity;
import com.vmware.bdd.entity.VcDatastoreEntity;
import com.vmware.bdd.entity.VcResourcePoolEntity;
import com.vmware.bdd.entity.resmgmt.ResourceReservation;
import com.vmware.bdd.exception.BddException;
import com.vmware.bdd.exception.VcProviderException;
import com.vmware.bdd.service.resmgmt.IResourceService;
import com.vmware.bdd.service.utils.VcResourceUtils;
import com.vmware.bdd.utils.AuAssert;
import com.vmware.bdd.utils.CommonUtil;
import com.vmware.bdd.utils.Constants;

/**
 * @author Jarred Li
 * @since 0.8
 * @version 0.8
 *
 */
@Service
public class ResourceService implements IResourceService {

    private static final Logger logger = Logger.getLogger(ResourceService.class);

    private IResourcePoolDAO rpDao;
    private IDatastoreDAO dsDao;
    private INetworkDAO networkDao;

    private final Map<UUID, ResourceReservation> reservedResource = new ConcurrentHashMap<UUID, ResourceReservation>();

    // Fair Semaphore ensures the policy of resource reservation is first come, first served. 
    private Semaphore reservationPermits = new Semaphore(1, true);

    /**
     * @return the rpDao
     */
    public IResourcePoolDAO getRpDao() {
        return rpDao;
    }

    /**
     * @param rpDao
     *           the rpDao to set
     */
    @Autowired
    public void setRpDao(IResourcePoolDAO rpDao) {
        this.rpDao = rpDao;
    }

    /**
     * @return the dsDao
     */
    public IDatastoreDAO getDsDao() {
        return dsDao;
    }

    /**
     * @param dsDao
     *           the dsDao to set
     */
    @Autowired
    public void setDsDao(IDatastoreDAO dsDao) {
        this.dsDao = dsDao;
    }

    /**
     * @return the networkDao
     */
    public INetworkDAO getNetworkDao() {
        return networkDao;
    }

    /**
     * @param networkDao
     *           the networkDao to set
     */
    @Autowired
    public void setNetworkDao(INetworkDAO networkDao) {
        this.networkDao = networkDao;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getResourcePoolByName(java.lang.String)
     */
    @Override
    public VcResourcePool getResourcePoolByName(String rpName) throws VcProviderException {
        if (StringUtils.isEmpty(rpName)) {
            throw VcProviderException.RESOURCE_POOL_NAME_INVALID(rpName);
        }
        VcResourcePoolEntity rp = rpDao.findByName(rpName);
        final String clusterName = rp.getVcCluster();
        final String vcRPName = rp.getVcResourcePool();

        VcResourcePool vcRP = VcResourceUtils.findRPInVCCluster(clusterName, vcRPName);
        if (vcRP == null) {
            throw VcProviderException.RESOURCE_POOL_NOT_FOUND(rpName);
        }
        return vcRP;
    }

    @Override
    public boolean isRPExistInVc(String clusterName, String rpName) throws VcProviderException {
        boolean result = false;
        VcResourcePool vcRP = VcResourceUtils.findRPInVCCluster(clusterName, rpName);
        if (vcRP != null) {
            result = true;
        }
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getAvailableRPs()
     */
    @Override
    public List<VcResourcePool> getAvailableRPs() throws VcProviderException {
        List<VcResourcePool> result = new ArrayList<VcResourcePool>();

        List<VcResourcePoolEntity> allRPEntities = rpDao.findAllOrderByClusterName();

        for (VcResourcePoolEntity rpEntity : allRPEntities) {
            VcResourcePool vcRP = VcResourceUtils.findRPInVCCluster(rpEntity.getVcCluster(),
                    rpEntity.getVcResourcePool());
            if (vcRP != null) {
                result.add(vcRP);
            } else {
                logger.warn("Could not find the resource pool in the vCenter. RP name:" + rpEntity.getName());
            }
        }
        return result;
    }

    @Override
    public void refreshResourcePool() {
        List<VcCluster> vcClusters = VcResourceUtils.getClusters();
        AuAssert.check(vcClusters != null && vcClusters.size() != 0);
        for (VcCluster vcCluster : vcClusters) {
            VcResourceUtils.refreshResourcePool(vcCluster);
        }
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getDatastoreByName(java.lang.String)
     */
    @Override
    public List<VcDatastore> getDatastoreByName(String dsName) throws VcProviderException {
        logger.info("get datastore by name: " + dsName);
        List<VcDatastoreEntity> datastores = dsDao.findByName(dsName);
        return findDSInVC(datastores);
    }

    @Deprecated
    public void refreshVcResources() {
        VcResourceUtils.refreshVcResources();
    }

    @Override
    public void refreshDatastore() {
        List<VcCluster> vcClusters = VcResourceUtils.getClusters();
        AuAssert.check(vcClusters != null && vcClusters.size() != 0);
        for (VcCluster vcCluster : vcClusters) {
            VcResourceUtils.refreshDatastore(vcCluster);
        }
    }

    @Override
    public boolean isDatastoreExistInVC(String dsName) throws VcProviderException {
        boolean result = false;
        Collection<VcDatastore> vcDS = VcResourceUtils.findDSInVCByPattern(dsName);
        if (vcDS != null && vcDS.size() > 0) {
            result = true;
        }
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getAvailableDSs()
     */
    @Override
    public List<VcDatastore> getAvailableDSs() throws VcProviderException {
        List<VcDatastoreEntity> datastores = dsDao.findAllSortByName();
        return findDSInVC(datastores);
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.IResourceManager#isDatastoreAccessibleByCluster(java.lang.String, java.lang.String)
     */
    @Override
    public boolean isDatastoreAccessibleByCluster(String datastoreSpec, String cluster) throws VcProviderException {
        boolean result = false;
        List<VcDatastore> availableDatastores = getDatastoreByName(datastoreSpec);
        List<VcHost> hosts = getHostsByClusterName(cluster);
        for (VcHost host : hosts) {
            List<VcDatastore> hostDSs = host.getDatastores();
            boolean found = false;
            for (VcDatastore availableDS : availableDatastores) {
                for (VcDatastore hostDS : hostDSs) {
                    if (availableDS.getName().equals(hostDS.getName())) {
                        found = true;
                        break;
                    }
                }
                if (found) {
                    break;
                }
            }
            if (found) {
                result = true;
                break;
            }
        }
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getNetworkByName(java.lang.String)
     */
    @Override
    public VcNetwork getNetworkByName(String networkName) throws VcProviderException {
        NetworkEntity networkEntity = networkDao.findNetworkByName(networkName);
        return VcResourceUtils.findNetworkInVC(networkEntity.getPortGroup());
    }

    @Override
    public void refreshNetwork() {
        List<VcCluster> vcClusters = VcResourceUtils.getClusters();
        AuAssert.check(vcClusters != null && vcClusters.size() != 0);
        for (VcCluster vcCluster : vcClusters) {
            VcResourceUtils.refreshNetwork(vcCluster);
        }
    }

    @Override
    public boolean isNetworkExistInVc(String networkName) throws VcProviderException {
        boolean result = false;
        refreshNetwork();
        VcNetwork network = VcResourceUtils.findNetworkInVC(networkName);
        if (network != null) {
            result = true;
        }
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getAvailableNetworks()
     */
    @Override
    public List<VcNetwork> getAvailableNetworks() throws VcProviderException {
        List<NetworkEntity> networkList = networkDao.findAllNetworks();
        List<VcNetwork> result = new ArrayList<VcNetwork>();
        for (NetworkEntity networkEntity : networkList) {
            VcNetwork network = VcResourceUtils.findNetworkInVC(networkEntity.getPortGroup());
            if (network != null) {
                result.add(network);
            } else {
                logger.warn("Could not find the network in the vCenter. Network name: " + networkEntity.getName());
            }
        }
        return result;
    }

    @Override
    public boolean isNetworkSharedInCluster(String networkName, String clusterName) throws VcProviderException {
        boolean result = true;
        refreshNetwork();
        VcNetwork vcNetwork = getNetworkByName(networkName);
        if (vcNetwork == null) {
            return false;
        } else {
            String portGroupName = vcNetwork.getName();
            List<VcHost> hosts = getHostsByClusterName(clusterName);
            for (VcHost vcHost : hosts) {
                List<VcNetwork> networks = vcHost.getNetworks();
                boolean found = false;
                for (VcNetwork network : networks) {
                    if (network.getName().equals(portGroupName)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    logger.error("host " + vcHost + " has networks " + networks + " does not have target network "
                            + portGroupName);
                    result = false;
                    break;
                }
            }
        }
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getHostsByRpName(java.lang.String)
     */
    @Override
    public List<VcHost> getHostsByRpName(String rpName) throws VcProviderException {
        VcResourcePoolEntity rp = rpDao.findByName(rpName);
        final String vcClusterName = rp.getVcCluster();
        final String vcRpName = rp.getVcResourcePool();
        return VcResourceUtils.findAllHostInVcResourcePool(vcClusterName, vcRpName);
    }

    private UUID addReservation(ResourceReservation resReservation) {
        UUID result = UUID.randomUUID();
        reservedResource.put(result, resReservation);
        return result;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#reserveResoruce(com.vmware.bdd.bo.ResourceReservation)
     */
    @Override
    public UUID reserveResource(ResourceReservation resReservation) throws VcProviderException {
        boolean concurrentJobEnabled = Configuration.getBoolean(Constants.SERENGETI_CONCURRENT_JOB_ENABLED, false);
        if (concurrentJobEnabled) {//if concurrent creation switch is on, don't check concurrent creations.
            logger.info("concurrent cluster create is performed.");
            return addReservation(resReservation);
        } else { // Only one creation can be running, others will wait for its finishing.
            long maxWait = Configuration.getLong("serengeti.concurrent.job.maxWaitMins", 120l);
            try {
                reservationPermits.tryAcquire(maxWait, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                BddException.INTERNAL(e, "waiting for concurrent cluster creation but was interrupted");
            }
            logger.info("reservedResource is empty: " + reservedResource.isEmpty());

            if (resourceAlreadyReserved()) {
                ResourceReservation[] reservations = reservedResource.values().toArray(new ResourceReservation[0]);
                String clusterName = reservations[0].getClusterName();
                logger.error("concurrent cluster create is not allowed.");
                throw VcProviderException
                        .CONCURRENT_CLUSTER_CREATING(clusterName != null ? clusterName : "unknown cluster");
            } else {
                return addReservation(resReservation);
            }
        }
    }

    private boolean resourceAlreadyReserved() {
        return !reservedResource.isEmpty();
    }

    private void removeReservation(UUID reservationId) {
        if (reservedResource.containsKey(reservationId)) {
            reservedResource.remove(reservationId);
            if (!Configuration.getBoolean(Constants.SERENGETI_CONCURRENT_JOB_ENABLED, false)) {
                reservationPermits.release();
            }
        } else {
            BddException.INTERNAL(new Exception(), String.format("%s: reservation ID %s not found",
                    Thread.currentThread().getName(), reservationId));
        }
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#cancleReservation(long)
     */
    @Override
    public void cancleReservation(UUID reservationId) throws VcProviderException {
        removeReservation(reservationId);
        logger.info("current VMs Cloning is canceled, remove Reservation.");
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#commitReservation(long)
     */
    @Override
    public void commitReservation(UUID reservationId) throws VcProviderException {
        removeReservation(reservationId);
        logger.info("current VMs Cloning is done, commit Reservation.");
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getHostsByClusterName(java.lang.String)
     */
    @Override
    public List<VcHost> getHostsByClusterName(String clusterName) throws VcProviderException {
        return VcResourceUtils.findAllHostsInVCCluster(clusterName);
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.ResourceManager#getAvailableClusters()
     */
    @Override
    public List<VcCluster> getAvailableClusters() throws VcProviderException {
        final HashSet<String> clusterNameFromRps = new HashSet<>(rpDao.findAllClusterName());

        return VcContext.inVcSessionDo(new VcSession<List<VcCluster>>() {

            @Override
            protected List<VcCluster> body() throws Exception {
                List<VcCluster> results = new ArrayList<>();

                for (VcCluster vcCluster : VcResourceUtils.getClusters()) {
                    if (clusterNameFromRps.contains(vcCluster.getName())) {
                        results.add(vcCluster);
                    }
                }

                return results;
            }

        });
    }

    /**
     * @param datastores
     * @return
     */
    protected List<VcDatastore> findDSInVC(List<VcDatastoreEntity> datastores) {
        List<VcDatastore> result = new ArrayList<VcDatastore>();
        if (datastores == null) {
            return result;
        }
        for (VcDatastoreEntity dsEntity : datastores) {
            Collection<VcDatastore> vcDS;
            if (dsEntity.getRegex() != null && dsEntity.getRegex()) {
                vcDS = VcResourceUtils.findDSInVCByPattern(dsEntity.getVcDatastore());
            } else {
                vcDS = VcResourceUtils
                        .findDSInVCByPattern(CommonUtil.getDatastoreJavaPattern(dsEntity.getVcDatastore()));
            }
            if (vcDS != null) {
                result.addAll(vcDS);
            } else {
                logger.warn("Could not find the data store in the vCenter. Name:" + dsEntity.getVcDatastore());
            }
        }
        return result;
    }

    @Override
    public Map<String, String> getCloudProviderAttributes() {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(Constants.CLOUD_PROVIDER_NAME_FIELD, Constants.VSPHERE_PROVIDER_NAME);
        attr.put(Constants.CLOUD_PROVIDER_TYPE_FIELD, Constants.VSPHERE_PROVIDER_TYPE);
        return attr;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.IResourceService#filterHostsByNetwork(java.util.List, java.util.List)
     */
    @Override
    public List<String> filterHostsByNetwork(List<String> networkList,
            List<com.vmware.bdd.spectypes.VcCluster> clusters) {
        // refresh all resource when at beginning of creating/resizing/resuming cluster
        //refreshNetwork();
        Set<String> networkNames = new HashSet<String>();
        networkNames.addAll(networkList);
        Set<String> portGroupNames = new HashSet<String>();
        for (String networkName : networkNames) {
            VcNetwork vcNetwork = getNetworkByName(networkName);
            if (vcNetwork == null) {
                throw VcProviderException.NETWORK_NOT_FOUND(networkName);
            }
            portGroupNames.add(vcNetwork.getName());
        }

        List<String> noNetworkHosts = new ArrayList<String>();
        for (com.vmware.bdd.spectypes.VcCluster cluster : clusters) {
            List<VcHost> hosts = getHostsByClusterName(cluster.getName());
            for (VcHost vcHost : hosts) {
                // check each host has all the networks
                List<VcNetwork> vcNetworks = vcHost.getNetworks();
                List<String> hostNetworkNames = new ArrayList<String>();
                for (VcNetwork vcNetwork : vcNetworks) {
                    hostNetworkNames.add(vcNetwork.getName());
                }
                if (!hostNetworkNames.containsAll(portGroupNames)) {
                    logger.info("host" + vcHost.getName() + " has networks " + vcNetworks
                            + " does not have target network " + portGroupNames);
                    noNetworkHosts.add(vcHost.getName());
                }
            }
        }
        return noNetworkHosts;
    }

    /* (non-Javadoc)
     * @see com.vmware.bdd.service.resmgmt.IResourceService#isNetworkAccessibleByCluster(java.util.List, java.util.List)
     */
    @Override
    public boolean isNetworkAccessibleByCluster(List<String> networkList,
            List<com.vmware.bdd.spectypes.VcCluster> clusters) {
        // refresh all resource when at beginning of creating/resizing/resuming cluster
        //      refreshNetwork();

        Set<String> portGroupNames = new HashSet<String>();
        for (String networkName : networkList) {
            VcNetwork vcNetwork = getNetworkByName(networkName);
            if (vcNetwork == null) {
                throw VcProviderException.NETWORK_NOT_FOUND(networkName);
            }
            portGroupNames.add(vcNetwork.getName());
        }

        for (com.vmware.bdd.spectypes.VcCluster cluster : clusters) {
            List<VcHost> hosts = getHostsByClusterName(cluster.getName());
            for (VcHost vcHost : hosts) {
                List<VcNetwork> vcNetworks = vcHost.getNetworks();
                List<String> hostNetworkNames = new ArrayList<String>();
                for (VcNetwork vcNetwork : vcNetworks) {
                    hostNetworkNames.add(vcNetwork.getName());
                }
                if (hostNetworkNames.containsAll(portGroupNames)) {
                    return true;
                }
            }
        }
        return false;
    }

}