diff --git a/api/src/com/cloud/exception/AffinityConflictException.java b/api/src/com/cloud/exception/AffinityConflictException.java index 75df78419ab..da7148f1e2d 100644 --- a/api/src/com/cloud/exception/AffinityConflictException.java +++ b/api/src/com/cloud/exception/AffinityConflictException.java @@ -1,9 +1,9 @@ package com.cloud.exception; -import com.cloud.exception.CloudException; import com.cloud.utils.SerialVersionUID; +import com.cloud.utils.exception.CloudRuntimeException; -public class AffinityConflictException extends CloudException { +public class AffinityConflictException extends CloudRuntimeException { private static final long serialVersionUID = SerialVersionUID.AffinityConflictException; diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java index e6c64b3ff9c..9bdd0515f47 100644 --- a/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java @@ -1,8 +1,27 @@ package org.apache.cloudstack.affinity; -import org.apache.cloudstack.deploy.UserPreferrenceProcessor; +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.utils.component.Adapter; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; -public interface AffinityGroupProcessor extends UserPreferrenceProcessor { +public interface AffinityGroupProcessor extends Adapter { + + /** + * process() is called to apply any user preferences to the deployment plan + * and avoid set for the given VM placement. + * + * @param vm + * virtual machine. + * @param plan + * deployment plan that tells you where it's being deployed to. + * @param avoid + * avoid these data centers, pods, clusters, or hosts. + */ + void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + throws AffinityConflictException; /** * getType() should return the affinity/anti-affinity group being diff --git a/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java new file mode 100644 index 00000000000..74fdde166eb --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java @@ -0,0 +1,28 @@ +package org.apache.cloudstack.affinity; + +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +public class AffinityProcessorBase extends AdapterBase implements AffinityGroupProcessor { + + protected String _type; + + @Override + public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + throws AffinityConflictException { + + } + + @Override + public String getType() { + return _type; + } + + public void setType(String type) { + _type = type; + } +} diff --git a/api/src/org/apache/cloudstack/deploy/UserPreferrenceProcessor.java b/api/src/org/apache/cloudstack/deploy/UserPreferrenceProcessor.java deleted file mode 100644 index ad26f0e06d8..00000000000 --- a/api/src/org/apache/cloudstack/deploy/UserPreferrenceProcessor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.apache.cloudstack.deploy; - - -import com.cloud.deploy.DeploymentPlan; -import com.cloud.deploy.DeploymentPlanner.ExcludeList; -import com.cloud.exception.AffinityConflictException; -import com.cloud.utils.component.Adapter; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineProfile; - -public interface UserPreferrenceProcessor extends Adapter { - - /** - * process() is called to apply any user preferences to the deployment plan - * and avoid set for the given VM placement. - * - * @param vm - * virtual machine. - * @param plan - * deployment plan that tells you where it's being deployed to. - * @param avoid - * avoid these data centers, pods, clusters, or hosts. - */ - void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) - throws AffinityConflictException; - -} \ No newline at end of file diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 55fa599825f..4ce9fd3af5c 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -574,3 +574,4 @@ createAffinityGroup=15 deleteAffinityGroup=15 listAffinityGroups=15 updateVMAffinityGroup=15 +listAffinityGroupTypes=15 diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index 0359db95a96..ec813b2e998 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -36,7 +36,9 @@ import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -55,7 +57,7 @@ import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; -import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineProfile; @@ -69,42 +71,45 @@ public class VMEntityManagerImpl implements VMEntityManager { protected VMInstanceDao _vmDao; @Inject protected VMTemplateDao _templateDao = null; - + @Inject protected ServiceOfferingDao _serviceOfferingDao; - + @Inject protected DiskOfferingDao _diskOfferingDao = null; - + @Inject protected NetworkDao _networkDao; - + @Inject protected AccountDao _accountDao = null; @Inject protected UserDao _userDao = null; - @Inject + @Inject protected VMEntityDao _vmEntityDao; - - @Inject + + @Inject protected VMReservationDao _reservationDao; - + @Inject protected VirtualMachineManager _itMgr; - + @Inject protected List _planners; - + @Inject protected VolumeDao _volsDao; - + @Inject protected PrimaryDataStoreDao _storagePoolDao; @Inject DataStoreManager dataStoreMgr; - + + @Inject + DeploymentPlanningManager _dpMgr; + @Override public VMEntityVO loadVirtualMachine(String vmId) { // TODO Auto-generated method stub @@ -114,11 +119,11 @@ public class VMEntityManagerImpl implements VMEntityManager { @Override public void saveVirtualMachine(VMEntityVO entity) { _vmEntityDao.persist(entity); - + } @Override - public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) + public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) throws InsufficientCapacityException, ResourceUnavailableException { //call planner and get the deployDestination. @@ -130,12 +135,12 @@ public class VMEntityManagerImpl implements VMEntityManager { if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){ plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId()); } - + List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId()); if(!vols.isEmpty()){ VolumeVO vol = vols.get(0); StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(vol.getPoolId()); - + if (!pool.isInMaintenance()) { long rootVolDcId = pool.getDataCenterId(); Long rootVolPodId = pool.getPodId(); @@ -156,21 +161,21 @@ public class VMEntityManagerImpl implements VMEntityManager { } } - + + } + + DeployDestination dest; + try { + dest = _dpMgr.planDeployment(vmProfile, plan, exclude); + } catch (AffinityConflictException e) { + throw new CloudRuntimeException("Unable to create deployment, affinity rules associted to the VM conflict"); } - - DeploymentPlanner planner = ComponentContext.getComponent(plannerToUse); - DeployDestination dest = null; - - if (planner.canHandle(vmProfile, plan, exclude)) { - dest = planner.plan(vmProfile, plan, exclude); - } if (dest != null) { //save destination with VMEntityVO VMReservationVO vmReservation = new VMReservationVO(vm.getId(), dest.getDataCenter().getId(), dest.getPod().getId(), dest.getCluster().getId(), dest.getHost().getId()); Map volumeReservationMap = new HashMap(); - + if (vm.getHypervisorType() != HypervisorType.BareMetal) { for(Volume vo : dest.getStorageForDisks().keySet()){ volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId()); @@ -180,21 +185,21 @@ public class VMEntityManagerImpl implements VMEntityManager { vmEntityVO.setVmReservation(vmReservation); _vmEntityDao.persist(vmEntityVO); - + return vmReservation.getUuid(); }else{ throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } - + } @Override public void deployVirtualMachine(String reservationId, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException{ //grab the VM Id and destination using the reservationId. - + VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId); long vmId = vmReservation.getVmId(); - + VMInstanceVO vm = _vmDao.findById(vmId); //Pass it down Long poolId = null; @@ -205,12 +210,17 @@ public class VMEntityManagerImpl implements VMEntityManager { poolId = storage.get(volIdList.get(0)); } } - - DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), + + DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), vmReservation.getHostId(), null , null); - - VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); - + try{ + VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), reservedPlan); + }catch(Exception ex){ + //Retry the deployment without using the reservation plan + DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), null, null,null, null , null); + _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); + } + } @Override @@ -227,7 +237,7 @@ public class VMEntityManagerImpl implements VMEntityManager { VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); return _itMgr.destroy(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId())); - + } } diff --git a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java index 11b391b74c6..88030f21799 100644 --- a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java +++ b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java @@ -28,7 +28,6 @@ import org.apache.log4j.Logger; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; -import com.cloud.utils.component.AdapterBase; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @@ -36,7 +35,7 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Local(value = AffinityGroupProcessor.class) -public class HostAntiAffinityProcessor extends AdapterBase implements AffinityGroupProcessor { +public class HostAntiAffinityProcessor extends AffinityProcessorBase implements AffinityGroupProcessor { private static final Logger s_logger = Logger.getLogger(HostAntiAffinityProcessor.class); @Inject @@ -74,9 +73,4 @@ public class HostAntiAffinityProcessor extends AdapterBase implements AffinityGr } - @Override - public String getType() { - return "HostAntiAffinity"; - } - } diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 2dffe70fb46..1647cf7dba9 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -161,38 +161,44 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { + hostIdSpecified); } HostVO host = _hostDao.findById(hostIdSpecified); - if (s_logger.isDebugEnabled()) { - if(host == null){ - s_logger.debug("The specified host cannot be found"); - }else{ + if (host == null) { + s_logger.debug("The specified host cannot be found"); + } else if (avoid.shouldAvoid(host)) { + s_logger.debug("The specified host is in avoid set"); + } else { + if (s_logger.isDebugEnabled()) { s_logger.debug("Looking for suitable pools for this host under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId()); } - } - //search for storage under the zone, pod, cluster of the host. - DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, plan.getReservationContext()); + // search for storage under the zone, pod, cluster of the host. + DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), + host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, plan.getReservationContext()); - Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); - Map> suitableVolumeStoragePools = result.first(); - List readyAndReusedVolumes = result.second(); + Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, + lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); + Map> suitableVolumeStoragePools = result.first(); + List readyAndReusedVolumes = result.second(); - //choose the potential pool for this VM for this host - if(!suitableVolumeStoragePools.isEmpty()){ - List suitableHosts = new ArrayList(); - suitableHosts.add(host); + // choose the potential pool for this VM for this host + if (!suitableVolumeStoragePools.isEmpty()) { + List suitableHosts = new ArrayList(); + suitableHosts.add(host); - Pair> potentialResources = findPotentialDeploymentResources(suitableHosts, suitableVolumeStoragePools); - if(potentialResources != null){ - Pod pod = _podDao.findById(host.getPodId()); - Cluster cluster = _clusterDao.findById(host.getClusterId()); - Map storageVolMap = potentialResources.second(); - // remove the reused vol<->pool from destination, since we don't have to prepare this volume. - for(Volume vol : readyAndReusedVolumes){ - storageVolMap.remove(vol); + Pair> potentialResources = findPotentialDeploymentResources( + suitableHosts, suitableVolumeStoragePools); + if (potentialResources != null) { + Pod pod = _podDao.findById(host.getPodId()); + Cluster cluster = _clusterDao.findById(host.getClusterId()); + Map storageVolMap = potentialResources.second(); + // remove the reused vol<->pool from destination, since + // we don't have to prepare this volume. + for (Volume vol : readyAndReusedVolumes) { + storageVolMap.remove(vol); + } + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; } - DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap); - s_logger.debug("Returning Deployment Destination: "+ dest); - return dest; } } s_logger.debug("Cannnot deploy to specified host, returning."); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 01798cc5b87..b869d1e21b3 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -37,14 +37,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; import javax.naming.ConfigurationException; import com.cloud.storage.dao.*; @@ -54,59 +49,43 @@ import org.apache.cloudstack.api.ApiConstants; import com.cloud.event.ActionEventUtils; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.account.*; -import org.apache.cloudstack.api.command.admin.autoscale.*; -import org.apache.cloudstack.api.command.admin.cluster.*; -import org.apache.cloudstack.api.command.admin.config.*; import org.apache.cloudstack.api.command.admin.domain.*; import org.apache.cloudstack.api.command.admin.host.*; -import org.apache.cloudstack.api.command.admin.ldap.*; import org.apache.cloudstack.api.command.admin.network.*; import org.apache.cloudstack.api.command.admin.offering.*; -import org.apache.cloudstack.api.command.admin.pod.*; -import org.apache.cloudstack.api.command.admin.region.*; import org.apache.cloudstack.api.command.admin.resource.*; import org.apache.cloudstack.api.command.admin.router.*; import org.apache.cloudstack.api.command.admin.storage.*; -import org.apache.cloudstack.api.command.admin.swift.*; import org.apache.cloudstack.api.command.admin.systemvm.*; -import org.apache.cloudstack.api.command.admin.template.*; import org.apache.cloudstack.api.command.admin.usage.*; import org.apache.cloudstack.api.command.admin.user.*; -import org.apache.cloudstack.api.command.admin.vlan.*; -import org.apache.cloudstack.api.command.admin.vm.*; import org.apache.cloudstack.api.command.admin.vpc.*; -import org.apache.cloudstack.api.command.admin.zone.*; -import org.apache.cloudstack.api.command.user.account.*; -import org.apache.cloudstack.api.command.user.address.*; import org.apache.cloudstack.api.command.user.autoscale.*; -import org.apache.cloudstack.api.command.user.config.*; -import org.apache.cloudstack.api.command.user.event.*; import org.apache.cloudstack.api.command.user.firewall.*; -import org.apache.cloudstack.api.command.user.guest.*; import org.apache.cloudstack.api.command.user.iso.*; -import org.apache.cloudstack.api.command.user.job.*; import org.apache.cloudstack.api.command.user.loadbalancer.*; import org.apache.cloudstack.api.command.user.nat.*; import org.apache.cloudstack.api.command.user.network.*; -import org.apache.cloudstack.api.command.user.offering.*; import org.apache.cloudstack.api.command.user.project.*; -import org.apache.cloudstack.api.command.user.region.*; import org.apache.cloudstack.api.command.user.resource.*; import org.apache.cloudstack.api.command.user.securitygroup.*; import org.apache.cloudstack.api.command.user.snapshot.*; -import org.apache.cloudstack.api.command.user.ssh.*; -import org.apache.cloudstack.api.command.user.tag.*; import org.apache.cloudstack.api.command.user.template.*; import org.apache.cloudstack.api.command.user.vm.*; -import org.apache.cloudstack.api.command.user.vmgroup.*; import org.apache.cloudstack.api.command.user.volume.*; import org.apache.cloudstack.api.command.user.vpc.*; import org.apache.cloudstack.api.command.user.vpn.*; -import org.apache.cloudstack.api.command.user.zone.*; import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; +import org.apache.cloudstack.affinity.AffinityGroupProcessor; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; + +import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.DeleteAffinityGroupCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupTypesCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.UpdateVMAffinityGroupCmd; import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; @@ -140,7 +119,6 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; @@ -175,7 +153,6 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.*; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload.Mode; -import com.cloud.storage.dao.*; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; @@ -193,11 +170,7 @@ import com.cloud.utils.EnumUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; -import com.cloud.utils.ReflectUtil; import com.cloud.utils.Ternary; -import com.cloud.utils.component.Adapter; -import com.cloud.utils.component.AdapterBase; -import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ComponentLifecycle; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -214,10 +187,6 @@ import com.cloud.vm.dao.*; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; -import org.apache.cloudstack.api.command.admin.account.*; import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; @@ -228,12 +197,8 @@ import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.domain.*; -import org.apache.cloudstack.api.command.admin.host.*; import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.network.*; -import org.apache.cloudstack.api.command.admin.offering.*; import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; @@ -241,22 +206,15 @@ import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; -import org.apache.cloudstack.api.command.admin.resource.*; -import org.apache.cloudstack.api.command.admin.router.*; -import org.apache.cloudstack.api.command.admin.storage.*; import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; -import org.apache.cloudstack.api.command.admin.systemvm.*; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; -import org.apache.cloudstack.api.command.admin.usage.*; -import org.apache.cloudstack.api.command.admin.user.*; import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -import org.apache.cloudstack.api.command.admin.vpc.*; import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.MarkDefaultZoneForAccountCmd; @@ -268,29 +226,19 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd; import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; -import org.apache.cloudstack.api.command.user.autoscale.*; import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd; import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; -import org.apache.cloudstack.api.command.user.firewall.*; import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd; import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd; -import org.apache.cloudstack.api.command.user.iso.*; import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.api.command.user.loadbalancer.*; -import org.apache.cloudstack.api.command.user.nat.*; -import org.apache.cloudstack.api.command.user.network.*; import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import org.apache.cloudstack.api.command.user.project.*; import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; import org.apache.cloudstack.api.command.user.region.ha.gslb.*; -import org.apache.cloudstack.api.command.user.resource.*; -import org.apache.cloudstack.api.command.user.securitygroup.*; -import org.apache.cloudstack.api.command.user.snapshot.*; import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd; @@ -298,8 +246,6 @@ import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd; import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd; import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; -import org.apache.cloudstack.api.command.user.template.*; -import org.apache.cloudstack.api.command.user.vm.*; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; @@ -308,27 +254,10 @@ import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd; -import org.apache.cloudstack.api.command.user.volume.*; -import org.apache.cloudstack.api.command.user.vpc.*; -import org.apache.cloudstack.api.command.user.vpn.*; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.lang.reflect.Field; -import java.net.*; -import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -466,6 +395,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject ClusterManager _clusterMgr; private String _hashKey = null; + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; + + @Inject + protected List _affinityProcessors; + public ManagementServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP); } @@ -824,6 +759,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ExcludeList excludes = new ExcludeList(); excludes.addHost(srcHostId); + // call affinitygroup chain + long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + + if (vmGroupCount > 0) { + for (AffinityGroupProcessor processor : _affinityProcessors) { + processor.process(vmProfile, plan, excludes); + } + } + for (HostAllocator allocator : _hostAllocators) { suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false); if (suitableHosts != null && !suitableHosts.isEmpty()) { @@ -2308,6 +2252,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(DeleteAffinityGroupCmd.class); cmdList.add(ListAffinityGroupsCmd.class); cmdList.add(UpdateVMAffinityGroupCmd.class); + cmdList.add(ListAffinityGroupTypesCmd.class); + return cmdList; } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index ca158f1995d..8b6ad3b8829 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2284,10 +2284,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } // check that the affinity groups exist - for (Long affinityGroupId : affinityGroupIdList) { - AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId); - if (ag == null) { - throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + if (affinityGroupIdList != null) { + for (Long affinityGroupId : affinityGroupIdList) { + AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId); + if (ag == null) { + throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + } } } @@ -2582,7 +2584,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _securityGroupMgr.addInstanceToGroups(vm.getId(), securityGroupIdList); - _affinityGroupVMMapDao.updateMap(vm.getId(), affinityGroupIdList); + if (affinityGroupIdList != null && !affinityGroupIdList.isEmpty()) { + _affinityGroupVMMapDao.updateMap(vm.getId(), affinityGroupIdList); + } return vm; } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 08c6e7c1208..40725314f46 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -703,8 +703,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac try { dest = _dpMgr.planDeployment(vmProfile, plan, avoids); } catch (AffinityConflictException e2) { - // TODO Auto-generated catch block - e2.printStackTrace(); + s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2); + throw new CloudRuntimeException( + "Unable to create deployment, affinity rules associted to the VM conflict"); + } if (dest == null) { @@ -718,6 +720,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } + if (dest != null) { + avoids.addHost(dest.getHost().getId()); + journal.record("Deployment found ", vmProfile, dest); + } + long destHostId = dest.getHost().getId(); vm.setPodId(dest.getPod().getId()); Long cluster_id = dest.getCluster().getId(); @@ -1486,25 +1493,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac DeployDestination dest = null; while (true) { - for (DeploymentPlanner planner : _planners) { - if (planner.canHandle(profile, plan, excludes)) { - dest = planner.plan(profile, plan, excludes); - } else { - continue; - } - if (dest != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Planner " + planner + " found " + dest + " for migrating to."); - } - break; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Planner " + planner + " was unable to find anything."); - } + try { + dest = _dpMgr.planDeployment(profile, plan, excludes); + } catch (AffinityConflictException e2) { + s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2); + throw new CloudRuntimeException( + "Unable to create deployment, affinity rules associted to the VM conflict"); } - if (dest == null) { + if (dest != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found destination " + dest + " for migrating to."); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find destination for migrating the vm " + profile); + } throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId()); } diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index 853602231d1..b22ed837533 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -16,6 +16,7 @@ import org.apache.log4j.Logger; import org.springframework.context.annotation.Primary; +import com.cloud.deploy.DeploymentPlanner; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -77,28 +78,22 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro //validate the affinityGroupType - String internalAffinityType = null; Map typeProcessorMap = getAffinityTypeToProcessorMap(); if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) { if (!typeProcessorMap.containsKey(affinityGroupType)) { throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + affinityGroupType); - } else { - AffinityGroupProcessor processor = typeProcessorMap.get(affinityGroupType); - internalAffinityType = processor.getType(); } } else { throw new InvalidParameterValueException( "Unable to create affinity group, no Affinity Group Types configured"); } - if (internalAffinityType == null) { - throw new InvalidParameterValueException( - "Unable to create affinity group, Affinity Group Processor for type " + affinityGroupType - + "is wrongly configured"); + if (domainId == null) { + domainId = owner.getDomainId(); } - AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, internalAffinityType, description, domainId, + AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, domainId, owner.getId()); _affinityGroupDao.persist(group); @@ -174,8 +169,6 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro vmInstanceSearch.and("instanceId", vmInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); SearchBuilder groupSearch = _affinityGroupDao.createSearchBuilder(); - groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch.entity() - .getAffinityGroupId(), JoinBuilder.JoinType.INNER); SearchCriteria sc = groupSearch.create(); @@ -207,6 +200,8 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro } _accountMgr.checkAccess(caller, null, true, userVM); // add join to affinity_groups_vm_map + groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch + .entity().getAffinityGroupId(), JoinBuilder.JoinType.INNER); sc.setJoinParameters("vmInstanceSearch", "instanceId", vmId); } @@ -222,11 +217,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro if (componentMap.size() > 0) { for (Entry entry : componentMap.entrySet()) { - Map params = entry.getValue().getConfigParams(); - if (params.containsKey("type")) { - types.add((String) params.get("type")); - } - + types.add(entry.getValue().getType()); } } @@ -235,17 +226,13 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro protected Map getAffinityTypeToProcessorMap() { Map typeProcessorMap = new HashMap(); - Map componentMap = ComponentContext.getComponentsOfType(AffinityGroupProcessor.class); + Map componentMap = ComponentContext + .getComponentsOfType(AffinityGroupProcessor.class); if (componentMap.size() > 0) { for (Entry entry : componentMap.entrySet()) { - Map params = entry.getValue().getConfigParams(); - if (params.containsKey("type")) { - typeProcessorMap.put((String) params.get("type"), entry.getValue()); - } - + typeProcessorMap.put(entry.getValue().getType(), entry.getValue()); } - } return typeProcessorMap; } diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java index 5401b4aef70..f84e4c351aa 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.InternalIdentity; @Entity @Table(name = ("affinity_group_vm_map")) -@SecondaryTables({ @SecondaryTable(name = "affinity_group", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "affinity_group_id", referencedColumnName = "id") }) }) public class AffinityGroupVMMapVO implements InternalIdentity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -43,9 +42,6 @@ public class AffinityGroupVMMapVO implements InternalIdentity { @Column(name = "instance_id") private long instanceId; - @Column(name = "name", table = "affinity_group", insertable = false, updatable = false) - private String groupName; - public AffinityGroupVMMapVO() { } @@ -67,8 +63,4 @@ public class AffinityGroupVMMapVO implements InternalIdentity { return instanceId; } - - public String getGroupName() { - return groupName; - } } diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java index ea315ac595c..b17d0b38383 100644 --- a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java @@ -76,12 +76,12 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase groupSearch = _affinityGroupDao.createSearchBuilder(); groupSearch.and("type", groupSearch.entity().getType(), SearchCriteria.Op.EQ); - ListByVmIdType.join("groupSearch", groupSearch, ListByVmIdType.entity().getAffinityGroupId(), groupSearch - .entity().getId(), JoinType.INNER); + + ListByVmIdType = createSearchBuilder(); + ListByVmIdType.and("instanceId", ListByVmIdType.entity().getInstanceId(), SearchCriteria.Op.EQ); + ListByVmIdType.join("groupSearch", groupSearch, ListByVmIdType.entity().getAffinityGroupId(), groupSearch.entity().getId(), JoinType.INNER); ListByVmIdType.done(); CountSGForVm = createSearchBuilder(Long.class); @@ -145,7 +145,7 @@ public class AffinityGroupVMMapDaoImpl extends GenericDaoBase sc = ListByVmIdType.create(); sc.setParameters("instanceId", instanceId); sc.setJoinParameters("groupSearch", "type", type); - return customSearch(sc, null).get(0); + return findOneBy(sc); } @Override