use of com.cloud.engine.subsystem.api.storage.VolumeInfo in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method liveMigrateVolume.
@DB
protected Volume liveMigrateVolume(final Volume volume, final StoragePool destPool) throws StorageUnavailableException {
final VolumeInfo vol = volFactory.getVolume(volume.getId(), true);
final AsyncCallFuture<VolumeApiResult> future = volService.migrateVolume(vol, (DataStore) destPool);
try {
final VolumeApiResult result = future.get();
if (result.isFailed()) {
s_logger.debug("Live migrate volume failed:" + result.getResult());
throw new StorageUnavailableException("Live migrate volume failed: " + result.getResult(), destPool.getId());
}
return result.getVolume();
} catch (final InterruptedException e) {
s_logger.debug("Live migrate volume failed", e);
throw new CloudRuntimeException(e.getMessage());
} catch (final ExecutionException e) {
s_logger.debug("Live migrate volume failed", e);
throw new CloudRuntimeException(e.getMessage());
}
}
use of com.cloud.engine.subsystem.api.storage.VolumeInfo in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method orchestrateAttachVolumeToVM.
private Volume orchestrateAttachVolumeToVM(final Long vmId, final Long volumeId, final Long deviceId) {
final VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
if (volumeToAttach.isAttachedVM()) {
throw new CloudRuntimeException("This volume is already attached to a VM.");
}
UserVmVO vm = _userVmDao.findById(vmId);
VolumeVO exstingVolumeOfVm = null;
final List<VolumeVO> rootVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.ROOT);
if (rootVolumesOfVm.size() > 1) {
throw new CloudRuntimeException("The VM " + vm.getHostName() + " has more than one ROOT volume and is in an invalid state.");
} else {
if (!rootVolumesOfVm.isEmpty()) {
exstingVolumeOfVm = rootVolumesOfVm.get(0);
} else {
// locate data volume of the vm
final List<VolumeVO> diskVolumesOfVm = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
for (final VolumeVO diskVolume : diskVolumesOfVm) {
if (diskVolume.getState() != Volume.State.Allocated) {
exstingVolumeOfVm = diskVolume;
break;
}
}
}
}
final HypervisorType rootDiskHyperType = vm.getHypervisorType();
final HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
VolumeInfo newVolumeOnPrimaryStorage = volumeToAttach;
// don't create volume on primary storage if its being attached to the vm which Root's volume hasn't been created yet
StoragePoolVO destPrimaryStorage = null;
if (exstingVolumeOfVm != null && !exstingVolumeOfVm.getState().equals(Volume.State.Allocated)) {
destPrimaryStorage = _storagePoolDao.findById(exstingVolumeOfVm.getPoolId());
}
final boolean volumeOnSecondary = volumeToAttach.getState() == Volume.State.Uploaded;
if (destPrimaryStorage != null && (volumeToAttach.getState() == Volume.State.Allocated || volumeOnSecondary)) {
try {
newVolumeOnPrimaryStorage = _volumeMgr.createVolumeOnPrimaryStorage(vm, volumeToAttach, rootDiskHyperType, destPrimaryStorage);
} catch (final NoTransitionException e) {
s_logger.debug("Failed to create volume on primary storage", e);
throw new CloudRuntimeException("Failed to create volume on primary storage", e);
}
}
// reload the volume from db
newVolumeOnPrimaryStorage = volFactory.getVolume(newVolumeOnPrimaryStorage.getId());
final boolean moveVolumeNeeded = needMoveVolume(exstingVolumeOfVm, newVolumeOnPrimaryStorage);
if (moveVolumeNeeded) {
final PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo) newVolumeOnPrimaryStorage.getDataStore();
if (primaryStore.isLocal()) {
throw new CloudRuntimeException("Failed to attach local data volume " + volumeToAttach.getName() + " to VM " + vm.getDisplayName() + " as migration of local data volume is not allowed");
}
final StoragePoolVO vmRootVolumePool = _storagePoolDao.findById(exstingVolumeOfVm.getPoolId());
try {
newVolumeOnPrimaryStorage = _volumeMgr.moveVolume(newVolumeOnPrimaryStorage, vmRootVolumePool.getDataCenterId(), vmRootVolumePool.getPodId(), vmRootVolumePool.getClusterId(), volumeToAttachHyperType);
} catch (final ConcurrentOperationException e) {
s_logger.debug("move volume failed", e);
throw new CloudRuntimeException("move volume failed", e);
} catch (final StorageUnavailableException e) {
s_logger.debug("move volume failed", e);
throw new CloudRuntimeException("move volume failed", e);
}
}
VolumeVO newVol = _volsDao.findById(newVolumeOnPrimaryStorage.getId());
// Getting the fresh vm object in case of volume migration to check the current state of VM
if (moveVolumeNeeded || volumeOnSecondary) {
vm = _userVmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("VM not found.");
}
}
newVol = sendAttachVolumeCommand(vm, newVol, deviceId);
return newVol;
}
use of com.cloud.engine.subsystem.api.storage.VolumeInfo in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method createVolume.
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_CREATE, eventDescription = "creating volume", async = true)
public VolumeVO createVolume(final CreateVolumeCmd cmd) {
VolumeVO volume = _volsDao.findById(cmd.getEntityId());
boolean created = true;
try {
if (cmd.getSnapshotId() != null) {
volume = createVolumeFromSnapshot(volume, cmd.getSnapshotId(), cmd.getVirtualMachineId());
if (volume.getState() != Volume.State.Ready) {
created = false;
}
// if VM Id is provided, attach the volume to the VM
if (cmd.getVirtualMachineId() != null) {
try {
attachVolumeToVM(cmd.getVirtualMachineId(), volume.getId(), volume.getDeviceId());
} catch (final Exception ex) {
final StringBuilder message = new StringBuilder("Volume: ");
message.append(volume.getUuid());
message.append(" created successfully, but failed to attach the newly created volume to VM: ");
message.append(cmd.getVirtualMachineId());
message.append(" due to error: ");
message.append(ex.getMessage());
if (s_logger.isDebugEnabled()) {
s_logger.debug(message.toString());
}
throw new CloudRuntimeException(message.toString());
}
}
}
return volume;
} catch (final Exception e) {
created = false;
final VolumeInfo vol = volFactory.getVolume(cmd.getEntityId());
vol.stateTransit(Volume.Event.DestroyRequested);
throw new CloudRuntimeException("Failed to create volume: " + volume.getId(), e);
} finally {
if (!created) {
s_logger.trace("Decrementing volume resource count for account id=" + volume.getAccountId() + " as volume failed to create on the backend");
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, cmd.getDisplayVolume());
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), ResourceType.primary_storage.getOrdinal());
}
}
}
use of com.cloud.engine.subsystem.api.storage.VolumeInfo in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method deleteVolume.
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_DELETE, eventDescription = "deleting volume")
public boolean deleteVolume(final long volumeId, final Account caller) throws ConcurrentOperationException {
final VolumeVO volume = _volsDao.findById(volumeId);
if (volume == null) {
throw new InvalidParameterValueException("Unable to find volume with ID: " + volumeId);
}
if (!_snapshotMgr.canOperateOnVolume(volume)) {
throw new InvalidParameterValueException("There are snapshot operations in progress on the volume, unable to delete it");
}
_accountMgr.checkAccess(caller, null, true, volume);
if (volume.getInstanceId() != null) {
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
}
if (volume.getState() == Volume.State.UploadOp) {
final VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(volume.getId());
if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
throw new InvalidParameterValueException("Please specify a volume that is not uploading");
}
}
if (volume.getState() == Volume.State.NotUploaded || volume.getState() == Volume.State.UploadInProgress) {
throw new InvalidParameterValueException("The volume is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
}
try {
if (volume.getState() != Volume.State.Destroy && volume.getState() != Volume.State.Expunging && volume.getState() != Volume.State.Expunged) {
final Long instanceId = volume.getInstanceId();
if (!volService.destroyVolume(volume.getId())) {
return false;
}
final VMInstanceVO vmInstance = _vmInstanceDao.findById(instanceId);
if (instanceId == null || vmInstance.getType().equals(VirtualMachine.Type.User)) {
// Decrement the resource count for volumes and primary storage belonging user VM's only
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
}
}
// Mark volume as removed if volume has not been created on primary or secondary
if (volume.getState() == Volume.State.Allocated) {
_volsDao.remove(volumeId);
stateTransitTo(volume, Volume.Event.DestroyRequested);
return true;
}
// expunge volume from primary if volume is on primary
final VolumeInfo volOnPrimary = volFactory.getVolume(volume.getId(), DataStoreRole.Primary);
if (volOnPrimary != null) {
s_logger.info("Expunging volume " + volume.getId() + " from primary data store");
final AsyncCallFuture<VolumeApiResult> future = volService.expungeVolumeAsync(volOnPrimary);
future.get();
// decrement primary storage count
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), ResourceType.primary_storage.getOrdinal());
}
// expunge volume from secondary if volume is on image store
final VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image);
if (volOnSecondary != null) {
s_logger.info("Expunging volume " + volume.getId() + " from secondary data store");
final AsyncCallFuture<VolumeApiResult> future2 = volService.expungeVolumeAsync(volOnSecondary);
future2.get();
// decrement secondary storage count
_resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), ResourceType.secondary_storage.getOrdinal());
}
// delete all cache entries for this volume
final List<VolumeInfo> cacheVols = volFactory.listVolumeOnCache(volume.getId());
for (final VolumeInfo volOnCache : cacheVols) {
s_logger.info("Delete volume from image cache store: " + volOnCache.getDataStore().getName());
volOnCache.delete();
}
} catch (InterruptedException | ExecutionException | NoTransitionException e) {
s_logger.warn("Failed to expunge volume:", e);
return false;
}
return true;
}
use of com.cloud.engine.subsystem.api.storage.VolumeInfo in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method uploadVolume.
@Override
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_UPLOAD, eventDescription = "uploading volume for post upload", async = true)
public GetUploadParamsResponse uploadVolume(final GetUploadParamsForVolumeCmd cmd) throws ResourceAllocationException, MalformedURLException {
final Account caller = CallContext.current().getCallingAccount();
final long ownerId = cmd.getEntityOwnerId();
final Account owner = _entityMgr.findById(Account.class, ownerId);
final Long zoneId = cmd.getZoneId();
final String volumeName = cmd.getName();
final String format = cmd.getFormat();
final Long diskOfferingId = cmd.getDiskOfferingId();
final String imageStoreUuid = cmd.getImageStoreUuid();
final DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId);
validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId);
return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
@Override
public GetUploadParamsResponse doInTransaction(final TransactionStatus status) throws MalformedURLException {
final VolumeVO volume = persistVolume(owner, zoneId, volumeName, null, cmd.getFormat(), diskOfferingId, Volume.State.NotUploaded);
final VolumeInfo vol = volFactory.getVolume(volume.getId());
final RegisterVolumePayload payload = new RegisterVolumePayload(null, cmd.getChecksum(), cmd.getFormat());
vol.addPayload(payload);
final Pair<EndPoint, DataObject> pair = volService.registerVolumeForPostUpload(vol, store);
final EndPoint ep = pair.first();
final DataObject dataObject = pair.second();
final GetUploadParamsResponse response = new GetUploadParamsResponse();
final String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key());
final String url = ImageStoreUtil.generatePostUploadUrl(ssvmUrlDomain, ep.getPublicAddr(), vol.getUuid());
response.setPostURL(new URL(url));
// set the post url, this is used in the monitoring thread to determine the SSVM
final VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(vol.getId());
assert volumeStore != null : "sincle volume is registered, volumestore cannot be null at this stage";
volumeStore.setExtractUrl(url);
_volumeStoreDao.persist(volumeStore);
response.setId(UUID.fromString(vol.getUuid()));
final int timeout = ImageStoreUploadMonitorImpl.getUploadOperationTimeout();
final DateTime currentDateTime = new DateTime(DateTimeZone.UTC);
final String expires = currentDateTime.plusMinutes(timeout).toString();
response.setTimeout(expires);
final String key = _configDao.getValue(Config.SSVMPSK.key());
/*
* encoded metadata using the post upload config key
*/
final TemplateOrVolumePostUploadCommand command = new TemplateOrVolumePostUploadCommand(vol.getId(), vol.getUuid(), volumeStore.getInstallPath(), cmd.getChecksum(), vol.getType().toString(), vol.getName(), vol.getFormat().toString(), dataObject.getDataStore().getUri(), dataObject.getDataStore().getRole().toString());
command.setLocalPath(volumeStore.getLocalDownloadPath());
// using the existing max upload size configuration
command.setMaxUploadSize(_configDao.getValue(Config.MaxUploadVolumeSize.key()));
command.setDefaultMaxAccountSecondaryStorage(_configDao.getValue(Config.DefaultMaxAccountSecondaryStorage.key()));
command.setAccountId(vol.getAccountId());
final Gson gson = new GsonBuilder().create();
final String metadata = EncryptionUtil.encodeData(gson.toJson(command), key);
response.setMetadata(metadata);
/*
* signature calculated on the url, expiry, metadata.
*/
response.setSignature(EncryptionUtil.generateSignature(metadata + url + expires, key));
return response;
}
});
}
Aggregations