mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-6650: Reorder Cluster list in deployment planner to protect
GPU enabled hosts from non-GPU VM deployment. Cluster reordering is based on the number of unique host tags in a cluster, cluster with most number of unique host tags will put at the end of list. Hosts with GPU capability will get tagged with implicit tags defined by global config param 'implicit.host.tags' at the time os host discovery. Also added FirstFitPlannerTest unit test file.
This commit is contained in:
parent
0db0e5e3cc
commit
176e0d47bb
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package com.cloud.agent.api;
|
package com.cloud.agent.api;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
@ -39,6 +41,7 @@ public class StartupRoutingCommand extends StartupCommand {
|
|||||||
String pool;
|
String pool;
|
||||||
HypervisorType hypervisorType;
|
HypervisorType hypervisorType;
|
||||||
Map<String, String> hostDetails; //stuff like host os, cpu capabilities
|
Map<String, String> hostDetails; //stuff like host os, cpu capabilities
|
||||||
|
List<String> hostTags = new ArrayList<String>();
|
||||||
String hypervisorVersion;
|
String hypervisorVersion;
|
||||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = new HashMap<String, HashMap<String, VgpuTypesInfo>>();
|
||||||
|
|
||||||
@ -162,6 +165,14 @@ public class StartupRoutingCommand extends StartupCommand {
|
|||||||
this.hypervisorVersion = hypervisorVersion;
|
this.hypervisorVersion = hypervisorVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getHostTags() {
|
||||||
|
return hostTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostTags(String hostTag) {
|
||||||
|
this.hostTags.add(hostTag);
|
||||||
|
}
|
||||||
|
|
||||||
public HashMap<String, HashMap<String, VgpuTypesInfo>> getGpuGroupDetails() {
|
public HashMap<String, HashMap<String, VgpuTypesInfo>> getGpuGroupDetails() {
|
||||||
return groupDetails;
|
return groupDetails;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,4 +27,6 @@ public interface HostTagsDao extends GenericDao<HostTagVO, Long> {
|
|||||||
|
|
||||||
List<String> gethostTags(long hostId);
|
List<String> gethostTags(long hostId);
|
||||||
|
|
||||||
|
List<String> getDistinctImplicitHostTags(List<Long> hostIds, String[] implicitHostTags);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,19 +25,28 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import com.cloud.host.HostTagVO;
|
import com.cloud.host.HostTagVO;
|
||||||
import com.cloud.utils.db.GenericDaoBase;
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.GenericSearchBuilder;
|
||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
import com.cloud.utils.db.TransactionLegacy;
|
import com.cloud.utils.db.TransactionLegacy;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Func;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Local(value = HostTagsDao.class)
|
@Local(value = HostTagsDao.class)
|
||||||
public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements HostTagsDao {
|
public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements HostTagsDao {
|
||||||
protected final SearchBuilder<HostTagVO> HostSearch;
|
protected final SearchBuilder<HostTagVO> HostSearch;
|
||||||
|
protected final GenericSearchBuilder<HostTagVO, String> DistinctImplictTagsSearch;
|
||||||
|
|
||||||
public HostTagsDaoImpl() {
|
public HostTagsDaoImpl() {
|
||||||
HostSearch = createSearchBuilder();
|
HostSearch = createSearchBuilder();
|
||||||
HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
|
HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
|
||||||
HostSearch.done();
|
HostSearch.done();
|
||||||
|
|
||||||
|
DistinctImplictTagsSearch = createSearchBuilder(String.class);
|
||||||
|
DistinctImplictTagsSearch.select(null, Func.DISTINCT, DistinctImplictTagsSearch.entity().getTag());
|
||||||
|
DistinctImplictTagsSearch.and("hostIds", DistinctImplictTagsSearch.entity().getHostId(), SearchCriteria.Op.IN);
|
||||||
|
DistinctImplictTagsSearch.and("implicitTags", DistinctImplictTagsSearch.entity().getTag(), SearchCriteria.Op.IN);
|
||||||
|
DistinctImplictTagsSearch.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,6 +63,14 @@ public class HostTagsDaoImpl extends GenericDaoBase<HostTagVO, Long> implements
|
|||||||
return hostTags;
|
return hostTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getDistinctImplicitHostTags(List<Long> hostIds, String[] implicitHostTags) {
|
||||||
|
SearchCriteria<String> sc = DistinctImplictTagsSearch.create();
|
||||||
|
sc.setParameters("hostIds", hostIds.toArray(new Object[hostIds.size()]));
|
||||||
|
sc.setParameters("implicitTags", (Object[])implicitHostTags);
|
||||||
|
return customSearch(sc, null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void persist(long hostId, List<String> hostTags) {
|
public void persist(long hostId, List<String> hostTags) {
|
||||||
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||||
|
|||||||
@ -69,8 +69,10 @@ import com.cloud.deploy.DataCenterDeployment;
|
|||||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||||
import com.cloud.deploy.ImplicitDedicationPlanner;
|
import com.cloud.deploy.ImplicitDedicationPlanner;
|
||||||
import com.cloud.exception.InsufficientServerCapacityException;
|
import com.cloud.exception.InsufficientServerCapacityException;
|
||||||
|
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.host.dao.HostTagsDao;
|
||||||
import com.cloud.resource.ResourceManager;
|
import com.cloud.resource.ResourceManager;
|
||||||
import com.cloud.service.ServiceOfferingVO;
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
import com.cloud.service.dao.ServiceOfferingDao;
|
import com.cloud.service.dao.ServiceOfferingDao;
|
||||||
@ -467,6 +469,16 @@ public class ImplicitPlannerTest {
|
|||||||
return Mockito.mock(HostDao.class);
|
return Mockito.mock(HostDao.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostTagsDao hostTagsDao() {
|
||||||
|
return Mockito.mock(HostTagsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostGpuGroupsDao hostGpuGroupsDao() {
|
||||||
|
return Mockito.mock(HostGpuGroupsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DataCenterDao dcDao() {
|
public DataCenterDao dcDao() {
|
||||||
return Mockito.mock(DataCenterDao.class);
|
return Mockito.mock(DataCenterDao.class);
|
||||||
|
|||||||
@ -84,6 +84,9 @@ public class XenServer620SP1Resource extends XenServer620Resource {
|
|||||||
try {
|
try {
|
||||||
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = getGPUGroupDetails(conn);
|
HashMap<String, HashMap<String, VgpuTypesInfo>> groupDetails = getGPUGroupDetails(conn);
|
||||||
cmd.setGpuGroupDetails(groupDetails);
|
cmd.setGpuGroupDetails(groupDetails);
|
||||||
|
if (groupDetails != null && !groupDetails.isEmpty()) {
|
||||||
|
cmd.setHostTags("GPU");
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (s_logger.isDebugEnabled()) {
|
if (s_logger.isDebugEnabled()) {
|
||||||
s_logger.debug("Error while getting GPU device info from host " + cmd.getName(), e);
|
s_logger.debug("Error while getting GPU device info from host " + cmd.getName(), e);
|
||||||
|
|||||||
@ -1360,6 +1360,14 @@ public enum Config {
|
|||||||
"false",
|
"false",
|
||||||
"Deploys a VM per zone to manage secondary storage if true, otherwise secondary storage is mounted on management server",
|
"Deploys a VM per zone to manage secondary storage if true, otherwise secondary storage is mounted on management server",
|
||||||
null),
|
null),
|
||||||
|
ImplicitHostTags(
|
||||||
|
"Hidden",
|
||||||
|
ManagementServer.class,
|
||||||
|
String.class,
|
||||||
|
"implicit.host.tags",
|
||||||
|
"GPU",
|
||||||
|
"Tag hosts at the time of host disovery based on the host properties/capabilities",
|
||||||
|
null),
|
||||||
CreatePoolsInPod(
|
CreatePoolsInPod(
|
||||||
"Hidden",
|
"Hidden",
|
||||||
ManagementServer.class,
|
ManagementServer.class,
|
||||||
|
|||||||
@ -17,6 +17,8 @@
|
|||||||
package com.cloud.deploy;
|
package com.cloud.deploy;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -44,9 +46,14 @@ import com.cloud.dc.dao.ClusterDao;
|
|||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.dc.dao.HostPodDao;
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
import com.cloud.exception.InsufficientServerCapacityException;
|
import com.cloud.exception.InsufficientServerCapacityException;
|
||||||
|
import com.cloud.gpu.GPU;
|
||||||
|
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||||
|
import com.cloud.host.Host;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.host.dao.HostTagsDao;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.offering.ServiceOffering;
|
import com.cloud.offering.ServiceOffering;
|
||||||
|
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||||
import com.cloud.storage.StorageManager;
|
import com.cloud.storage.StorageManager;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||||
@ -102,9 +109,16 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
|
|||||||
DataStoreManager dataStoreMgr;
|
DataStoreManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
protected ClusterDetailsDao _clusterDetailsDao;
|
protected ClusterDetailsDao _clusterDetailsDao;
|
||||||
|
@Inject
|
||||||
|
protected ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
|
||||||
|
@Inject
|
||||||
|
protected HostGpuGroupsDao _hostGpuGroupsDao;
|
||||||
|
@Inject
|
||||||
|
protected HostTagsDao _hostTagsDao;
|
||||||
|
|
||||||
protected String _allocationAlgorithm = "random";
|
protected String _allocationAlgorithm = "random";
|
||||||
protected String _globalDeploymentPlanner = "FirstFitPlanner";
|
protected String _globalDeploymentPlanner = "FirstFitPlanner";
|
||||||
|
protected String[] _implicitHostTags;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Long> orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException {
|
public List<Long> orderClusters(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException {
|
||||||
@ -131,7 +145,6 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
|
|||||||
clusterList.add(clusterIdSpecified);
|
clusterList.add(clusterIdSpecified);
|
||||||
removeClustersCrossingThreshold(clusterList, avoid, vmProfile, plan);
|
removeClustersCrossingThreshold(clusterList, avoid, vmProfile, plan);
|
||||||
}
|
}
|
||||||
return clusterList;
|
|
||||||
} else {
|
} else {
|
||||||
s_logger.debug("The specified cluster cannot be found, returning.");
|
s_logger.debug("The specified cluster cannot be found, returning.");
|
||||||
avoid.addCluster(plan.getClusterId());
|
avoid.addCluster(plan.getClusterId());
|
||||||
@ -152,7 +165,6 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
|
|||||||
avoid.addPod(plan.getPodId());
|
avoid.addPod(plan.getPodId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return clusterList;
|
|
||||||
} else {
|
} else {
|
||||||
s_logger.debug("The specified Pod cannot be found, returning.");
|
s_logger.debug("The specified Pod cannot be found, returning.");
|
||||||
avoid.addPod(plan.getPodId());
|
avoid.addPod(plan.getPodId());
|
||||||
@ -164,13 +176,44 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
|
|||||||
boolean applyAllocationAtPods = Boolean.parseBoolean(_configDao.getValue(Config.ApplyAllocationAlgorithmToPods.key()));
|
boolean applyAllocationAtPods = Boolean.parseBoolean(_configDao.getValue(Config.ApplyAllocationAlgorithmToPods.key()));
|
||||||
if (applyAllocationAtPods) {
|
if (applyAllocationAtPods) {
|
||||||
//start scan at all pods under this zone.
|
//start scan at all pods under this zone.
|
||||||
return scanPodsForDestination(vmProfile, plan, avoid);
|
clusterList = scanPodsForDestination(vmProfile, plan, avoid);
|
||||||
} else {
|
} else {
|
||||||
//start scan at clusters under this zone.
|
//start scan at clusters under this zone.
|
||||||
return scanClustersForDestinationInZoneOrPod(plan.getDataCenterId(), true, vmProfile, plan, avoid);
|
clusterList = scanClustersForDestinationInZoneOrPod(plan.getDataCenterId(), true, vmProfile, plan, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clusterList != null && !clusterList.isEmpty()) {
|
||||||
|
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||||
|
// In case of non-GPU VMs, protect GPU enabled Hosts and prefer VM deployment on non-GPU Hosts.
|
||||||
|
if ((_serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null) && !(_hostGpuGroupsDao.listHostIds().isEmpty())) {
|
||||||
|
int requiredCpu = offering.getCpu() * offering.getSpeed();
|
||||||
|
long requiredRam = offering.getRamSize() * 1024L * 1024L;
|
||||||
|
reorderClustersBasedOnImplicitTags(clusterList, requiredCpu, requiredRam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clusterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reorderClustersBasedOnImplicitTags(List<Long> clusterList, int requiredCpu, long requiredRam) {
|
||||||
|
final HashMap<Long, Long> UniqueTagsInClusterMap = new HashMap<Long, Long>();
|
||||||
|
Long uniqueTags;
|
||||||
|
for (Long clusterId : clusterList) {
|
||||||
|
uniqueTags = (long) 0;
|
||||||
|
List<Long> hostList = _capacityDao.listHostsWithEnoughCapacity(requiredCpu, requiredRam, clusterId, Host.Type.Routing.toString());
|
||||||
|
if (!hostList.isEmpty() && _implicitHostTags.length > 0) {
|
||||||
|
uniqueTags = new Long(_hostTagsDao.getDistinctImplicitHostTags(hostList, _implicitHostTags).size());
|
||||||
|
}
|
||||||
|
UniqueTagsInClusterMap.put(clusterId, uniqueTags);
|
||||||
|
}
|
||||||
|
Collections.sort(clusterList, new Comparator<Long>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Long o1, Long o2) {
|
||||||
|
Long t1 = UniqueTagsInClusterMap.get(o1);
|
||||||
|
Long t2 = UniqueTagsInClusterMap.get(o2);
|
||||||
|
return t1.compareTo(t2);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Long> scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) {
|
private List<Long> scanPodsForDestination(VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoid) {
|
||||||
@ -504,6 +547,10 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla
|
|||||||
super.configure(name, params);
|
super.configure(name, params);
|
||||||
_allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key());
|
_allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key());
|
||||||
_globalDeploymentPlanner = _configDao.getValue(Config.VmDeploymentPlanner.key());
|
_globalDeploymentPlanner = _configDao.getValue(Config.VmDeploymentPlanner.key());
|
||||||
|
String configValue;
|
||||||
|
if ((configValue = _configDao.getValue(Config.ImplicitHostTags.key())) != null) {
|
||||||
|
_implicitHostTags = configValue.trim().split("\\s*,\\s*");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1645,6 +1645,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (startup instanceof StartupRoutingCommand) {
|
||||||
|
StartupRoutingCommand ssCmd = ((StartupRoutingCommand)startup);
|
||||||
|
List<String> implicitHostTags = ssCmd.getHostTags();
|
||||||
|
if (!implicitHostTags.isEmpty()) {
|
||||||
|
if (hostTags == null) {
|
||||||
|
hostTags = _hostTagsDao.gethostTags(host.getId());
|
||||||
|
}
|
||||||
|
if (hostTags != null) {
|
||||||
|
implicitHostTags.removeAll(hostTags);
|
||||||
|
hostTags.addAll(implicitHostTags);
|
||||||
|
} else {
|
||||||
|
hostTags = implicitHostTags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
host.setDataCenterId(dc.getId());
|
host.setDataCenterId(dc.getId());
|
||||||
host.setPodId(podId);
|
host.setPodId(podId);
|
||||||
host.setClusterId(clusterId);
|
host.setClusterId(clusterId);
|
||||||
|
|||||||
@ -76,7 +76,9 @@ import com.cloud.deploy.PlannerHostReservationVO;
|
|||||||
import com.cloud.deploy.dao.PlannerHostReservationDao;
|
import com.cloud.deploy.dao.PlannerHostReservationDao;
|
||||||
import com.cloud.exception.AffinityConflictException;
|
import com.cloud.exception.AffinityConflictException;
|
||||||
import com.cloud.exception.InsufficientServerCapacityException;
|
import com.cloud.exception.InsufficientServerCapacityException;
|
||||||
|
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.host.dao.HostTagsDao;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.resource.ResourceManager;
|
import com.cloud.resource.ResourceManager;
|
||||||
import com.cloud.service.ServiceOfferingVO;
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
@ -239,6 +241,11 @@ public class DeploymentPlanningManagerImplTest {
|
|||||||
return Mockito.mock(VirtualMachineProfileImpl.class);
|
return Mockito.mock(VirtualMachineProfileImpl.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostTagsDao hostTagsDao() {
|
||||||
|
return Mockito.mock(HostTagsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ClusterDetailsDao clusterDetailsDao() {
|
public ClusterDetailsDao clusterDetailsDao() {
|
||||||
return Mockito.mock(ClusterDetailsDao.class);
|
return Mockito.mock(ClusterDetailsDao.class);
|
||||||
@ -389,6 +396,11 @@ public class DeploymentPlanningManagerImplTest {
|
|||||||
return Mockito.mock(AffinityGroupService.class);
|
return Mockito.mock(AffinityGroupService.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostGpuGroupsDao hostGpuGroupsDap() {
|
||||||
|
return Mockito.mock(HostGpuGroupsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
public static class Library implements TypeFilter {
|
public static class Library implements TypeFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
387
server/test/com/cloud/vm/FirstFitPlannerTest.java
Normal file
387
server/test/com/cloud/vm/FirstFitPlannerTest.java
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you 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.cloud.vm;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.context.CallContext;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
|
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Matchers;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
|
||||||
|
import com.cloud.capacity.Capacity;
|
||||||
|
import com.cloud.capacity.CapacityManager;
|
||||||
|
import com.cloud.capacity.dao.CapacityDao;
|
||||||
|
import com.cloud.configuration.Config;
|
||||||
|
import com.cloud.dc.ClusterDetailsDao;
|
||||||
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
|
import com.cloud.deploy.DataCenterDeployment;
|
||||||
|
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||||
|
import com.cloud.deploy.FirstFitPlanner;
|
||||||
|
import com.cloud.exception.InsufficientServerCapacityException;
|
||||||
|
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.host.dao.HostTagsDao;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
|
import com.cloud.service.dao.ServiceOfferingDao;
|
||||||
|
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||||
|
import com.cloud.storage.StorageManager;
|
||||||
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
|
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.user.AccountManager;
|
||||||
|
import com.cloud.user.AccountVO;
|
||||||
|
import com.cloud.utils.Pair;
|
||||||
|
import com.cloud.utils.component.ComponentContext;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class FirstFitPlannerTest {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FirstFitPlanner planner = new FirstFitPlanner();
|
||||||
|
@Inject
|
||||||
|
DataCenterDao dcDao;
|
||||||
|
@Inject
|
||||||
|
ClusterDao clusterDao;
|
||||||
|
@Inject
|
||||||
|
UserVmDao vmDao;
|
||||||
|
@Inject
|
||||||
|
ConfigurationDao configDao;
|
||||||
|
@Inject
|
||||||
|
CapacityDao capacityDao;
|
||||||
|
@Inject
|
||||||
|
AccountManager accountMgr;
|
||||||
|
@Inject
|
||||||
|
ServiceOfferingDao serviceOfferingDao;
|
||||||
|
@Inject
|
||||||
|
ServiceOfferingDetailsDao serviceOfferingDetailsDao;
|
||||||
|
@Inject
|
||||||
|
HostGpuGroupsDao hostGpuGroupsDao;
|
||||||
|
@Inject
|
||||||
|
HostTagsDao hostTagsDao;
|
||||||
|
|
||||||
|
private static long domainId = 1L;
|
||||||
|
long dataCenterId = 1L;
|
||||||
|
long accountId = 1L;
|
||||||
|
long offeringId = 12L;
|
||||||
|
int noOfCpusInOffering = 1;
|
||||||
|
int cpuSpeedInOffering = 500;
|
||||||
|
int ramInOffering = 512;
|
||||||
|
AccountVO acct = new AccountVO(accountId);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
when(configDao.getValue(Mockito.anyString())).thenReturn(null);
|
||||||
|
when(configDao.getValue(Config.ImplicitHostTags.key())).thenReturn("GPU");
|
||||||
|
|
||||||
|
ComponentContext.initComponentsLifeCycle();
|
||||||
|
acct.setType(Account.ACCOUNT_TYPE_ADMIN);
|
||||||
|
acct.setAccountName("user1");
|
||||||
|
acct.setDomainId(domainId);
|
||||||
|
acct.setId(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
CallContext.unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkClusterReorderingBasedOnImplicitHostTags() throws InsufficientServerCapacityException {
|
||||||
|
VirtualMachineProfileImpl vmProfile = mock(VirtualMachineProfileImpl.class);
|
||||||
|
DataCenterDeployment plan = mock(DataCenterDeployment.class);
|
||||||
|
ExcludeList avoids = mock(ExcludeList.class);
|
||||||
|
initializeForTest(vmProfile, plan, avoids);
|
||||||
|
|
||||||
|
List<Long> clusterList = planner.orderClusters(vmProfile, plan, avoids);
|
||||||
|
List<Long> reorderedClusterList = new ArrayList<Long>();
|
||||||
|
reorderedClusterList.add(4L);
|
||||||
|
reorderedClusterList.add(3L);
|
||||||
|
reorderedClusterList.add(1L);
|
||||||
|
reorderedClusterList.add(5L);
|
||||||
|
reorderedClusterList.add(6L);
|
||||||
|
reorderedClusterList.add(2L);
|
||||||
|
|
||||||
|
assertTrue("Reordered cluster list is not ownering the implict host tags", (clusterList.equals(reorderedClusterList)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeForTest(VirtualMachineProfileImpl vmProfile, DataCenterDeployment plan, ExcludeList avoids) {
|
||||||
|
DataCenterVO mockDc = mock(DataCenterVO.class);
|
||||||
|
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||||
|
UserVmVO userVm = mock(UserVmVO.class);
|
||||||
|
ServiceOfferingVO offering = mock(ServiceOfferingVO.class);
|
||||||
|
|
||||||
|
AccountVO account = mock(AccountVO.class);
|
||||||
|
when(account.getId()).thenReturn(accountId);
|
||||||
|
when(account.getAccountId()).thenReturn(accountId);
|
||||||
|
when(vmProfile.getOwner()).thenReturn(account);
|
||||||
|
when(vmProfile.getVirtualMachine()).thenReturn(vm);
|
||||||
|
when(vmProfile.getId()).thenReturn(12L);
|
||||||
|
when(vmDao.findById(12L)).thenReturn(userVm);
|
||||||
|
when(userVm.getAccountId()).thenReturn(accountId);
|
||||||
|
|
||||||
|
when(vm.getDataCenterId()).thenReturn(dataCenterId);
|
||||||
|
when(dcDao.findById(1L)).thenReturn(mockDc);
|
||||||
|
when(avoids.shouldAvoid(mockDc)).thenReturn(false);
|
||||||
|
when(plan.getDataCenterId()).thenReturn(dataCenterId);
|
||||||
|
when(plan.getClusterId()).thenReturn(null);
|
||||||
|
when(plan.getPodId()).thenReturn(null);
|
||||||
|
|
||||||
|
// Mock offering details.
|
||||||
|
when(vmProfile.getServiceOffering()).thenReturn(offering);
|
||||||
|
when(offering.getId()).thenReturn(offeringId);
|
||||||
|
when(vmProfile.getServiceOfferingId()).thenReturn(offeringId);
|
||||||
|
when(offering.getCpu()).thenReturn(noOfCpusInOffering);
|
||||||
|
when(offering.getSpeed()).thenReturn(cpuSpeedInOffering);
|
||||||
|
when(offering.getRamSize()).thenReturn(ramInOffering);
|
||||||
|
|
||||||
|
List<Long> clustersWithEnoughCapacity = new ArrayList<Long>();
|
||||||
|
clustersWithEnoughCapacity.add(1L);
|
||||||
|
clustersWithEnoughCapacity.add(2L);
|
||||||
|
clustersWithEnoughCapacity.add(3L);
|
||||||
|
clustersWithEnoughCapacity.add(4L);
|
||||||
|
clustersWithEnoughCapacity.add(5L);
|
||||||
|
clustersWithEnoughCapacity.add(6L);
|
||||||
|
|
||||||
|
when(
|
||||||
|
capacityDao.listClustersInZoneOrPodByHostCapacities(dataCenterId, noOfCpusInOffering * cpuSpeedInOffering, ramInOffering * 1024L * 1024L,
|
||||||
|
Capacity.CAPACITY_TYPE_CPU, true)).thenReturn(clustersWithEnoughCapacity);
|
||||||
|
|
||||||
|
Map<Long, Double> clusterCapacityMap = new HashMap<Long, Double>();
|
||||||
|
clusterCapacityMap.put(1L, 2048D);
|
||||||
|
clusterCapacityMap.put(2L, 2048D);
|
||||||
|
clusterCapacityMap.put(3L, 2048D);
|
||||||
|
clusterCapacityMap.put(4L, 2048D);
|
||||||
|
clusterCapacityMap.put(5L, 2048D);
|
||||||
|
clusterCapacityMap.put(6L, 2048D);
|
||||||
|
|
||||||
|
Pair<List<Long>, Map<Long, Double>> clustersOrderedByCapacity = new Pair<List<Long>, Map<Long, Double>>(clustersWithEnoughCapacity, clusterCapacityMap);
|
||||||
|
when(capacityDao.orderClustersByAggregateCapacity(dataCenterId, Capacity.CAPACITY_TYPE_CPU, true)).thenReturn(clustersOrderedByCapacity);
|
||||||
|
|
||||||
|
List<Long> disabledClusters = new ArrayList<Long>();
|
||||||
|
List<Long> clustersWithDisabledPods = new ArrayList<Long>();
|
||||||
|
when(clusterDao.listDisabledClusters(dataCenterId, null)).thenReturn(disabledClusters);
|
||||||
|
when(clusterDao.listClustersWithDisabledPods(dataCenterId)).thenReturn(clustersWithDisabledPods);
|
||||||
|
|
||||||
|
List<Long> hostList0 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList1 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList2 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList3 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList4 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList5 = new ArrayList<Long>();
|
||||||
|
List<Long> hostList6 = new ArrayList<Long>();
|
||||||
|
hostList0.add(new Long(1));
|
||||||
|
hostList1.add(new Long(10));
|
||||||
|
hostList2.add(new Long(11));
|
||||||
|
hostList3.add(new Long(12));
|
||||||
|
hostList4.add(new Long(13));
|
||||||
|
hostList5.add(new Long(14));
|
||||||
|
hostList6.add(new Long(15));
|
||||||
|
String[] implicitHostTags = {"GPU"};
|
||||||
|
int ramInBytes = ramInOffering * 1024 * 1024;
|
||||||
|
when(serviceOfferingDetailsDao.findDetail(Matchers.anyLong(), anyString())).thenReturn(null);
|
||||||
|
when(hostGpuGroupsDao.listHostIds()).thenReturn(hostList0);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(1), Host.Type.Routing.toString())).thenReturn(hostList1);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(2), Host.Type.Routing.toString())).thenReturn(hostList2);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(3), Host.Type.Routing.toString())).thenReturn(hostList3);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(4), Host.Type.Routing.toString())).thenReturn(hostList4);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(5), Host.Type.Routing.toString())).thenReturn(hostList5);
|
||||||
|
when(capacityDao.listHostsWithEnoughCapacity(noOfCpusInOffering * cpuSpeedInOffering, ramInBytes, new Long(6), Host.Type.Routing.toString())).thenReturn(hostList6);
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList1, implicitHostTags)).thenReturn(Arrays.asList("abc", "pqr","xyz"));
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList2, implicitHostTags)).thenReturn(Arrays.asList("abc", "123", "pqr", "456", "xyz"));
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList3, implicitHostTags)).thenReturn(Arrays.asList("abc", "pqr"));
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList4, implicitHostTags)).thenReturn(Arrays.asList("abc"));
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList5, implicitHostTags)).thenReturn(Arrays.asList("abc", "pqr","xyz"));
|
||||||
|
when(hostTagsDao.getDistinctImplicitHostTags(hostList6, implicitHostTags)).thenReturn(Arrays.asList("abc", "123", "pqr","xyz"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan(basePackageClasses = {FirstFitPlanner.class},
|
||||||
|
includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)},
|
||||||
|
useDefaultFilters = false)
|
||||||
|
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostDao hostDao() {
|
||||||
|
return Mockito.mock(HostDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostTagsDao hostTagsDao() {
|
||||||
|
return Mockito.mock(HostTagsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostGpuGroupsDao hostGpuGroupsDao() {
|
||||||
|
return Mockito.mock(HostGpuGroupsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataCenterDao dcDao() {
|
||||||
|
return Mockito.mock(DataCenterDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HostPodDao hostPodDao() {
|
||||||
|
return Mockito.mock(HostPodDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ClusterDao clusterDao() {
|
||||||
|
return Mockito.mock(ClusterDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public GuestOSDao guestOsDao() {
|
||||||
|
return Mockito.mock(GuestOSDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public GuestOSCategoryDao guestOsCategoryDao() {
|
||||||
|
return Mockito.mock(GuestOSCategoryDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DiskOfferingDao diskOfferingDao() {
|
||||||
|
return Mockito.mock(DiskOfferingDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public StoragePoolHostDao storagePoolHostDao() {
|
||||||
|
return Mockito.mock(StoragePoolHostDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserVmDao userVmDao() {
|
||||||
|
return Mockito.mock(UserVmDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public VMInstanceDao vmInstanceDao() {
|
||||||
|
return Mockito.mock(VMInstanceDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public VolumeDao volumeDao() {
|
||||||
|
return Mockito.mock(VolumeDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CapacityManager capacityManager() {
|
||||||
|
return Mockito.mock(CapacityManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConfigurationDao configurationDao() {
|
||||||
|
return Mockito.mock(ConfigurationDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PrimaryDataStoreDao primaryDataStoreDao() {
|
||||||
|
return Mockito.mock(PrimaryDataStoreDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CapacityDao capacityDao() {
|
||||||
|
return Mockito.mock(CapacityDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AccountManager accountManager() {
|
||||||
|
return Mockito.mock(AccountManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public StorageManager storageManager() {
|
||||||
|
return Mockito.mock(StorageManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataStoreManager dataStoreManager() {
|
||||||
|
return Mockito.mock(DataStoreManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ClusterDetailsDao clusterDetailsDao() {
|
||||||
|
return Mockito.mock(ClusterDetailsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServiceOfferingDao serviceOfferingDao() {
|
||||||
|
return Mockito.mock(ServiceOfferingDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServiceOfferingDetailsDao serviceOfferingDetailsDao() {
|
||||||
|
return Mockito.mock(ServiceOfferingDetailsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ResourceManager resourceManager() {
|
||||||
|
return Mockito.mock(ResourceManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Library implements TypeFilter {
|
||||||
|
@Override
|
||||||
|
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||||
|
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
|
||||||
|
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -443,6 +443,8 @@ CREATE VIEW `cloud`.`template_view` AS
|
|||||||
|
|
||||||
UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC,Hyperv' WHERE name='hypervisor.list';
|
UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC,Hyperv' WHERE name='hypervisor.list';
|
||||||
UPDATE `cloud`.`configuration` SET description="If set to true, will set guest VM's name as it appears on the hypervisor, to its hostname. The flag is supported for VMware hypervisor only" WHERE name='vm.instancename.flag';
|
UPDATE `cloud`.`configuration` SET description="If set to true, will set guest VM's name as it appears on the hypervisor, to its hostname. The flag is supported for VMware hypervisor only" WHERE name='vm.instancename.flag';
|
||||||
|
INSERT IGNORE INTO `cloud`.`configuration`(category, instance, component, name, value, description, default_value) VALUES ('Advanced', 'DEFAULT', 'management-server', 'implicit.host.tags', 'GPU', 'Tag hosts at the time of host disovery based on the host properties/capabilities ', 'GPU');
|
||||||
|
|
||||||
DROP VIEW IF EXISTS `cloud`.`domain_router_view`;
|
DROP VIEW IF EXISTS `cloud`.`domain_router_view`;
|
||||||
CREATE VIEW `cloud`.`domain_router_view` AS
|
CREATE VIEW `cloud`.`domain_router_view` AS
|
||||||
select
|
select
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user