use of com.cloud.legacymodel.storage.DiskProfile in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method copyVolumeFromSecToPrimary.
@DB
public VolumeInfo copyVolumeFromSecToPrimary(final VolumeInfo volume, final VirtualMachine vm, final VirtualMachineTemplate template, final DataCenter dc, final Pod pod, final Long clusterId, final DiskOffering diskOffering, final List<StoragePool> avoids) {
final HashSet<StoragePool> avoidPools = new HashSet<>(avoids);
final DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
dskCh.setHyperType(vm.getHypervisorType());
// Find a suitable storage to create volume on
final StoragePool destPool = findStoragePool(dskCh, dc, pod, clusterId, null, vm, avoidPools);
final DataStore destStore = this.dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary);
final AsyncCallFuture<VolumeService.VolumeApiResult> future = this.volService.copyVolume(volume, destStore);
try {
final VolumeService.VolumeApiResult result = future.get();
if (result.isFailed()) {
s_logger.debug("copy volume failed: " + result.getResult());
throw new CloudRuntimeException("copy volume failed: " + result.getResult());
}
return result.getVolume();
} catch (final InterruptedException | ExecutionException e) {
s_logger.debug("Failed to copy volume: " + volume.getId(), e);
throw new CloudRuntimeException("Failed to copy volume", e);
}
}
use of com.cloud.legacymodel.storage.DiskProfile in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method createVolumeFromSnapshot.
@DB
@Override
public VolumeInfo createVolumeFromSnapshot(final Volume volume, final Snapshot snapshot, final UserVm vm) throws StorageUnavailableException {
final Account account = this._entityMgr.findById(Account.class, volume.getAccountId());
final HashSet<StoragePool> poolsToAvoid = new HashSet<>();
StoragePool pool = null;
final Set<Long> podsToAvoid = new HashSet<>();
Pair<Pod, Long> pod = null;
final DiskOffering diskOffering = this._entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
final DataCenter dc = this._entityMgr.findById(DataCenter.class, volume.getDataCenterId());
final DiskProfile dskCh = new DiskProfile(volume, diskOffering, snapshot.getHypervisorType());
String msg = "There are no available storage pools to store the volume in";
if (vm != null) {
final Pod podofVM = this._entityMgr.findById(Pod.class, vm.getPodIdToDeployIn());
if (podofVM != null) {
pod = new Pair<>(podofVM, podofVM.getId());
}
}
if (vm != null && pod != null) {
// if VM is running use the hostId to find the clusterID. If it is stopped, refer the cluster where the ROOT volume of the VM exists.
Long hostId = null;
Long clusterId = null;
if (vm.getState() == State.Running) {
hostId = vm.getHostId();
if (hostId != null) {
final Host vmHost = this._entityMgr.findById(Host.class, hostId);
clusterId = vmHost.getClusterId();
}
} else {
final List<VolumeVO> rootVolumesOfVm = this._volsDao.findByInstanceAndType(vm.getId(), VolumeType.ROOT);
if (rootVolumesOfVm.size() != 1) {
throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state. Please contact Cloud Support.");
} else {
final VolumeVO rootVolumeOfVm = rootVolumesOfVm.get(0);
final StoragePoolVO rootDiskPool = this._storagePoolDao.findById(rootVolumeOfVm.getPoolId());
clusterId = (rootDiskPool == null ? null : rootDiskPool.getClusterId());
}
}
// Determine what storage pool to store the volume in
while ((pool = findStoragePool(dskCh, dc, pod.first(), clusterId, hostId, vm, poolsToAvoid)) != null) {
break;
}
if (pool == null) {
// pool could not be found in the VM's pod/cluster.
if (s_logger.isDebugEnabled()) {
s_logger.debug("Could not find any storage pool to create Volume in the pod/cluster of the provided VM " + vm.getUuid());
}
final StringBuilder addDetails = new StringBuilder(msg);
addDetails.append(", Could not find any storage pool to create Volume in the pod/cluster of the VM ");
addDetails.append(vm.getUuid());
msg = addDetails.toString();
}
} else {
// Determine what pod to store the volume in
while ((pod = findPod(null, null, dc, account.getId(), podsToAvoid)) != null) {
podsToAvoid.add(pod.first().getId());
// Determine what storage pool to store the volume in
while ((pool = findStoragePool(dskCh, dc, pod.first(), null, null, null, poolsToAvoid)) != null) {
break;
}
if (pool != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found a suitable pool for create volume: " + pool.getId());
}
break;
}
}
}
if (pool == null) {
s_logger.info(msg);
throw new StorageUnavailableException(msg, -1);
}
final VolumeInfo vol = this.volFactory.getVolume(volume.getId());
final DataStore store = this.dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
final DataStoreRole dataStoreRole = getDataStoreRole(snapshot);
SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
if (snapInfo == null && dataStoreRole == DataStoreRole.Image) {
// snapshot is not backed up to secondary, let's do that now.
snapInfo = this.snapshotFactory.getSnapshot(snapshot.getId(), DataStoreRole.Primary);
if (snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId());
}
// We need to copy the snapshot onto secondary.
final SnapshotStrategy snapshotStrategy = this._storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.BACKUP);
snapshotStrategy.backupSnapshot(snapInfo);
// Attempt to grab it again.
snapInfo = this.snapshotFactory.getSnapshot(snapshot.getId(), dataStoreRole);
if (snapInfo == null) {
throw new CloudRuntimeException("Cannot find snapshot " + snapshot.getId() + " on secondary and could not create backup");
}
}
// don't try to perform a sync if the DataStoreRole of the snapshot is equal to DataStoreRole.Primary
if (!DataStoreRole.Primary.equals(dataStoreRole)) {
try {
// sync snapshot to region store if necessary
final DataStore snapStore = snapInfo.getDataStore();
final long snapVolId = snapInfo.getVolumeId();
this._snapshotSrv.syncVolumeSnapshotsToRegionStore(snapVolId, snapStore);
} catch (final Exception ex) {
// log but ignore the sync error to avoid any potential S3 down issue, it should be sync next time
s_logger.warn(ex.getMessage(), ex);
}
}
// create volume on primary from snapshot
final AsyncCallFuture<VolumeService.VolumeApiResult> future = this.volService.createVolumeFromSnapshot(vol, store, snapInfo);
try {
final VolumeService.VolumeApiResult result = future.get();
if (result.isFailed()) {
s_logger.debug("Failed to create volume from snapshot:" + result.getResult());
throw new CloudRuntimeException("Failed to create volume from snapshot:" + result.getResult());
}
return result.getVolume();
} catch (final InterruptedException e) {
s_logger.debug("Failed to create volume from snapshot", e);
throw new CloudRuntimeException("Failed to create volume from snapshot", e);
} catch (final ExecutionException e) {
s_logger.debug("Failed to create volume from snapshot", e);
throw new CloudRuntimeException("Failed to create volume from snapshot", e);
}
}
use of com.cloud.legacymodel.storage.DiskProfile in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method createVolume.
@DB
public VolumeInfo createVolume(final StoragePool storagePool, VolumeInfo volume, final VirtualMachineTemplate template, final DataCenter dc, final ServiceOffering offering, final DiskOffering diskOffering, final long size, final HypervisorType hyperType) {
// update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
volume = this.volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
final DiskProfile dskCh;
if (volume.getVolumeType() == VolumeType.ROOT && ImageFormat.ISO != template.getFormat()) {
dskCh = createDiskCharacteristics(volume, template, dc, offering);
} else {
dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
}
if (diskOffering != null && diskOffering.isCustomized()) {
dskCh.setSize(size);
}
dskCh.setHyperType(hyperType);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Trying to create " + volume + " on " + storagePool);
}
final DataStore store = this.dataStoreMgr.getDataStore(storagePool.getId(), DataStoreRole.Primary);
for (int i = 0; i < 2; i++) {
// retry one more time in case of template reload is required for Vmware case
final AsyncCallFuture<VolumeService.VolumeApiResult> future;
final boolean isNotCreatedFromTemplate = volume.getTemplateId() == null;
if (isNotCreatedFromTemplate) {
future = this.volService.createVolumeAsync(volume, store);
} else {
final TemplateInfo templ = this.tmplFactory.getTemplate(template.getId(), DataStoreRole.Image);
future = this.volService.createVolumeFromTemplateAsync(volume, store.getId(), templ);
}
try {
final VolumeService.VolumeApiResult result = future.get();
if (result.isFailed()) {
if (result.getResult().contains("request template reload") && (i == 0)) {
s_logger.debug("Retry template re-deploy for vmware");
continue;
} else {
s_logger.debug("create volume failed: " + result.getResult());
throw new CloudRuntimeException("create volume failed:" + result.getResult());
}
}
return result.getVolume();
} catch (final InterruptedException | ExecutionException e) {
s_logger.error("create volume failed", e);
throw new CloudRuntimeException("create volume failed", e);
}
}
throw new CloudRuntimeException("create volume failed even after template re-deploy");
}
use of com.cloud.legacymodel.storage.DiskProfile in project cosmic by MissionCriticalCloud.
the class VirtualMachineManagerImpl method getPoolListForVolumesForMigration.
private Map<Volume, StoragePool> getPoolListForVolumesForMigration(final VirtualMachineProfile profile, final Host host, final Map<Long, Long> volumeToPool) {
final List<VolumeVO> allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId());
final Map<Volume, StoragePool> volumeToPoolObjectMap = new HashMap<>();
for (final VolumeVO volume : allVolumes) {
final Long poolId = volumeToPool.get(volume.getId());
final StoragePoolVO pool = _storagePoolDao.findById(poolId);
final StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId());
final DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId());
if (pool != null) {
// created is compliant with the pool type.
if (_poolHostDao.findByPoolHost(pool.getId(), host.getId()) == null || pool.isLocal() != diskOffering.getUseLocalStorage()) {
// Cannot find a pool for the volume. Throw an exception.
throw new CloudRuntimeException("Cannot migrate volume " + volume + " to storage pool " + pool + " while migrating vm to host " + host + ". Either the pool is not accessible from the host or because of the offering with which the volume is created it cannot be placed on " + "the given pool.");
} else if (pool.getId() == currentPool.getId()) {
// If the pool to migrate too is the same as current pool, the volume doesn't need to be migrated.
} else {
volumeToPoolObjectMap.put(volume, pool);
}
} else {
// Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools.
final DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType());
final DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), host.getId(), null, null);
final ExcludeList avoid = new ExcludeList();
boolean currentPoolAvailable = false;
final List<StoragePool> poolList = new ArrayList<>();
for (final StoragePoolAllocator allocator : _storagePoolAllocators) {
final List<StoragePool> poolListFromAllocator = allocator.allocateToPool(diskProfile, profile, plan, avoid, StoragePoolAllocator.RETURN_UPTO_ALL);
if (poolListFromAllocator != null && !poolListFromAllocator.isEmpty()) {
poolList.addAll(poolListFromAllocator);
}
}
if (poolList != null && !poolList.isEmpty()) {
// Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the
// volume to a pool only if it is required; that is the current pool on which the volume resides
// is not available on the destination host.
final Iterator<StoragePool> iter = poolList.iterator();
while (iter.hasNext()) {
if (currentPool.getId() == iter.next().getId()) {
currentPoolAvailable = true;
break;
}
}
if (!currentPoolAvailable) {
volumeToPoolObjectMap.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid()));
}
}
if (!currentPoolAvailable && !volumeToPoolObjectMap.containsKey(volume)) {
// Cannot find a pool for the volume. Throw an exception.
throw new CloudRuntimeException("Cannot find a storage pool which is available for volume " + volume + " while migrating virtual machine " + profile.getVirtualMachine() + " to host " + host);
}
}
}
return volumeToPoolObjectMap;
}
use of com.cloud.legacymodel.storage.DiskProfile in project cosmic by MissionCriticalCloud.
the class DeploymentPlanningManagerImpl method findSuitablePoolsForVolumes.
protected Pair<Map<Volume, List<StoragePool>>, List<Volume>> findSuitablePoolsForVolumes(final VirtualMachineProfile vmProfile, final DeploymentPlan plan, final ExcludeList avoid, final int returnUpTo) {
final List<VolumeVO> volumesTobeCreated = _volsDao.findUsableVolumesForInstance(vmProfile.getId());
final Map<Volume, List<StoragePool>> suitableVolumeStoragePools = new HashMap<>();
final List<Volume> readyAndReusedVolumes = new ArrayList<>();
// There should be atleast the ROOT volume of the VM in usable state
if (volumesTobeCreated.isEmpty()) {
throw new CloudRuntimeException("Unable to create deployment, no usable volumes found for the VM");
}
// don't allow to start vm that doesn't have a root volume
if (_volsDao.findByInstanceAndType(vmProfile.getId(), VolumeType.ROOT).isEmpty()) {
throw new CloudRuntimeException("Unable to prepare volumes for vm as ROOT volume is missing");
}
// for each volume find list of suitable storage pools by calling the
// allocators
Set<Long> originalAvoidPoolSet = avoid.getPoolsToAvoid();
if (originalAvoidPoolSet == null) {
originalAvoidPoolSet = new HashSet<>();
}
final Set<Long> poolsToAvoidOutput = new HashSet<>(originalAvoidPoolSet);
for (final VolumeVO toBeCreated : volumesTobeCreated) {
s_logger.debug("Checking suitable pools for volume (Id, Type): (" + toBeCreated.getId() + "," + toBeCreated.getVolumeType().name() + ")");
// be reused.
if (plan.getPoolId() != null || (toBeCreated.getVolumeType() == VolumeType.DATADISK && toBeCreated.getPoolId() != null && toBeCreated.getState() == Volume.State.Ready)) {
s_logger.debug("Volume has pool already allocated, checking if pool can be reused, poolId: " + toBeCreated.getPoolId());
final List<StoragePool> suitablePools = new ArrayList<>();
StoragePool pool = null;
if (toBeCreated.getPoolId() != null) {
pool = (StoragePool) dataStoreMgr.getPrimaryDataStore(toBeCreated.getPoolId());
} else {
pool = (StoragePool) dataStoreMgr.getPrimaryDataStore(plan.getPoolId());
}
if (!pool.isInMaintenance()) {
if (!avoid.shouldAvoid(pool)) {
final long exstPoolDcId = pool.getDataCenterId();
final long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
final long exstPoolClusterId = pool.getClusterId() != null ? pool.getClusterId() : -1;
boolean canReusePool = false;
if (plan.getDataCenterId() == exstPoolDcId && plan.getPodId() == exstPoolPodId && plan.getClusterId() == exstPoolClusterId) {
canReusePool = true;
} else if (plan.getDataCenterId() == exstPoolDcId) {
final DataStore dataStore = dataStoreMgr.getPrimaryDataStore(pool.getId());
if (dataStore != null && dataStore.getScope() != null && dataStore.getScope().getScopeType() == ScopeType.ZONE) {
canReusePool = true;
}
} else {
s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
canReusePool = false;
}
if (canReusePool) {
s_logger.debug("Planner need not allocate a pool for this volume since its READY");
suitablePools.add(pool);
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
if (!(toBeCreated.getState() == Volume.State.Allocated || toBeCreated.getState() == Volume.State.Creating)) {
readyAndReusedVolumes.add(toBeCreated);
}
continue;
}
} else {
s_logger.debug("Pool of the volume is in avoid set, need to reallocate a pool for this volume");
}
} else {
s_logger.debug("Pool of the volume is in maintenance, need to reallocate a pool for this volume");
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("We need to allocate new storagepool for this volume");
}
if (!isRootAdmin(vmProfile)) {
if (!isEnabledForAllocation(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId())) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cannot allocate new storagepool for this volume in this cluster, allocation state is disabled");
s_logger.debug("Cannot deploy to this specified plan, allocation state is disabled, returning.");
}
// Cannot find suitable storage pools under this cluster for
// this volume since allocation_state is disabled.
// - remove any suitable pools found for other volumes.
// All volumes should get suitable pools under this cluster;
// else we cant use this cluster.
suitableVolumeStoragePools.clear();
break;
}
}
s_logger.debug("Calling StoragePoolAllocators to find suitable pools");
final DiskOfferingVO diskOffering = _diskOfferingDao.findById(toBeCreated.getDiskOfferingId());
if (vmProfile.getTemplate().getFormat() == ImageFormat.ISO && vmProfile.getServiceOffering().getTagsArray().length != 0) {
diskOffering.setTagsArray(Arrays.asList(vmProfile.getServiceOffering().getTagsArray()));
}
final DiskProfile diskProfile = new DiskProfile(toBeCreated, diskOffering, vmProfile.getHypervisorType());
boolean useLocalStorage = false;
if (vmProfile.getType() != VirtualMachineType.User) {
final Zone zone = zoneRepository.findById(plan.getDataCenterId()).orElse(null);
assert (zone != null) : "Invalid zone in deployment plan";
final Boolean useLocalStorageForSystemVM = ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(zone.getId());
if (useLocalStorageForSystemVM != null) {
useLocalStorage = useLocalStorageForSystemVM.booleanValue();
s_logger.debug("System VMs will use " + (useLocalStorage ? "local" : "shared") + " storage for zone id=" + plan.getDataCenterId());
}
} else {
useLocalStorage = diskOffering.getUseLocalStorage();
// offering when it is a ROOT disk
if (!useLocalStorage && vmProfile.getServiceOffering().getUseLocalStorage()) {
if (toBeCreated.getVolumeType() == VolumeType.ROOT) {
useLocalStorage = true;
}
}
}
diskProfile.setUseLocalStorage(useLocalStorage);
boolean foundPotentialPools = false;
for (final StoragePoolAllocator allocator : _storagePoolAllocators) {
final List<StoragePool> suitablePools = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, returnUpTo);
if (suitablePools != null && !suitablePools.isEmpty()) {
suitableVolumeStoragePools.put(toBeCreated, suitablePools);
foundPotentialPools = true;
break;
}
}
if (avoid.getPoolsToAvoid() != null) {
poolsToAvoidOutput.addAll(avoid.getPoolsToAvoid());
avoid.getPoolsToAvoid().retainAll(originalAvoidPoolSet);
}
if (!foundPotentialPools) {
s_logger.debug("No suitable pools found for volume: " + toBeCreated + " under cluster: " + plan.getClusterId());
// No suitable storage pools found under this cluster for this
// volume. - remove any suitable pools found for other volumes.
// All volumes should get suitable pools under this cluster;
// else we cant use this cluster.
suitableVolumeStoragePools.clear();
break;
}
}
final HashSet<Long> toRemove = new HashSet<>();
for (final List<StoragePool> lsp : suitableVolumeStoragePools.values()) {
for (final StoragePool sp : lsp) {
toRemove.add(sp.getId());
}
}
poolsToAvoidOutput.removeAll(toRemove);
if (avoid.getPoolsToAvoid() != null) {
avoid.getPoolsToAvoid().addAll(poolsToAvoidOutput);
}
if (suitableVolumeStoragePools.isEmpty()) {
s_logger.debug("No suitable pools found");
}
return new Pair<>(suitableVolumeStoragePools, readyAndReusedVolumes);
}
Aggregations