use of com.cloud.storage.DiskOfferingVO in project cloudstack by apache.
the class UserVmManagerImpl method upgradeRunningVirtualMachine.
private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingId, Map<String, String> customParameters) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException {
Account caller = CallContext.current().getCallingAccount();
VMInstanceVO vmInstance = _vmInstanceDao.findById(vmId);
Set<HypervisorType> supportedHypervisorTypes = new HashSet<>();
supportedHypervisorTypes.add(HypervisorType.XenServer);
supportedHypervisorTypes.add(HypervisorType.VMware);
supportedHypervisorTypes.add(HypervisorType.Simulator);
supportedHypervisorTypes.add(HypervisorType.KVM);
HypervisorType vmHypervisorType = vmInstance.getHypervisorType();
if (!supportedHypervisorTypes.contains(vmHypervisorType)) {
String message = String.format("Scaling the VM dynamically is not supported for VMs running on Hypervisor [%s].", vmInstance.getHypervisorType());
s_logger.info(message);
throw new InvalidParameterValueException(message);
}
_accountMgr.checkAccess(caller, null, true, vmInstance);
// Check if its a scale "up"
ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId);
if (newServiceOffering.isDynamic()) {
newServiceOffering.setDynamicFlag(true);
validateCustomParameters(newServiceOffering, customParameters);
newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters);
}
// Check that the specified service offering ID is valid
_itMgr.checkIfCanUpgrade(vmInstance, newServiceOffering);
ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
if (newServiceOffering.isDynamicScalingEnabled() != currentServiceOffering.isDynamicScalingEnabled()) {
throw new InvalidParameterValueException("Unable to Scale VM: since dynamic scaling enabled flag is not same for new service offering and old service offering");
}
validateDiskOfferingChecks(currentServiceOffering, newServiceOffering);
int newCpu = newServiceOffering.getCpu();
int newMemory = newServiceOffering.getRamSize();
int newSpeed = newServiceOffering.getSpeed();
int currentCpu = currentServiceOffering.getCpu();
int currentMemory = currentServiceOffering.getRamSize();
int currentSpeed = currentServiceOffering.getSpeed();
int memoryDiff = newMemory - currentMemory;
int cpuDiff = newCpu * newSpeed - currentCpu * currentSpeed;
// Don't allow to scale when (Any of the new values less than current values) OR (All current and new values are same)
if ((newSpeed < currentSpeed || newMemory < currentMemory || newCpu < currentCpu) || (newSpeed == currentSpeed && newMemory == currentMemory && newCpu == currentCpu)) {
String message = String.format("While the VM is running, only scalling up it is supported. New service offering {\"memory\": %s, \"speed\": %s, \"cpu\": %s} should" + " have at least one value (ram, speed or cpu) greater than the current values {\"memory\": %s, \"speed\": %s, \"cpu\": %s}.", newMemory, newSpeed, newCpu, currentMemory, currentSpeed, currentCpu);
throw new InvalidParameterValueException(message);
}
if (vmHypervisorType.equals(HypervisorType.KVM) && !currentServiceOffering.isDynamic()) {
String message = String.format("Unable to live scale VM on KVM when current service offering is a \"Fixed Offering\". KVM needs the tag \"maxMemory\" to live scale and it is only configured when VM is deployed with a custom service offering and \"Dynamic Scalable\" is enabled.");
s_logger.info(message);
throw new InvalidParameterValueException(message);
}
_offeringDao.loadDetails(currentServiceOffering);
_offeringDao.loadDetails(newServiceOffering);
Map<String, String> currentDetails = currentServiceOffering.getDetails();
Map<String, String> newDetails = newServiceOffering.getDetails();
String currentVgpuType = currentDetails.get("vgpuType");
String newVgpuType = newDetails.get("vgpuType");
if (currentVgpuType != null && (newVgpuType == null || !newVgpuType.equalsIgnoreCase(currentVgpuType))) {
throw new InvalidParameterValueException(String.format("Dynamic scaling of vGPU type is not supported. VM has vGPU Type: [%s].", currentVgpuType));
}
// Check resource limits
if (newCpu > currentCpu) {
_resourceLimitMgr.checkResourceLimit(caller, ResourceType.cpu, newCpu - currentCpu);
}
if (newMemory > currentMemory) {
_resourceLimitMgr.checkResourceLimit(caller, ResourceType.memory, memoryDiff);
}
// Dynamically upgrade the running vms
boolean success = false;
if (vmInstance.getState().equals(State.Running)) {
int retry = _scaleRetry;
ExcludeList excludes = new ExcludeList();
// Check zone wide flag
boolean enableDynamicallyScaleVm = EnableDynamicallyScaleVm.valueIn(vmInstance.getDataCenterId());
if (!enableDynamicallyScaleVm) {
throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin.");
}
// Check vm flag
if (!vmInstance.isDynamicallyScalable()) {
throw new CloudRuntimeException(String.format("Unable to scale %s as it does not have tools to support dynamic scaling.", vmInstance.toString()));
}
// Check disable threshold for cluster is not crossed
HostVO host = _hostDao.findById(vmInstance.getHostId());
if (_capacityMgr.checkIfClusterCrossesThreshold(host.getClusterId(), cpuDiff, memoryDiff)) {
throw new CloudRuntimeException(String.format("Unable to scale %s due to insufficient resources.", vmInstance.toString()));
}
while (retry-- != 0) {
// It's != so that it can match -1.
try {
boolean existingHostHasCapacity = false;
// Increment CPU and Memory count accordingly.
if (newCpu > currentCpu) {
_resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
}
if (memoryDiff > 0) {
_resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(memoryDiff));
}
// #1 Check existing host has capacity
if (!excludes.shouldAvoid(ApiDBUtils.findHostById(vmInstance.getHostId()))) {
existingHostHasCapacity = _capacityMgr.checkIfHostHasCpuCapability(vmInstance.getHostId(), newCpu, newSpeed) && _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), cpuDiff, ByteScaleUtils.mibToBytes(memoryDiff), false, _capacityMgr.getClusterOverProvisioningFactor(host.getClusterId(), Capacity.CAPACITY_TYPE_CPU), _capacityMgr.getClusterOverProvisioningFactor(host.getClusterId(), Capacity.CAPACITY_TYPE_MEMORY), false);
excludes.addHost(vmInstance.getHostId());
}
// #2 migrate the vm if host doesn't have capacity or is in avoid set
if (!existingHostHasCapacity) {
_itMgr.findHostAndMigrate(vmInstance.getUuid(), newServiceOfferingId, customParameters, excludes);
}
// #3 resize or migrate the root volume if required
DiskOfferingVO newDiskOffering = _diskOfferingDao.findById(newServiceOffering.getDiskOfferingId());
changeDiskOfferingForRootVolume(vmId, newDiskOffering, customParameters);
// #4 scale the vm now
vmInstance = _vmInstanceDao.findById(vmId);
_itMgr.reConfigureVm(vmInstance.getUuid(), currentServiceOffering, newServiceOffering, customParameters, existingHostHasCapacity);
success = true;
return success;
} catch (InsufficientCapacityException | ResourceUnavailableException | ConcurrentOperationException e) {
s_logger.error(String.format("Unable to scale %s due to [%s].", vmInstance.toString(), e.getMessage()), e);
} finally {
if (!success) {
// Decrement CPU and Memory count accordingly.
if (newCpu > currentCpu) {
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long(newCpu - currentCpu));
}
if (memoryDiff > 0) {
_resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long(memoryDiff));
}
}
}
}
}
return success;
}
use of com.cloud.storage.DiskOfferingVO in project cloudstack by apache.
the class UserVmManagerImpl method recoverVirtualMachine.
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_VM_RECOVER, eventDescription = "Recovering VM")
public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException, CloudRuntimeException {
final Long vmId = cmd.getId();
Account caller = CallContext.current().getCallingAccount();
final Long userId = caller.getAccountId();
// Verify input parameters
final UserVmVO vm = _vmDao.findById(vmId);
if (vm == null) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
// When trying to expunge, permission is denied when the caller is not an admin and the AllowUserExpungeRecoverVm is false for the caller.
if (!_accountMgr.isAdmin(userId) && !AllowUserExpungeRecoverVm.valueIn(userId)) {
throw new PermissionDeniedException("Recovering a vm can only be done by an Admin. Or when the allow.user.expunge.recover.vm key is set.");
}
if (vm.getRemoved() != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to find vm or vm is removed: " + vmId);
}
throw new InvalidParameterValueException("Unable to find vm by id " + vmId);
}
if (vm.getState() != State.Destroyed) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("vm is not in the right state: " + vmId);
}
throw new InvalidParameterValueException("Vm with id " + vmId + " is not in the right state");
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Recovering vm " + vmId);
}
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<ResourceAllocationException>() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) throws ResourceAllocationException {
Account account = _accountDao.lockRow(vm.getAccountId(), true);
// if the account is deleted, throw error
if (account.getRemoved() != null) {
throw new CloudRuntimeException("Unable to recover VM as the account is deleted");
}
// Get serviceOffering for Virtual Machine
ServiceOfferingVO serviceOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
// accountId will not be exceeded
if (!VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
resourceLimitCheck(account, vm.isDisplayVm(), new Long(serviceOffering.getCpu()), new Long(serviceOffering.getRamSize()));
}
_haMgr.cancelDestroy(vm, vm.getHostId());
try {
if (!_itMgr.stateTransitTo(vm, VirtualMachine.Event.RecoveryRequested, null)) {
s_logger.debug("Unable to recover the vm because it is not in the correct state: " + vmId);
throw new InvalidParameterValueException("Unable to recover the vm because it is not in the correct state: " + vmId);
}
} catch (NoTransitionException e) {
throw new InvalidParameterValueException("Unable to recover the vm because it is not in the correct state: " + vmId);
}
// Recover the VM's disks
List<VolumeVO> volumes = _volsDao.findByInstance(vmId);
for (VolumeVO volume : volumes) {
if (volume.getVolumeType().equals(Volume.Type.ROOT)) {
// Create an event
Long templateId = volume.getTemplateId();
Long diskOfferingId = volume.getDiskOfferingId();
Long offeringId = null;
if (diskOfferingId != null) {
DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
if (offering != null && !offering.isComputeOnly()) {
offeringId = offering.getId();
}
}
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), offeringId, templateId, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume());
}
}
// Update Resource Count for the given account
resourceCountIncrement(account.getId(), vm.isDisplayVm(), new Long(serviceOffering.getCpu()), new Long(serviceOffering.getRamSize()));
}
});
return _vmDao.findById(vmId);
}
use of com.cloud.storage.DiskOfferingVO in project cloudstack by apache.
the class UserVmManagerImpl method changeDiskOfferingForRootVolume.
private void changeDiskOfferingForRootVolume(Long vmId, DiskOfferingVO newDiskOffering, Map<String, String> customParameters) throws ResourceAllocationException {
List<VolumeVO> vols = _volsDao.findReadyAndAllocatedRootVolumesByInstance(vmId);
for (final VolumeVO rootVolumeOfVm : vols) {
DiskOfferingVO currentRootDiskOffering = _diskOfferingDao.findById(rootVolumeOfVm.getDiskOfferingId());
HypervisorType hypervisorType = _volsDao.getHypervisorType(rootVolumeOfVm.getId());
if (HypervisorType.Simulator != hypervisorType) {
Long minIopsInNewDiskOffering = null;
Long maxIopsInNewDiskOffering = null;
boolean autoMigrate = false;
boolean shrinkOk = false;
if (customParameters.containsKey(ApiConstants.MIN_IOPS)) {
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(ApiConstants.MIN_IOPS));
}
if (customParameters.containsKey(ApiConstants.MAX_IOPS)) {
minIopsInNewDiskOffering = Long.parseLong(customParameters.get(ApiConstants.MAX_IOPS));
}
if (customParameters.containsKey(ApiConstants.AUTO_MIGRATE)) {
autoMigrate = Boolean.parseBoolean(customParameters.get(ApiConstants.AUTO_MIGRATE));
}
if (customParameters.containsKey(ApiConstants.SHRINK_OK)) {
shrinkOk = Boolean.parseBoolean(customParameters.get(ApiConstants.SHRINK_OK));
}
ChangeOfferingForVolumeCmd changeOfferingForVolumeCmd = new ChangeOfferingForVolumeCmd(rootVolumeOfVm.getId(), newDiskOffering.getId(), minIopsInNewDiskOffering, maxIopsInNewDiskOffering, autoMigrate, shrinkOk);
Volume result = _volumeService.changeDiskOfferingForVolume(changeOfferingForVolumeCmd);
if (result == null) {
throw new CloudRuntimeException("Failed to change disk offering of the root volume");
}
} else if (newDiskOffering.getDiskSize() > 0 && currentRootDiskOffering.getDiskSize() != newDiskOffering.getDiskSize()) {
throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support volume resize");
}
}
}
use of com.cloud.storage.DiskOfferingVO in project cloudstack by apache.
the class DatabaseConfig method saveDiskOffering.
@DB
protected void saveDiskOffering() {
long id = Long.parseLong(_currentObjectParams.get("id"));
String name = _currentObjectParams.get("name");
String displayText = _currentObjectParams.get("displayText");
ProvisioningType provisioningType = ProvisioningType.valueOf(_currentObjectParams.get("provisioningtype"));
long diskSpace = Long.parseLong(_currentObjectParams.get("diskSpace"));
diskSpace = diskSpace * 1024 * 1024;
// boolean mirroring = Boolean.parseBoolean(_currentObjectParams.get("mirrored"));
String tags = _currentObjectParams.get("tags");
String useLocal = _currentObjectParams.get("useLocal");
boolean local = false;
if (useLocal != null) {
local = Boolean.parseBoolean(useLocal);
}
if (tags != null && tags.length() > 0) {
String[] tokens = tags.split(",");
StringBuilder newTags = new StringBuilder();
for (String token : tokens) {
newTags.append(token.trim()).append(",");
}
newTags.delete(newTags.length() - 1, newTags.length());
tags = newTags.toString();
}
DiskOfferingVO diskOffering = new DiskOfferingVO(name, displayText, provisioningType, diskSpace, tags, false, null, null, null);
diskOffering.setUseLocalStorage(local);
Long bytesReadRate = Long.parseLong(_currentObjectParams.get("bytesReadRate"));
if (bytesReadRate != null && (bytesReadRate > 0))
diskOffering.setBytesReadRate(bytesReadRate);
Long bytesWriteRate = Long.parseLong(_currentObjectParams.get("bytesWriteRate"));
if (bytesWriteRate != null && (bytesWriteRate > 0))
diskOffering.setBytesWriteRate(bytesWriteRate);
Long iopsReadRate = Long.parseLong(_currentObjectParams.get("iopsReadRate"));
if (iopsReadRate != null && (iopsReadRate > 0))
diskOffering.setIopsReadRate(iopsReadRate);
Long iopsWriteRate = Long.parseLong(_currentObjectParams.get("iopsWriteRate"));
if (iopsWriteRate != null && (iopsWriteRate > 0))
diskOffering.setIopsWriteRate(iopsWriteRate);
DiskOfferingDaoImpl offering = ComponentContext.inject(DiskOfferingDaoImpl.class);
try {
offering.persist(diskOffering);
} catch (Exception e) {
s_logger.error("error creating disk offering", e);
}
/*
String insertSql = "INSERT INTO `cloud`.`disk_offering` (id, domain_id, name, display_text, disk_size, mirrored, tags) " +
"VALUES (" + id + "," + domainId + ",'" + name + "','" + displayText + "'," + diskSpace + "," + mirroring + ", ? )";
Transaction txn = Transaction.currentTxn();
try {
PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql);
stmt.setString(1, tags);
stmt.executeUpdate();
} catch (SQLException ex) {
s_logger.error("error creating disk offering", ex);
return;
}
*/
}
use of com.cloud.storage.DiskOfferingVO 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(Long.valueOf(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;
}
Aggregations