use of com.cloud.legacymodel.storage.DiskOffering in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method getTasks.
private List<VolumeTask> getTasks(final List<VolumeVO> vols, final Map<Volume, StoragePool> destVols, final VirtualMachineProfile vm) throws StorageUnavailableException {
final boolean recreate = RecreatableSystemVmEnabled.value();
final List<VolumeTask> tasks = new ArrayList<>();
for (final VolumeVO vol : vols) {
StoragePoolVO assignedPool = null;
if (destVols != null) {
final StoragePool pool = destVols.get(vol);
if (pool != null) {
assignedPool = this._storagePoolDao.findById(pool.getId());
}
}
if (assignedPool == null && recreate) {
assignedPool = this._storagePoolDao.findById(vol.getPoolId());
}
if (assignedPool != null) {
final Volume.State state = vol.getState();
if (state == Volume.State.Allocated || state == Volume.State.Creating) {
final VolumeTask task = new VolumeTask(VolumeTaskType.RECREATE, vol, null);
tasks.add(task);
} else {
if (vol.isRecreatable()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Volume " + vol + " will be recreated on storage pool " + assignedPool + " assigned by deploymentPlanner");
}
final VolumeTask task = new VolumeTask(VolumeTaskType.RECREATE, vol, null);
tasks.add(task);
} else {
if (assignedPool.getId() != vol.getPoolId()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Mismatch in storage pool " + assignedPool + " assigned by deploymentPlanner and the one associated with volume " + vol);
}
final DiskOffering diskOffering = this._entityMgr.findById(DiskOffering.class, vol.getDiskOfferingId());
if (diskOffering.getUseLocalStorage()) {
// Currently migration of local volume is not supported so bail out
if (s_logger.isDebugEnabled()) {
s_logger.debug("Local volume " + vol + " cannot be recreated on storagepool " + assignedPool + " assigned by deploymentPlanner");
}
throw new CloudRuntimeException("Local volume " + vol + " cannot be recreated on storagepool " + assignedPool + " assigned by deploymentPlanner");
} else {
// Check if storage migration is enabled in config
final Boolean isHAOperation = (Boolean) vm.getParameter(VirtualMachineProfile.Param.HaOperation);
Boolean storageMigrationEnabled = true;
if (isHAOperation != null && isHAOperation) {
storageMigrationEnabled = StorageHAMigrationEnabled.value();
} else {
storageMigrationEnabled = StorageMigrationEnabled.value();
}
// Always allow ISOs volumes to be "migrated"
if (storageMigrationEnabled || vol.getIsoId() != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Shared volume " + vol + " will be migrated on storage pool " + assignedPool + " assigned by deploymentPlanner");
}
final VolumeTask task = new VolumeTask(VolumeTaskType.MIGRATE, vol, assignedPool);
tasks.add(task);
} else {
throw new CloudRuntimeException("Cannot start VM on the hypervisor it was last running on, due to not enough capacity. Please try to start on" + " " + "another hypervisor in the same cluster, or migrate the volumes to another storage pool. Automatic Volume Migration is disabled, " + "so this is not handled automatically.");
}
}
} else {
final StoragePoolVO pool = this._storagePoolDao.findById(vol.getPoolId());
final VolumeTask task = new VolumeTask(VolumeTaskType.NOP, vol, pool);
tasks.add(task);
}
}
}
} else {
if (vol.getPoolId() == null) {
throw new StorageUnavailableException("Volume has no pool associate and also no storage pool assigned in DeployDestination, Unable to create " + vol, Volume.class, vol.getId());
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("No need to recreate the volume: " + vol + ", since it already has a pool assigned: " + vol.getPoolId() + ", adding disk to VM");
}
final StoragePoolVO pool = this._storagePoolDao.findById(vol.getPoolId());
final VolumeTask task = new VolumeTask(VolumeTaskType.NOP, vol, pool);
tasks.add(task);
}
}
return tasks;
}
use of com.cloud.legacymodel.storage.DiskOffering 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.DiskOffering in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method findStoragePoolToCreateVolumeOn.
/**
* Volume placement logic
*/
private StoragePool findStoragePoolToCreateVolumeOn(final VolumeInfo volumeInfo, final UserVmVO virtualMachine) {
final DiskOffering diskOffering = this._diskOfferingDao.findById(volumeInfo.getDiskOfferingId());
final List<StoragePoolVO> storagePoolsInScopeWithVirtualMachine = findAllStoragePoolsInScopeWithVirtualMachine(virtualMachine);
final List<StoragePoolVO> storagePoolVOListMatchedTags = checkIfStoragePoolWithMatchingTags(storagePoolsInScopeWithVirtualMachine, Arrays.asList(diskOffering.getTagsArray()));
final List<StoragePoolVO> storagePoolVOListSufficientResources = checkIfStoragePoolHasSufficientResources(storagePoolVOListMatchedTags, volumeInfo);
return getStoragePoolLeastResourcesUsed(storagePoolVOListSufficientResources);
}
use of com.cloud.legacymodel.storage.DiskOffering in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method moveVolume.
@Override
public VolumeInfo moveVolume(final VolumeInfo volume, final long destPoolDcId, final Long destPoolPodId, final Long destPoolClusterId, final HypervisorType dataDiskHyperType) throws ConcurrentOperationException, StorageUnavailableException {
// Find a destination storage pool with the specified criteria
final DiskOffering diskOffering = this._entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
final DiskProfile dskCh = new DiskProfile(volume.getId(), volume.getVolumeType(), volume.getName(), diskOffering.getId(), diskOffering.getDiskSize(), diskOffering.getTagsArray(), diskOffering.getUseLocalStorage(), diskOffering.isRecreatable(), null);
dskCh.setHyperType(dataDiskHyperType);
final DataCenter destPoolDataCenter = this._entityMgr.findById(DataCenter.class, destPoolDcId);
final Pod destPoolPod = this._entityMgr.findById(Pod.class, destPoolPodId);
final StoragePool destPool = findStoragePool(dskCh, destPoolDataCenter, destPoolPod, destPoolClusterId, null, null, new HashSet<>());
if (destPool == null) {
throw new CloudRuntimeException("Failed to find a storage pool with enough capacity to move the volume to.");
}
final Volume newVol = migrateVolume(volume, destPool);
return this.volFactory.getVolume(newVol.getId());
}
use of com.cloud.legacymodel.storage.DiskOffering in project cosmic by MissionCriticalCloud.
the class VolumeOrchestrator method recreateVolume.
private Pair<VolumeVO, DataStore> recreateVolume(final VolumeVO vol, final VirtualMachineProfile vm, final DeployDestination dest) throws StorageUnavailableException {
VolumeVO newVol;
final boolean recreate = RecreatableSystemVmEnabled.value();
DataStore destPool = null;
if (recreate && (dest.getStorageForDisks() == null || dest.getStorageForDisks().get(vol) == null)) {
destPool = this.dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary);
s_logger.debug("existing pool: " + destPool.getId());
} else {
final StoragePool pool = dest.getStorageForDisks().get(vol);
destPool = this.dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
}
if (vol.getState() == Volume.State.Allocated || vol.getState() == Volume.State.Creating) {
newVol = vol;
} else {
newVol = switchVolume(vol, vm);
// changed
if (dest.getStorageForDisks() != null && dest.getStorageForDisks().containsKey(vol)) {
final StoragePool poolWithOldVol = dest.getStorageForDisks().get(vol);
dest.getStorageForDisks().put(newVol, poolWithOldVol);
dest.getStorageForDisks().remove(vol);
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Created new volume " + newVol + " for old volume " + vol);
}
}
VolumeInfo volume = this.volFactory.getVolume(newVol.getId(), destPool);
final Long templateId = newVol.getTemplateId();
for (int i = 0; i < 2; i++) {
// retry one more time in case of template reload is required for Vmware case
AsyncCallFuture<VolumeService.VolumeApiResult> future = null;
if (templateId == null) {
final DiskOffering diskOffering = this._entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
final HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
// update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
this.volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
volume = this.volFactory.getVolume(newVol.getId(), destPool);
future = this.volService.createVolumeAsync(volume, destPool);
} else {
final TemplateInfo templ = this.tmplFactory.getReadyTemplateOnImageStore(templateId, dest.getZone().getId());
if (templ == null) {
s_logger.debug("can't find ready template: " + templateId + " for data center " + dest.getZone().getId());
throw new CloudRuntimeException("can't find ready template: " + templateId + " for data center " + dest.getZone().getId());
}
final PrimaryDataStore primaryDataStore = (PrimaryDataStore) destPool;
if (primaryDataStore.isManaged()) {
final DiskOffering diskOffering = this._entityMgr.findById(DiskOffering.class, volume.getDiskOfferingId());
final HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
// update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
this.volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
final long hostId = vm.getVirtualMachine().getHostId();
future = this.volService.createManagedStorageAndVolumeFromTemplateAsync(volume, destPool.getId(), templ, hostId);
} else {
future = this.volService.createVolumeFromTemplateAsync(volume, destPool.getId(), templ);
}
}
VolumeService.VolumeApiResult result = null;
try {
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("Unable to create " + newVol + ":" + result.getResult());
throw new StorageUnavailableException("Unable to create " + newVol + ":" + result.getResult(), destPool.getId());
}
}
final StoragePoolVO storagePool = this._storagePoolDao.findById(destPool.getId());
if (storagePool.isManaged()) {
final long hostId = vm.getVirtualMachine().getHostId();
final Host host = this._hostDao.findById(hostId);
this.volService.grantAccess(this.volFactory.getVolume(newVol.getId()), host, destPool);
}
newVol = this._volsDao.findById(newVol.getId());
// break out of template-redeploy retry loop
break;
} catch (final InterruptedException e) {
s_logger.error("Unable to create " + newVol, e);
throw new StorageUnavailableException("Unable to create " + newVol + ":" + e.toString(), destPool.getId());
} catch (final ExecutionException e) {
s_logger.error("Unable to create " + newVol, e);
throw new StorageUnavailableException("Unable to create " + newVol + ":" + e.toString(), destPool.getId());
}
}
return new Pair<>(newVol, destPool);
}
Aggregations