1717package com .cloud .deploy ;
1818
1919import java .util .ArrayList ;
20+ import java .util .Collections ;
21+ import java .util .Comparator ;
2022import java .util .HashMap ;
2123import java .util .List ;
2224import java .util .Map ;
4446import com .cloud .dc .dao .DataCenterDao ;
4547import com .cloud .dc .dao .HostPodDao ;
4648import com .cloud .exception .InsufficientServerCapacityException ;
49+ import com .cloud .gpu .GPU ;
50+ import com .cloud .gpu .dao .HostGpuGroupsDao ;
51+ import com .cloud .host .Host ;
4752import com .cloud .host .dao .HostDao ;
53+ import com .cloud .host .dao .HostTagsDao ;
4854import com .cloud .hypervisor .Hypervisor .HypervisorType ;
4955import com .cloud .offering .ServiceOffering ;
56+ import com .cloud .service .dao .ServiceOfferingDetailsDao ;
5057import com .cloud .storage .StorageManager ;
5158import com .cloud .storage .dao .DiskOfferingDao ;
5259import com .cloud .storage .dao .GuestOSCategoryDao ;
@@ -102,9 +109,16 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
102109 DataStoreManager dataStoreMgr ;
103110 @ Inject
104111 protected ClusterDetailsDao _clusterDetailsDao ;
112+ @ Inject
113+ protected ServiceOfferingDetailsDao _serviceOfferingDetailsDao ;
114+ @ Inject
115+ protected HostGpuGroupsDao _hostGpuGroupsDao ;
116+ @ Inject
117+ protected HostTagsDao _hostTagsDao ;
105118
106119 protected String _allocationAlgorithm = "random" ;
107120 protected String _globalDeploymentPlanner = "FirstFitPlanner" ;
121+ protected String [] _implicitHostTags ;
108122
109123 @ Override
110124 public List <Long > orderClusters (VirtualMachineProfile vmProfile , DeploymentPlan plan , ExcludeList avoid ) throws InsufficientServerCapacityException {
@@ -131,7 +145,6 @@ public List<Long> orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan
131145 clusterList .add (clusterIdSpecified );
132146 removeClustersCrossingThreshold (clusterList , avoid , vmProfile , plan );
133147 }
134- return clusterList ;
135148 } else {
136149 s_logger .debug ("The specified cluster cannot be found, returning." );
137150 avoid .addCluster (plan .getClusterId ());
@@ -152,7 +165,6 @@ public List<Long> orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan
152165 avoid .addPod (plan .getPodId ());
153166 }
154167 }
155- return clusterList ;
156168 } else {
157169 s_logger .debug ("The specified Pod cannot be found, returning." );
158170 avoid .addPod (plan .getPodId ());
@@ -164,13 +176,44 @@ public List<Long> orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan
164176 boolean applyAllocationAtPods = Boolean .parseBoolean (_configDao .getValue (Config .ApplyAllocationAlgorithmToPods .key ()));
165177 if (applyAllocationAtPods ) {
166178 //start scan at all pods under this zone.
167- return scanPodsForDestination (vmProfile , plan , avoid );
179+ clusterList = scanPodsForDestination (vmProfile , plan , avoid );
168180 } else {
169181 //start scan at clusters under this zone.
170- return scanClustersForDestinationInZoneOrPod (plan .getDataCenterId (), true , vmProfile , plan , avoid );
182+ clusterList = scanClustersForDestinationInZoneOrPod (plan .getDataCenterId (), true , vmProfile , plan , avoid );
171183 }
172184 }
173185
186+ if (clusterList != null && !clusterList .isEmpty ()) {
187+ ServiceOffering offering = vmProfile .getServiceOffering ();
188+ // In case of non-GPU VMs, protect GPU enabled Hosts and prefer VM deployment on non-GPU Hosts.
189+ if ((_serviceOfferingDetailsDao .findDetail (offering .getId (), GPU .Keys .vgpuType .toString ()) == null ) && !(_hostGpuGroupsDao .listHostIds ().isEmpty ())) {
190+ int requiredCpu = offering .getCpu () * offering .getSpeed ();
191+ long requiredRam = offering .getRamSize () * 1024L * 1024L ;
192+ reorderClustersBasedOnImplicitTags (clusterList , requiredCpu , requiredRam );
193+ }
194+ }
195+ return clusterList ;
196+ }
197+
198+ private void reorderClustersBasedOnImplicitTags (List <Long > clusterList , int requiredCpu , long requiredRam ) {
199+ final HashMap <Long , Long > UniqueTagsInClusterMap = new HashMap <Long , Long >();
200+ Long uniqueTags ;
201+ for (Long clusterId : clusterList ) {
202+ uniqueTags = (long ) 0 ;
203+ List <Long > hostList = _capacityDao .listHostsWithEnoughCapacity (requiredCpu , requiredRam , clusterId , Host .Type .Routing .toString ());
204+ if (!hostList .isEmpty () && _implicitHostTags .length > 0 ) {
205+ uniqueTags = new Long (_hostTagsDao .getDistinctImplicitHostTags (hostList , _implicitHostTags ).size ());
206+ }
207+ UniqueTagsInClusterMap .put (clusterId , uniqueTags );
208+ }
209+ Collections .sort (clusterList , new Comparator <Long >() {
210+ @ Override
211+ public int compare (Long o1 , Long o2 ) {
212+ Long t1 = UniqueTagsInClusterMap .get (o1 );
213+ Long t2 = UniqueTagsInClusterMap .get (o2 );
214+ return t1 .compareTo (t2 );
215+ }
216+ });
174217 }
175218
176219 private List <Long > scanPodsForDestination (VirtualMachineProfile vmProfile , DeploymentPlan plan , ExcludeList avoid ) {
@@ -504,6 +547,10 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
504547 super .configure (name , params );
505548 _allocationAlgorithm = _configDao .getValue (Config .VmAllocationAlgorithm .key ());
506549 _globalDeploymentPlanner = _configDao .getValue (Config .VmDeploymentPlanner .key ());
550+ String configValue ;
551+ if ((configValue = _configDao .getValue (Config .ImplicitHostTags .key ())) != null ) {
552+ _implicitHostTags = configValue .trim ().split ("\\ s*,\\ s*" );
553+ }
507554 return true ;
508555 }
509556
0 commit comments