From 7998413f48784863a392d8e7719ff4c440a84659 Mon Sep 17 00:00:00 2001 From: Sateesh Chodapuneedi Date: Wed, 29 May 2013 01:20:05 +0530 Subject: [PATCH] CLOUDSTACK-2029 zone wide primary storage support for cloudstack over vmware deployments Added hypervisor type to CreateStoragePoolCmd & Storage pool responses. DatastoreLifeCycle would consider hypervisor type while attaching datastore to zone. ZoneWideStoragePoolAllocator would filter zone wide primary storage pools by hypervisor type along with tags in disk profile. hypervisor type is mandatory parameter if scope is specified as ZONE while creating primary storage pool. As of now KVM, VMware are allowed to use ZoneWideStoragePoolAllocator. Signed-off-by: Sateesh Chodapuneedi --- .../admin/storage/CreateStoragePoolCmd.java | 20 +++--- .../StoragePoolForMigrationResponse.java | 11 ++++ .../api/response/StoragePoolResponse.java | 21 ++++-- .../api/storage/DataStoreLifeCycle.java | 5 +- .../DefaultImageDataStoreLifeCycle.java | 3 +- .../ZoneWideStoragePoolAllocator.java | 64 ++++++++++--------- .../datastore/PrimaryDataStoreHelper.java | 44 +++++++------ .../DefaultPrimaryDataStoreLifeCycleImpl.java | 2 +- ...oudStackPrimaryDataStoreLifeCycleImpl.java | 24 +++---- .../com/cloud/storage/StorageManagerImpl.java | 21 +++++- .../storage/listener/StoragePoolMonitor.java | 5 +- 11 files changed, 138 insertions(+), 82 deletions(-) diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java index 5178d685889..74eb2b9bf8f 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java @@ -71,15 +71,19 @@ public class CreateStoragePoolCmd extends BaseCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class, required=true, description="the Zone ID for the storage pool") private Long zoneId; - + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, required=false, description="the storage provider name") private String storageProviderName; - + @Parameter(name=ApiConstants.SCOPE, type=CommandType.STRING, required=false, description="the scope of the storage: cluster or zone") private String scope; + @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=false, + description="hypervisor type of the hosts in zone that will be attached to this storage pool. KVM, VMware supported as of now.") + private String hypervisor; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -111,18 +115,18 @@ public class CreateStoragePoolCmd extends BaseCmd { public Long getZoneId() { return zoneId; } - + public String getStorageProviderName() { return this.storageProviderName; } - + public String getScope() { - return this.scope; + return this.scope; } - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// + public String getHypervisor() { + return hypervisor; + } @Override public String getCommandName() { diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java index f0bbcb19136..2cfc8d03c3c 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java @@ -83,6 +83,9 @@ public class StoragePoolForMigrationResponse extends BaseResponse { @SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool") private String scope; + @SerializedName(ApiConstants.HYPERVISOR) @Param(description="the hypervisor type of the storage pool") + private String hypervisor; + @SerializedName("suitableformigration") @Param(description="true if this pool is suitable to migrate a volume," + " false otherwise") private Boolean suitableForMigration; @@ -101,6 +104,14 @@ public class StoragePoolForMigrationResponse extends BaseResponse { this.scope = scope; } + public String getHypervisor() { + return hypervisor; + } + + public void setHypervisor(String hypervisor) { + this.hypervisor = hypervisor; + } + @Override public String getObjectId() { return this.getId(); diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 4411ddcb112..57a5ea14840 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -40,13 +40,13 @@ public class StoragePoolResponse extends BaseResponse { @SerializedName(ApiConstants.ZONE_TYPE) @Param(description = "network type of the availability zone") private String zoneType; - + @SerializedName("podid") @Param(description="the Pod ID of the storage pool") private String podId; @SerializedName("podname") @Param(description="the Pod name of the storage pool") private String podName; - + @SerializedName("name") @Param(description="the name of the storage pool") private String name; @@ -82,10 +82,13 @@ public class StoragePoolResponse extends BaseResponse { @SerializedName(ApiConstants.STATE) @Param(description="the state of the storage pool") private StoragePoolStatus state; - + @SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool") private String scope; + @SerializedName(ApiConstants.HYPERVISOR) @Param(description="the hypervisor type of the storage pool") + private String hypervisor; + /** * @return the scope */ @@ -100,6 +103,14 @@ public class StoragePoolResponse extends BaseResponse { this.scope = scope; } + public String getHypervisor() { + return hypervisor; + } + + public void setHypervisor(String hypervisor) { + this.hypervisor = hypervisor; + } + @Override public String getObjectId() { return this.getId(); @@ -132,11 +143,11 @@ public class StoragePoolResponse extends BaseResponse { public String getZoneType() { return zoneType; } - + public void setZoneType(String zoneType) { this.zoneType = zoneType; } - + public String getPodId() { return podId; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java index 280e02e2a32..cb467093955 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java @@ -21,6 +21,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import java.util.Map; import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.hypervisor.Hypervisor.HypervisorType; public interface DataStoreLifeCycle { @@ -28,8 +29,8 @@ public interface DataStoreLifeCycle { public boolean attachCluster(DataStore store, ClusterScope scope); public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo); - boolean attachZone(DataStore dataStore, ZoneScope scope); - + boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType); + public boolean dettach(); public boolean unmanaged(); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java index ba29c1a14b0..fef97671961 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java @@ -30,6 +30,7 @@ import org.apache.cloudstack.storage.image.db.ImageDataStoreDao; import org.apache.cloudstack.storage.image.db.ImageDataStoreVO; import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.hypervisor.Hypervisor.HypervisorType; public class DefaultImageDataStoreLifeCycle implements ImageDataStoreLifeCycle { @Inject @@ -65,7 +66,7 @@ public class DefaultImageDataStoreLifeCycle implements ImageDataStoreLifeCycle { @Override - public boolean attachZone(DataStore dataStore, ZoneScope scope) { + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisor) { // TODO Auto-generated method stub return false; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index e9769802a37..d8d413283ad 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -38,34 +38,36 @@ import com.cloud.vm.VirtualMachineProfile; @Component public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { - private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class); - @Inject PrimaryDataStoreDao _storagePoolDao; - @Inject DataStoreManager dataStoreMgr; + private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class); + @Inject PrimaryDataStoreDao _storagePoolDao; + @Inject DataStoreManager dataStoreMgr; - @Override - protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, - DeploymentPlan plan) { + @Override + protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, + DeploymentPlan plan) { Volume volume = _volumeDao.findById(dskCh.getVolumeId()); List requestVolumes = new ArrayList(); requestVolumes.add(volume); return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool); - } + } - @Override - protected List select(DiskProfile dskCh, - VirtualMachineProfile vmProfile, - DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); - List suitablePools = new ArrayList(); - HypervisorType hypervisor = dskCh.getHypervisorType(); - if (hypervisor != null) { - if (hypervisor != HypervisorType.KVM) { - s_logger.debug("Only kvm supports zone wide storage"); - return suitablePools; - } - } + @Override + protected List select(DiskProfile dskCh, + VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); + List suitablePools = new ArrayList(); + HypervisorType hypervisor = dskCh.getHypervisorType(); + if (hypervisor != null) { + if (hypervisor != HypervisorType.KVM && hypervisor != HypervisorType.VMware) { + s_logger.debug("Only kvm, VMware hypervisors are enabled to support zone wide storage"); + return suitablePools; + } + } - List storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags()); + List storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags()); + List storagePoolsByHypervisor = _storagePoolDao.findZoneWideStoragePoolsByHypervisor(plan.getDataCenterId(), dskCh.getHypervisorType()); + storagePools.retainAll(storagePoolsByHypervisor); // add remaining pools in zone, that did not match tags, to avoid set List allPools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), null); @@ -74,17 +76,17 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { avoid.addPool(pool.getId()); } - for (StoragePoolVO storage : storagePools) { - if (suitablePools.size() == returnUpTo) { - break; - } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId()); - if (filter(avoid, pol, dskCh, plan)) { - suitablePools.add(pol); + for (StoragePoolVO storage : storagePools) { + if (suitablePools.size() == returnUpTo) { + break; + } + StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId()); + if (filter(avoid, pol, dskCh, plan)) { + suitablePools.add(pol); } else { avoid.addPool(pol.getId()); } - } - return suitablePools; - } + } + return suitablePools; + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java index 5f8daf42bb3..349f6ba9079 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java @@ -29,25 +29,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType; -import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.StoragePoolInfo; -import com.cloud.alert.AlertManager; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.StorageManager; -import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.dao.StoragePoolHostDao; -import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @@ -70,7 +65,7 @@ public class PrimaryDataStoreHelper { if (dataStoreVO != null) { throw new CloudRuntimeException("duplicate uuid: " + params.getUuid()); } - + dataStoreVO = new StoragePoolVO(); dataStoreVO.setStorageProviderName(params.getProviderName()); dataStoreVO.setHostAddress(params.getHost()); @@ -84,7 +79,7 @@ public class PrimaryDataStoreHelper { dataStoreVO.setClusterId(params.getClusterId()); dataStoreVO.setStatus(StoragePoolStatus.Initialized); dataStoreVO.setUserInfo(params.getUserInfo()); - + Map details = params.getDetails(); String tags = params.getTags(); if (tags != null) { @@ -98,19 +93,19 @@ public class PrimaryDataStoreHelper { details.put(tag, "true"); } } - + dataStoreVO = dataStoreDao.persist(dataStoreVO, details); return dataStoreMgr.getDataStore(dataStoreVO.getId(), DataStoreRole.Primary); } - + public DataStore attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(store.getId(), scope.getScopeId()); if (poolHost == null) { poolHost = new StoragePoolHostVO(store.getId(), scope.getScopeId(), existingInfo.getLocalPath()); storagePoolHostDao.persist(poolHost); } - + StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); pool.setScope(scope.getScopeType()); pool.setAvailableBytes(existingInfo.getAvailableBytes()); @@ -120,18 +115,18 @@ public class PrimaryDataStoreHelper { this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, pool.getCapacityBytes() - pool.getAvailableBytes()); return dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); } - + public DataStore attachCluster(DataStore store) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); - + storageMgr.createCapacityEntry(pool.getId()); - + pool.setScope(ScopeType.CLUSTER); pool.setStatus(StoragePoolStatus.Up); this.dataStoreDao.update(pool.getId(), pool); return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); } - + public DataStore attachZone(DataStore store) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); pool.setScope(ScopeType.ZONE); @@ -139,21 +134,30 @@ public class PrimaryDataStoreHelper { this.dataStoreDao.update(pool.getId(), pool); return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); } - + + public DataStore attachZone(DataStore store, HypervisorType hypervisor) { + StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); + pool.setScope(ScopeType.ZONE); + pool.setHypervisor(hypervisor); + pool.setStatus(StoragePoolStatus.Up); + this.dataStoreDao.update(pool.getId(), pool); + return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); + } + public boolean maintain(DataStore store) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); pool.setStatus(StoragePoolStatus.Maintenance); this.dataStoreDao.update(pool.getId(), pool); return true; } - + public boolean cancelMaintain(DataStore store) { StoragePoolVO pool = this.dataStoreDao.findById(store.getId()); pool.setStatus(StoragePoolStatus.Up); dataStoreDao.update(store.getId(), pool); return true; } - + protected boolean deletePoolStats(Long poolId) { CapacityVO capacity1 = _capacityDao.findByHostIdType(poolId, @@ -167,10 +171,10 @@ public class PrimaryDataStoreHelper { if (capacity2 != null) { _capacityDao.remove(capacity2.getId()); } - + return true; } - + public boolean deletePrimaryDataStore(DataStore store) { List hostPoolRecords = this.storagePoolHostDao .listByPoolId(store.getId()); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java index fea02e8d1ed..cffa1cee4dc 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java @@ -114,7 +114,7 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif } @Override - public boolean attachZone(DataStore dataStore, ZoneScope scope) { + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { // TODO Auto-generated method stub return false; } diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java index 7153282a2aa..fb37e8f4b10 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java @@ -441,18 +441,18 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } @Override - public boolean attachZone(DataStore dataStore, ZoneScope scope) { - List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.KVM, scope.getScopeId()); - for (HostVO host : hosts) { - try { - this.storageMgr.connectHostToSharedPool(host.getId(), - dataStore.getId()); - } catch (Exception e) { - s_logger.warn("Unable to establish a connection between " + host - + " and " + dataStore, e); - } - } - this.dataStoreHelper.attachZone(dataStore); + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId()); + for (HostVO host : hosts) { + try { + this.storageMgr.connectHostToSharedPool(host.getId(), + dataStore.getId()); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + host + + " and " + dataStore, e); + } + } + this.dataStoreHelper.attachZone(dataStore, hypervisorType); return true; } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index a67397ec460..956aa87f0d5 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -775,6 +775,25 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C "zone id can't be null, if scope is zone"); } + String hypervisor = cmd.getHypervisor(); + HypervisorType hypervisorType; + if (hypervisor != null) { + try { + hypervisorType = HypervisorType.getType(hypervisor); + } catch (Exception e) { + throw new InvalidParameterValueException("invalid hypervisor type" + hypervisor); + } + } else { + throw new InvalidParameterValueException( + "Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage."); + } + + if (scopeType == ScopeType.ZONE && + (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware)) { + throw new InvalidParameterValueException( + "zone wide storage pool is not suported for hypervisor type " + hypervisor); + } + Map ds = cmd.getDetails(); Map details = new HashMap(); if (ds != null) { @@ -826,7 +845,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C lifeCycle.attachCluster(store, clusterScope); } else if (scopeType == ScopeType.ZONE) { ZoneScope zoneScope = new ZoneScope(zoneId); - lifeCycle.attachZone(store, zoneScope); + lifeCycle.attachZone(store, zoneScope, hypervisorType); } } catch (Exception e) { s_logger.debug("Failed to add data store", e); diff --git a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java index f957ca31ada..4848d446d21 100755 --- a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java +++ b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java @@ -77,7 +77,10 @@ public class StoragePoolMonitor implements Listener { if (scCmd.getHypervisorType() == HypervisorType.XenServer || scCmd.getHypervisorType() == HypervisorType.KVM || scCmd.getHypervisorType() == HypervisorType.VMware || scCmd.getHypervisorType() == HypervisorType.Simulator || scCmd.getHypervisorType() == HypervisorType.Ovm) { List pools = _poolDao.listBy(host.getDataCenterId(), host.getPodId(), host.getClusterId(), ScopeType.CLUSTER); - pools.addAll(_poolDao.findZoneWideStoragePoolsByTags(host.getDataCenterId(), null)); + List zoneStoragePoolsByTags = _poolDao.findZoneWideStoragePoolsByTags(host.getDataCenterId(), null); + List zoneStoragePoolsByHypervisor = _poolDao.findZoneWideStoragePoolsByHypervisor(host.getDataCenterId(), scCmd.getHypervisorType()); + zoneStoragePoolsByTags.retainAll(zoneStoragePoolsByHypervisor); + pools.addAll(zoneStoragePoolsByTags); for (StoragePoolVO pool : pools) { if (pool.getStatus() != StoragePoolStatus.Up) { continue;