You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2026/04/13 08:29:25 UTC
(cloudstack) 23/25: Implement/fix limit validation for secondary storage
This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 22.0.1-fixes
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit e8d57d1b0dc173ef55c6386f91f1d77b8b8c9830
Author: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
AuthorDate: Sun Feb 22 10:44:24 2026 -0300
Implement/fix limit validation for secondary storage
---
.../manager/BareMetalTemplateAdapter.java | 1 -
.../cloud/storage/ImageStoreUploadMonitorImpl.java | 17 +
.../com/cloud/storage/VolumeApiServiceImpl.java | 551 ++++++++++-----------
.../cloud/template/HypervisorTemplateAdapter.java | 129 +++--
.../com/cloud/template/TemplateAdapterBase.java | 38 +-
.../com/cloud/template/TemplateManagerImpl.java | 437 ++++++++--------
.../cloud/template/TemplateManagerImplTest.java | 134 ++---
7 files changed, 687 insertions(+), 620 deletions(-)
diff --git a/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java b/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
index 940897de3c9..c6c38a39809 100644
--- a/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
+++ b/plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/manager/BareMetalTemplateAdapter.java
@@ -106,7 +106,6 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem
}
}
- _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
return template;
}
diff --git a/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java b/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java
index 06da14e4e1c..5c6f8dc6599 100755
--- a/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java
+++ b/server/src/main/java/com/cloud/storage/ImageStoreUploadMonitorImpl.java
@@ -63,6 +63,7 @@ import com.cloud.configuration.Resource;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.ConnectionException;
+import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.Host;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
@@ -543,6 +544,22 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
break;
}
}
+
+ Account owner = accountDao.findById(template.getAccountId());
+ long templateSize = answer.getVirtualSize();
+
+ try (CheckedReservation secondaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.secondary_storage, null, null, templateSize, reservationDao, _resourceLimitMgr)) {
+ _resourceLimitMgr.incrementResourceCount(owner.getId(), Resource.ResourceType.secondary_storage, templateSize);
+ } catch (ResourceAllocationException e) {
+ tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOAD_ERROR);
+ tmpTemplateDataStore.setState(State.Failed);
+ stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
+ msg = String.format("Upload of template [%s] failed because its owner [%s] does not have enough secondary storage space available.", template.getUuid(), owner.getUuid());
+ logger.warn(msg);
+ sendAlert = true;
+ break;
+ }
+
stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationSucceeded, null, _templateDao);
//publish usage event
String etype = EventTypes.EVENT_TEMPLATE_CREATE;
diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index d50b0ebdf7a..5861f7ced43 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -35,7 +35,6 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
-import com.cloud.resourcelimit.ReservationHelper;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.InternalIdentity;
@@ -111,6 +110,7 @@ import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.cloudstack.utils.imagestore.ImageStoreUtil;
import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
@@ -169,6 +169,7 @@ import com.cloud.projects.ProjectManager;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
import com.cloud.resourcelimit.CheckedReservation;
+import com.cloud.resourcelimit.ReservationHelper;
import com.cloud.serializer.GsonHelper;
import com.cloud.server.ManagementService;
import com.cloud.server.ResourceTag;
@@ -356,10 +357,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
private ManagementService managementService;
@Inject
protected SnapshotHelper snapshotHelper;
-
@Inject
protected DomainDao domainDao;
-
@Inject
protected ProjectManager projectManager;
@Inject
@@ -374,7 +373,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
EndPointSelector _epSelector;
@Inject
private ReservationDao reservationDao;
-
@Inject
private VMSnapshotDetailsDao vmSnapshotDetailsDao;
@@ -499,76 +497,77 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
List<Reserver> reservations = new ArrayList<>();
try {
- validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId, reservations);
-
- return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
- @Override
- public GetUploadParamsResponse doInTransaction(TransactionStatus status) throws MalformedURLException {
-
- VolumeVO volume = persistVolume(owner, zoneId, volumeName, null, format, diskOfferingId, Volume.State.NotUploaded);
-
- final DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId, volume);
-
- VolumeInfo vol = volFactory.getVolume(volume.getId());
-
- RegisterVolumePayload payload = new RegisterVolumePayload(null, cmd.getChecksum(), format);
- vol.addPayload(payload);
+ validateVolume(caller, ownerId, zoneId, volumeName, null, format, diskOfferingId, reservations);
- Pair<EndPoint, DataObject> pair = volService.registerVolumeForPostUpload(vol, store);
- EndPoint ep = pair.first();
- DataObject dataObject = pair.second();
-
- GetUploadParamsResponse response = new GetUploadParamsResponse();
-
- String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key());
- String protocol = UseHttpsToUpload.value() ? "https" : "http";
-
- String url = ImageStoreUtil.generatePostUploadUrl(ssvmUrlDomain, ep.getPublicAddr(), vol.getUuid(), protocol);
- response.setPostURL(new URL(url));
-
- // set the post url, this is used in the monitoring thread to determine the SSVM
- 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()));
-
- int timeout = ImageStoreUploadMonitorImpl.getUploadOperationTimeout();
- DateTime currentDateTime = new DateTime(DateTimeZone.UTC);
- String expires = currentDateTime.plusMinutes(timeout).toString();
- response.setTimeout(expires);
-
- String key = _configDao.getValue(Config.SSVMPSK.key());
- /*
- * encoded metadata using the post upload config key
- */
- 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.setProcessTimeout(NumbersUtil.parseLong(_configDao.getValue("vmware.package.ova.timeout"), 3600));
- command.setMaxUploadSize(_configDao.getValue(Config.MaxUploadVolumeSize.key()));
-
- long accountId = vol.getAccountId();
- Account account = _accountDao.findById(accountId);
- Domain domain = domainDao.findById(account.getDomainId());
-
- // one of the two following might have to be removed
- command.setDefaultMaxSecondaryStorageInGB(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
- command.setDefaultMaxSecondaryStorageInBytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
- command.setAccountId(accountId);
- Gson gson = new GsonBuilder().create();
- 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;
- }
- });
+ return Transaction.execute(new TransactionCallbackWithException<GetUploadParamsResponse, MalformedURLException>() {
+ @Override
+ public GetUploadParamsResponse doInTransaction(TransactionStatus status) throws MalformedURLException {
+
+ VolumeVO volume = persistVolume(owner, zoneId, volumeName, null, format, diskOfferingId, Volume.State.NotUploaded);
+
+ final DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId, volume);
+
+ VolumeInfo vol = volFactory.getVolume(volume.getId());
+
+ RegisterVolumePayload payload = new RegisterVolumePayload(null, cmd.getChecksum(), format);
+ vol.addPayload(payload);
+
+ Pair<EndPoint, DataObject> pair = volService.registerVolumeForPostUpload(vol, store);
+ EndPoint ep = pair.first();
+ DataObject dataObject = pair.second();
+
+ GetUploadParamsResponse response = new GetUploadParamsResponse();
+
+ String ssvmUrlDomain = _configDao.getValue(Config.SecStorageSecureCopyCert.key());
+ String protocol = UseHttpsToUpload.value() ? "https" : "http";
+
+ String url = ImageStoreUtil.generatePostUploadUrl(ssvmUrlDomain, ep.getPublicAddr(), vol.getUuid(), protocol);
+ response.setPostURL(new URL(url));
+
+ // set the post url, this is used in the monitoring thread to determine the SSVM
+ 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()));
+
+ int timeout = ImageStoreUploadMonitorImpl.getUploadOperationTimeout();
+ DateTime currentDateTime = new DateTime(DateTimeZone.UTC);
+ String expires = currentDateTime.plusMinutes(timeout).toString();
+ response.setTimeout(expires);
+
+ String key = _configDao.getValue(Config.SSVMPSK.key());
+ /*
+ * encoded metadata using the post upload config key
+ */
+ 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.setProcessTimeout(NumbersUtil.parseLong(_configDao.getValue("vmware.package.ova.timeout"), 3600));
+ command.setMaxUploadSize(_configDao.getValue(Config.MaxUploadVolumeSize.key()));
+
+ long accountId = vol.getAccountId();
+ Account account = _accountDao.findById(accountId);
+ Domain domain = domainDao.findById(account.getDomainId());
+
+ // one of the two following might have to be removed
+ command.setDefaultMaxSecondaryStorageInGB(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
+ command.setDefaultMaxSecondaryStorageInGB(ByteScaleUtils.bytesToGibibytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null)));
+ command.setDefaultMaxSecondaryStorageInBytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null));
+ command.setAccountId(accountId);
+ Gson gson = new GsonBuilder().create();
+ 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;
+ }
+ });
} finally {
ReservationHelper.closeAll(reservations);
@@ -967,29 +966,29 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
List<Reserver> reservations = new ArrayList<>();
try {
- _resourceLimitMgr.checkVolumeResourceLimit(owner, displayVolume, size, diskOffering, reservations);
+ _resourceLimitMgr.checkVolumeResourceLimit(owner, displayVolume, size, diskOffering, reservations);
- // Verify that zone exists
- DataCenterVO zone = _dcDao.findById(zoneId);
- if (zone == null) {
- throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
- }
+ // Verify that zone exists
+ DataCenterVO zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
+ }
- // Check if zone is disabled
- if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
- throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone: %s is currently disabled", zone));
- }
+ // Check if zone is disabled
+ if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getId())) {
+ throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone: %s is currently disabled", zone));
+ }
- // If local storage is disabled then creation of volume with local disk
- // offering not allowed
- if (!zone.isLocalStorageEnabled() && diskOffering.isUseLocalStorage()) {
- throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
- }
+ // If local storage is disabled then creation of volume with local disk
+ // offering not allowed
+ if (!zone.isLocalStorageEnabled() && diskOffering.isUseLocalStorage()) {
+ throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
+ }
- String userSpecifiedName = getVolumeNameFromCommand(cmd);
+ String userSpecifiedName = getVolumeNameFromCommand(cmd);
- return commitVolume(cmd.getSnapshotId(), caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName,
- _uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
+ return commitVolume(cmd.getSnapshotId(), caller, owner, displayVolume, zoneId, diskOfferingId, provisioningType, size, minIops, maxIops, parentVolume, userSpecifiedName,
+ _uuidMgr.generateUuid(Volume.class, cmd.getCustomId()), details);
} finally {
ReservationHelper.closeAll(reservations);
}
@@ -1320,134 +1319,134 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
List<Reserver> reservations = new ArrayList<>();
try {
- validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering, reservations);
+ validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering, reservations);
- // Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
- // the requested change
+ // Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform
+ // the requested change
- /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
- // We need to publish this event to usage_volume table
- if (volume.getState() == Volume.State.Allocated) {
- logger.debug("Volume is in the allocated state, but has never been created. Simply updating database with new size and IOPS.");
+ /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
+ // We need to publish this event to usage_volume table
+ if (volume.getState() == Volume.State.Allocated) {
+ logger.debug("Volume is in the allocated state, but has never been created. Simply updating database with new size and IOPS.");
- volume.setSize(newSize);
- volume.setMinIops(newMinIops);
- volume.setMaxIops(newMaxIops);
- volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
+ volume.setSize(newSize);
+ volume.setMinIops(newMinIops);
+ volume.setMaxIops(newMaxIops);
+ volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
- if (newDiskOffering != null) {
- volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
- }
+ if (newDiskOffering != null) {
+ volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
+ }
- _volsDao.update(volume.getId(), volume);
- _resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
- diskOffering, newDiskOffering);
- UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
- volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
- return volume;
- }
+ _volsDao.update(volume.getId(), volume);
+ _resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
+ diskOffering, newDiskOffering);
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
+ volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
+ return volume;
+ }
- Long newDiskOfferingId = newDiskOffering != null ? newDiskOffering.getId() : diskOffering.getId();
+ Long newDiskOfferingId = newDiskOffering != null ? newDiskOffering.getId() : diskOffering.getId();
- boolean volumeMigrateRequired = false;
- List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = null;
- StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
- if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) {
- if (!autoMigrateVolume) {
- throw new CloudRuntimeException(String.format("Failed to resize volume %s since the storage pool does not have enough space to accommodate new size for the volume %s, try with automigrate set to true in order to check in the other suitable pools for the new size and then migrate & resize volume there.", volume.getUuid(), volume.getName()));
- }
- Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOfferingId, currentSize, newMinIops, newMaxIops, true, false);
- List<? extends StoragePool> suitableStoragePools = poolsPair.second();
- if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering or new size", volume.getUuid()));
- }
- final Long newSizeFinal = newSize;
- suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
- if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) with enough space found.", volume.getUuid()));
+ boolean volumeMigrateRequired = false;
+ List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = null;
+ StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
+ if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) {
+ if (!autoMigrateVolume) {
+ throw new CloudRuntimeException(String.format("Failed to resize volume %s since the storage pool does not have enough space to accommodate new size for the volume %s, try with automigrate set to true in order to check in the other suitable pools for the new size and then migrate & resize volume there.", volume.getUuid(), volume.getName()));
+ }
+ Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOfferingId, currentSize, newMinIops, newMaxIops, true, false);
+ List<? extends StoragePool> suitableStoragePools = poolsPair.second();
+ if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering or new size", volume.getUuid()));
+ }
+ final Long newSizeFinal = newSize;
+ suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) with enough space found.", volume.getUuid()));
+ }
+ Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
+ volumeMigrateRequired = true;
}
- Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
- volumeMigrateRequired = true;
- }
- boolean volumeResizeRequired = false;
- if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
- volumeResizeRequired = true;
- }
- if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
- _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
- volume = _volsDao.findById(volume.getId());
- updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
+ boolean volumeResizeRequired = false;
+ if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
+ volumeResizeRequired = true;
+ }
+ if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
+ _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
+ volume = _volsDao.findById(volume.getId());
+ updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
- return volume;
- }
+ return volume;
+ }
- if (volumeMigrateRequired) {
- MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOfferingId, true);
- try {
- Volume result = migrateVolume(migrateVolumeCmd);
- volume = (result != null) ? _volsDao.findById(result.getId()) : null;
- if (volume == null) {
+ if (volumeMigrateRequired) {
+ MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOfferingId, true);
+ try {
+ Volume result = migrateVolume(migrateVolumeCmd);
+ volume = (result != null) ? _volsDao.findById(result.getId()) : null;
+ if (volume == null) {
+ throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
+ }
+ } catch (Exception e) {
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
}
- } catch (Exception e) {
- throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
}
- }
- UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
+ UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
- if (userVm != null) {
- // serialize VM operation
- AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+ if (userVm != null) {
+ // serialize VM operation
+ AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
- if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
- // avoid re-entrance
+ if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+ // avoid re-entrance
- VmWorkJobVO placeHolder = null;
+ VmWorkJobVO placeHolder = null;
- placeHolder = createPlaceHolderWork(userVm.getId());
+ placeHolder = createPlaceHolderWork(userVm.getId());
- try {
- return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
+ try {
+ return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
+ newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
+ } finally {
+ _workJobDao.expunge(placeHolder.getId());
+ }
+ } else {
+ Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
- } finally {
- _workJobDao.expunge(placeHolder.getId());
- }
- } else {
- Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve,
- newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
- try {
- outcome.get();
- } catch (InterruptedException e) {
- throw new RuntimeException("Operation was interrupted", e);
- } catch (ExecutionException e) {
- throw new RuntimeException("Execution exception", e);
- }
-
- Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+ try {
+ outcome.get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Operation was interrupted", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Execution exception", e);
+ }
- if (jobResult != null) {
- if (jobResult instanceof ConcurrentOperationException) {
- throw (ConcurrentOperationException) jobResult;
- } else if (jobResult instanceof ResourceAllocationException) {
- throw (ResourceAllocationException) jobResult;
- } else if (jobResult instanceof RuntimeException) {
- throw (RuntimeException) jobResult;
- } else if (jobResult instanceof Throwable) {
- throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
- } else if (jobResult instanceof Long) {
- return _volsDao.findById((Long) jobResult);
+ Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+
+ if (jobResult != null) {
+ if (jobResult instanceof ConcurrentOperationException) {
+ throw (ConcurrentOperationException) jobResult;
+ } else if (jobResult instanceof ResourceAllocationException) {
+ throw (ResourceAllocationException) jobResult;
+ } else if (jobResult instanceof RuntimeException) {
+ throw (RuntimeException) jobResult;
+ } else if (jobResult instanceof Throwable) {
+ throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
+ } else if (jobResult instanceof Long) {
+ return _volsDao.findById((Long) jobResult);
+ }
}
- }
- return volume;
+ return volume;
+ }
}
- }
- return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null,
- shrinkOk);
+ return orchestrateResizeVolume(volume.getId(), currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, newDiskOffering != null ? cmd.getNewDiskOfferingId() : null,
+ shrinkOk);
} finally {
ReservationHelper.closeAll(reservations);
@@ -1912,17 +1911,17 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
List<Reserver> reservations = new ArrayList<>();
try {
- _resourceLimitMgr.checkVolumeResourceLimit(_accountMgr.getAccount(volume.getAccountId()), volume.isDisplayVolume(), volume.getSize(), diskOffering, reservations);
+ _resourceLimitMgr.checkVolumeResourceLimit(_accountMgr.getAccount(volume.getAccountId()), volume.isDisplayVolume(), volume.getSize(), diskOffering, reservations);
- try {
- _volsDao.detachVolume(volume.getId());
- stateTransitTo(volume, Volume.Event.RecoverRequested);
- } catch (NoTransitionException e) {
- logger.debug("Failed to recover volume {}", volume, e);
- throw new CloudRuntimeException(String.format("Failed to recover volume %s", volume), e);
- }
- _resourceLimitMgr.incrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(),
- volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
+ try {
+ _volsDao.detachVolume(volume.getId());
+ stateTransitTo(volume, Volume.Event.RecoverRequested);
+ } catch (NoTransitionException e) {
+ logger.debug("Failed to recover volume {}", volume, e);
+ throw new CloudRuntimeException(String.format("Failed to recover volume %s", volume), e);
+ }
+ _resourceLimitMgr.incrementVolumeResourceCount(volume.getAccountId(), volume.isDisplay(),
+ volume.getSize(), _diskOfferingDao.findById(volume.getDiskOfferingId()));
} catch (ResourceAllocationException e) {
logger.error("primary storage resource limit check failed", e);
@@ -2161,96 +2160,96 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
List<Reserver> reservations = new ArrayList<>();
try {
- validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering, reservations);
+ validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering, reservations);
- /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
- // We need to publish this event to usage_volume table
- if (volume.getState() == Volume.State.Allocated) {
- logger.debug("Volume {} is in the allocated state, but has never been created. Simply updating database with new size and IOPS.", volume);
+ /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */
+ // We need to publish this event to usage_volume table
+ if (volume.getState() == Volume.State.Allocated) {
+ logger.debug("Volume {} is in the allocated state, but has never been created. Simply updating database with new size and IOPS.", volume);
- volume.setSize(newSize);
- volume.setMinIops(newMinIops);
- volume.setMaxIops(newMaxIops);
- volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
+ volume.setSize(newSize);
+ volume.setMinIops(newMinIops);
+ volume.setMaxIops(newMaxIops);
+ volume.setHypervisorSnapshotReserve(newHypervisorSnapshotReserve);
- if (newDiskOffering != null) {
- volume.setDiskOfferingId(newDiskOfferingId);
- _volumeMgr.saveVolumeDetails(newDiskOfferingId, volume.getId());
- }
+ if (newDiskOffering != null) {
+ volume.setDiskOfferingId(newDiskOfferingId);
+ _volumeMgr.saveVolumeDetails(newDiskOfferingId, volume.getId());
+ }
- _volsDao.update(volume.getId(), volume);
- _resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
- existingDiskOffering, newDiskOffering);
+ _volsDao.update(volume.getId(), volume);
+ _resourceLimitMgr.updateVolumeResourceCountForDiskOfferingChange(volume.getAccountId(), volume.isDisplayVolume(), currentSize, newSize,
+ existingDiskOffering, newDiskOffering);
- if (currentSize != newSize) {
- UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
- volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
+ if (currentSize != newSize) {
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_RESIZE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(),
+ volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid());
+ }
+ return volume;
}
- return volume;
- }
- if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
- volumeResizeRequired = true;
- validateVolumeReadyStateAndHypervisorChecks(volume, currentSize, newSize);
- }
+ if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
+ volumeResizeRequired = true;
+ validateVolumeReadyStateAndHypervisorChecks(volume, currentSize, newSize);
+ }
- StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId());
+ StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId());
- Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), currentSize, newMinIops, newMaxIops, true, false);
- List<? extends StoragePool> suitableStoragePools = poolsPair.second();
+ Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), currentSize, newMinIops, newMaxIops, true, false);
+ List<? extends StoragePool> suitableStoragePools = poolsPair.second();
- if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) {
- volumeMigrateRequired = true;
- if (!autoMigrateVolume) {
- throw new InvalidParameterValueException(String.format("Failed to change offering for volume %s since automigrate is set to false but volume needs to migrated", volume.getUuid()));
+ if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) {
+ volumeMigrateRequired = true;
+ if (!autoMigrateVolume) {
+ throw new InvalidParameterValueException(String.format("Failed to change offering for volume %s since automigrate is set to false but volume needs to migrated", volume.getUuid()));
+ }
}
- }
-
- if (!volumeMigrateRequired && !volumeResizeRequired) {
- _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
- volume = _volsDao.findById(volume.getId());
- updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
- return volume;
- }
+ if (!volumeMigrateRequired && !volumeResizeRequired) {
+ _volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
+ volume = _volsDao.findById(volume.getId());
+ updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
- if (volumeMigrateRequired) {
- if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) found for migrating to support new disk offering", volume));
- }
- final Long newSizeFinal = newSize;
- List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
- if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
- throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) with enough space found for volume migration.", volume));
+ return volume;
}
- Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
- MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOffering.getId(), true);
- try {
- Volume result = migrateVolume(migrateVolumeCmd);
- volume = (result != null) ? _volsDao.findById(result.getId()) : null;
- if (volume == null) {
- throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s", volume, suitableStoragePools.get(0)));
+
+ if (volumeMigrateRequired) {
+ if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) found for migrating to support new disk offering", volume));
+ }
+ final Long newSizeFinal = newSize;
+ List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume: %s as no suitable pool(s) with enough space found for volume migration.", volume));
+ }
+ Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
+ MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOffering.getId(), true);
+ try {
+ Volume result = migrateVolume(migrateVolumeCmd);
+ volume = (result != null) ? _volsDao.findById(result.getId()) : null;
+ if (volume == null) {
+ throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s", volume, suitableStoragePools.get(0)));
+ }
+ } catch (Exception e) {
+ throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s due to %s", volume, suitableStoragePools.get(0), e.getMessage()));
}
- } catch (Exception e) {
- throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume: %s migration failed to storage pool %s due to %s", volume, suitableStoragePools.get(0), e.getMessage()));
}
- }
- if (volumeResizeRequired) {
- // refresh volume data
- volume = _volsDao.findById(volume.getId());
- try {
- volume = resizeVolumeInternal(volume, newDiskOffering, currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, shrinkOk);
- } catch (Exception e) {
- if (volumeMigrateRequired) {
- logger.warn(String.format("Volume change offering operation succeeded for volume ID: %s but volume resize operation failed, so please try resize volume operation separately", volume.getUuid()));
- } else {
- throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s due to resize volume operation failed", volume.getUuid()));
+ if (volumeResizeRequired) {
+ // refresh volume data
+ volume = _volsDao.findById(volume.getId());
+ try {
+ volume = resizeVolumeInternal(volume, newDiskOffering, currentSize, newSize, newMinIops, newMaxIops, newHypervisorSnapshotReserve, shrinkOk);
+ } catch (Exception e) {
+ if (volumeMigrateRequired) {
+ logger.warn(String.format("Volume change offering operation succeeded for volume ID: %s but volume resize operation failed, so please try resize volume operation separately", volume.getUuid()));
+ } else {
+ throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s due to resize volume operation failed", volume.getUuid()));
+ }
}
}
- }
- return volume;
+ return volume;
} finally {
ReservationHelper.closeAll(reservations);
@@ -2807,7 +2806,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
// if target VM has associated VM snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
if (vmSnapshots.size() > 0) {
- throw new InvalidParameterValueException(String.format("Unable to attach volume to VM %s/%s, please specify a VM that does not have VM snapshots", vm.getName(), vm.getUuid()));
+ throw new InvalidParameterValueException(String.format("Unable to attach volume to Instance %s/%s, please specify an Instance that does not have Instance Snapshots", vm.getName(), vm.getUuid()));
}
}
@@ -3130,7 +3129,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
// Don't allow detach if target VM has associated VM snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
if (CollectionUtils.isNotEmpty(vmSnapshots)) {
- throw new InvalidParameterValueException("Unable to detach volume, please specify a VM that does not have VM snapshots");
+ throw new InvalidParameterValueException("Unable to detach volume, please specify an Instance that does not have Instance Snapshots");
}
checkForBackups(vm, false);
@@ -3426,7 +3425,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
// Check that Vm to which this volume is attached does not have VM Snapshots
// OfflineVmwareMigration: consider if this is needed and desirable
if (vm != null && _vmSnapshotDao.findByVm(vm.getId()).size() > 0) {
- throw new InvalidParameterValueException("Volume cannot be migrated, please remove all VM snapshots for VM to which this volume is attached");
+ throw new InvalidParameterValueException("Volume cannot be migrated, please remove all Instance Snapshots for Instance to which this volume is attached");
}
StoragePoolVO srcStoragePoolVO = _storagePoolDao.findById(vol.getPoolId());
@@ -3435,7 +3434,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
if (vm != null && State.Running.equals(vm.getState())) {
// Check if the VM is GPU enabled.
if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
- throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
+ throw new InvalidParameterValueException("Live Migration of GPU enabled Instance is not supported");
}
// Check if the underlying hypervisor supports storage motion.
diff --git a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
index 6084987e29c..2599d64f82f 100644
--- a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
@@ -34,14 +34,14 @@ import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
-import org.apache.cloudstack.api.command.user.iso.GetUploadParamsForIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
-import org.apache.cloudstack.api.command.user.template.GetUploadParamsForTemplateCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.direct.download.DirectDownloadManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
@@ -57,15 +57,18 @@ import org.apache.cloudstack.storage.command.TemplateOrVolumePostUploadCommand;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
+import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.collections.CollectionUtils;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.alert.AlertManager;
+import com.cloud.configuration.Config;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.domain.Domain;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
@@ -73,6 +76,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
+import com.cloud.org.Grouping;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.ImageFormat;
@@ -197,19 +201,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
profile.setSize(templateSize);
}
profile.setUrl(url);
- // Check that the resource limit for secondary storage won't be exceeded
- _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
- ResourceType.secondary_storage,
- UriUtils.getRemoteSize(url, followRedirects));
- return profile;
- }
-
- @Override
- public TemplateProfile prepare(GetUploadParamsForIsoCmd cmd) throws ResourceAllocationException {
- TemplateProfile profile = super.prepare(cmd);
-
- // Check that the resource limit for secondary storage won't be exceeded
- _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage);
return profile;
}
@@ -228,19 +219,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
profile.setForCks(cmd.isForCks());
}
profile.setUrl(url);
- // Check that the resource limit for secondary storage won't be exceeded
- _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
- ResourceType.secondary_storage,
- UriUtils.getRemoteSize(url, followRedirects));
- return profile;
- }
-
- @Override
- public TemplateProfile prepare(GetUploadParamsForTemplateCmd cmd) throws ResourceAllocationException {
- TemplateProfile profile = super.prepare(cmd);
- // Check that the resource limit for secondary storage won't be exceeded
- _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage);
return profile;
}
@@ -268,7 +247,6 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
persistDirectDownloadTemplate(template.getId(), profile.getSize());
}
- _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
return template;
}
@@ -322,6 +300,44 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
}
}
+ protected boolean isZoneAndImageStoreAvailable(DataStore imageStore, Long zoneId, Set<Long> zoneSet, boolean isTemplatePrivate) {
+ if (zoneId == null) {
+ logger.warn(String.format("Zone ID is null, cannot allocate ISO/template in image store [%s].", imageStore));
+ return false;
+ }
+
+ DataCenterVO zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ logger.warn("Unable to find zone by id [{}], so skip downloading template to its image store [{}].", zoneId, imageStore);
+ return false;
+ }
+
+ if (Grouping.AllocationState.Disabled == zone.getAllocationState()) {
+ logger.info("Zone [{}] is disabled. Skip downloading template to its image store [{}].", zone, imageStore);
+ return false;
+ }
+
+ if (!_statsCollector.imageStoreHasEnoughCapacity(imageStore)) {
+ logger.info("Image store doesn't have enough capacity. Skip downloading template to this image store [{}].", imageStore);
+ return false;
+ }
+
+ if (zoneSet == null) {
+ logger.info(String.format("Zone set is null; therefore, the ISO/template should be allocated in every secondary storage of zone [%s].", zone));
+ return true;
+ }
+
+ if (isTemplatePrivate && zoneSet.contains(zoneId)) {
+ logger.info(String.format("The template is private and it is already allocated in a secondary storage in zone [%s]; therefore, image store [%s] will be skipped.",
+ zone, imageStore));
+ return false;
+ }
+
+ logger.info(String.format("Private template will be allocated in image store [%s] in zone [%s].", imageStore, zone));
+ zoneSet.add(zoneId);
+ return true;
+ }
+
@Override
public List<TemplateOrVolumePostUploadCommand> createTemplateForPostUpload(final TemplateProfile profile) {
// persist entry in vm_template, vm_template_details and template_zone_ref tables, not that entry at template_store_ref is not created here, and created in createTemplateAsync.
@@ -369,12 +385,67 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
if(payloads.isEmpty()) {
throw new CloudRuntimeException("unable to find zone or an image store with enough capacity");
}
- _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
+
return payloads;
}
});
}
+ /**
+ * If the template/ISO is marked as private, then it is allocated to a random secondary storage; otherwise, allocates to every storage pool in every zone given by the
+ * {@link TemplateProfile#getZoneIdList()}.
+ */
+ protected void postUploadAllocation(List<DataStore> imageStores, VMTemplateVO template, List<TemplateOrVolumePostUploadCommand> payloads) {
+ Set<Long> zoneSet = new HashSet<>();
+ Collections.shuffle(imageStores);
+ for (DataStore imageStore : imageStores) {
+ Long zoneId_is = imageStore.getScope().getScopeId();
+
+ if (!isZoneAndImageStoreAvailable(imageStore, zoneId_is, zoneSet, isPrivateTemplate(template))) {
+ continue;
+ }
+
+ TemplateInfo tmpl = imageFactory.getTemplate(template.getId(), imageStore);
+
+ // persist template_store_ref entry
+ DataObject templateOnStore = imageStore.create(tmpl);
+
+ // update template_store_ref and template state
+ EndPoint ep = _epSelector.select(templateOnStore);
+ if (ep == null) {
+ String errMsg = String.format("There is no secondary storage VM for downloading template to image store %s", imageStore);
+ logger.warn(errMsg);
+ throw new CloudRuntimeException(errMsg);
+ }
+
+ TemplateOrVolumePostUploadCommand payload = new TemplateOrVolumePostUploadCommand(template.getId(), template.getUuid(), tmpl.getInstallPath(), tmpl
+ .getChecksum(), tmpl.getType().toString(), template.getUniqueName(), template.getFormat().toString(), templateOnStore.getDataStore().getUri(),
+ templateOnStore.getDataStore().getRole().toString());
+ //using the existing max template size configuration
+ payload.setMaxUploadSize(_configDao.getValue(Config.MaxTemplateAndIsoSize.key()));
+
+ Long accountId = template.getAccountId();
+ Account account = _accountDao.findById(accountId);
+ Domain domain = _domainDao.findById(account.getDomainId());
+
+ payload.setDefaultMaxSecondaryStorageInGB(ByteScaleUtils.bytesToGibibytes(_resourceLimitMgr.findCorrectResourceLimitForAccountAndDomain(account, domain, ResourceType.secondary_storage, null)));
+ payload.setAccountId(accountId);
+ payload.setRemoteEndPoint(ep.getPublicAddr());
+ payload.setRequiresHvm(template.requiresHvm());
+ payload.setDescription(template.getDisplayText());
+ payloads.add(payload);
+ }
+ }
+
+ protected boolean isPrivateTemplate(VMTemplateVO template){
+
+ // if public OR featured OR system template
+ if(template.isPublicTemplate() || template.isFeatured() || template.getTemplateType() == TemplateType.SYSTEM)
+ return false;
+ else
+ return true;
+ }
+
private class CreateTemplateContext<T> extends AsyncRpcContext<T> {
final TemplateInfo template;
diff --git a/server/src/main/java/com/cloud/template/TemplateAdapterBase.java b/server/src/main/java/com/cloud/template/TemplateAdapterBase.java
index a9adfa93236..d650ef98db7 100644
--- a/server/src/main/java/com/cloud/template/TemplateAdapterBase.java
+++ b/server/src/main/java/com/cloud/template/TemplateAdapterBase.java
@@ -293,7 +293,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
}
GuestOS noneGuestOs = ApiDBUtils.findGuestOSByDisplayName(ApiConstants.ISO_GUEST_OS_NONE);
if ((guestOSId == null || guestOSId == noneGuestOs.getId()) && bootable == true) {
- throw new InvalidParameterValueException("Please pass a valid GuestOS Id");
+ throw new InvalidParameterValueException("Please pass a valid GuestOS ID");
}
if (bootable == false) {
guestOSId = noneGuestOs.getId(); //Guest os id of None.
@@ -309,7 +309,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
requiresHVM = true;
}
if (deployAsIs) {
- logger.info("Setting default guest OS for deploy-as-is template while the template registration is not completed");
+ logger.info("Setting default guest OS for deploy-as-is Template while the Template registration is not completed");
guestOSId = getDefaultDeployAsIsGuestOsId();
}
}
@@ -342,7 +342,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
// check whether owner can create public templates
boolean allowPublicUserTemplates = TemplateManager.AllowPublicUserTemplates.valueIn(templateOwner.getId());
if (!isAdmin && !allowPublicUserTemplates && isPublic) {
- throw new InvalidParameterValueException("Only private templates/ISO can be created.");
+ throw new InvalidParameterValueException("Only private Templates/ISO can be created.");
}
if (!isAdmin || featured == null) {
@@ -363,8 +363,6 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
throw new IllegalArgumentException("Unable to find user with id " + userId);
}
- _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
-
// If a zoneId is specified, make sure it is valid
if (zoneIdList != null) {
for (Long zoneId :zoneIdList) {
@@ -386,7 +384,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
Objects.equals(template.getArch(), arch)) {
logger.error("{} for same arch {} is having same name or description", template,
template.getArch());
- throw new IllegalArgumentException("Cannot use reserved names for templates");
+ throw new IllegalArgumentException("Cannot use reserved names for Templates");
}
}
@@ -442,11 +440,11 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
if (cmd.isDeployAsIs()) {
if (MapUtils.isNotEmpty(details)) {
if (details.containsKey(VmDetailConstants.ROOT_DISK_CONTROLLER)) {
- logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the template");
+ logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the Template");
details.remove(VmDetailConstants.ROOT_DISK_CONTROLLER);
}
if (details.containsKey(VmDetailConstants.NIC_ADAPTER)) {
- logger.info("Ignoring the nicAdapter detail provided, as we honour what is defined in the template");
+ logger.info("Ignoring the nicAdapter detail provided, as we honour what is defined in the Template");
details.remove(VmDetailConstants.NIC_ADAPTER);
}
}
@@ -512,7 +510,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
public TemplateProfile prepare(GetUploadParamsForTemplateCmd cmd) throws ResourceAllocationException {
Long osTypeId = cmd.getOsTypeId();
if (osTypeId == null) {
- logger.info("Setting the default guest OS for deploy-as-is templates while the template upload is not completed");
+ logger.info("Setting the default guest OS for deploy-as-is Templates while the Template upload is not completed");
osTypeId = getDefaultDeployAsIsGuestOsId();
}
UploadParams params = new TemplateUploadParams(CallContext.current().getCallingUserId(), cmd.getName(),
@@ -574,7 +572,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
List<DataCenterVO> dcs = _dcDao.listAll();
if (dcs.isEmpty()) {
- throw new CloudRuntimeException("No zones are present in the system, can't add template");
+ throw new CloudRuntimeException("No zones are present in the system, can't add Template");
}
template.setCrossZones(true);
@@ -604,7 +602,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
Account owner = _accountMgr.getAccount(template.getAccountId());
if (owner.getType() == Account.Type.PROJECT) {
if (!_projectMgr.canAccessProjectAccount(account, owner.getId())) {
- throw new PermissionDeniedException(msg + ". Permission denied. The caller can't access project's template");
+ throw new PermissionDeniedException(msg + ". Permission denied. The caller can't access project's Template");
}
} else {
throw new PermissionDeniedException(msg + ". Permission denied.");
@@ -638,10 +636,10 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find template with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find Template with ID " + templateId);
}
- userId = accountAndUserValidation(account, userId, null, template, "Unable to delete template ");
+ userId = accountAndUserValidation(account, userId, null, template, "Unable to delete Template ");
UserVO user = _userDao.findById(userId);
if (user == null) {
@@ -649,11 +647,11 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
}
if (template.getFormat() == ImageFormat.ISO) {
- throw new InvalidParameterValueException("Please specify a valid template.");
+ throw new InvalidParameterValueException("Please specify a valid Template.");
}
if (template.getState() == VirtualMachineTemplate.State.NotUploaded || template.getState() == VirtualMachineTemplate.State.UploadInProgress) {
- throw new InvalidParameterValueException("The template is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
+ throw new InvalidParameterValueException("The Template is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
}
return new TemplateProfile(userId, template, zoneId);
@@ -667,7 +665,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find template with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find Template with ID " + templateId);
}
return new TemplateProfile(userId, template, zoneId);
}
@@ -681,10 +679,10 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find iso with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find ISO with ID " + templateId);
}
- userId = accountAndUserValidation(account, userId, null, template, "Unable to delete iso ");
+ userId = accountAndUserValidation(account, userId, null, template, "Unable to delete ISO ");
UserVO user = _userDao.findById(userId);
if (user == null) {
@@ -692,11 +690,11 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
}
if (template.getFormat() != ImageFormat.ISO) {
- throw new InvalidParameterValueException("Please specify a valid iso.");
+ throw new InvalidParameterValueException("Please specify a valid ISO.");
}
if (template.getState() == VirtualMachineTemplate.State.NotUploaded || template.getState() == VirtualMachineTemplate.State.UploadInProgress) {
- throw new InvalidParameterValueException("The iso is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
+ throw new InvalidParameterValueException("The ISO is either getting uploaded or it may be initiated shortly, please wait for it to be completed");
}
return new TemplateProfile(userId, template, zoneId);
diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
index 3ff374e273f..38fd9ab205b 100755
--- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
@@ -132,6 +132,7 @@ import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
+import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
@@ -306,27 +307,25 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
private HypervisorGuruManager _hvGuruMgr;
@Inject
ReservationDao reservationDao;
-
- private List<TemplateAdapter> _adapters;
-
- ExecutorService _preloadExecutor;
-
@Inject
private StorageCacheManager cacheMgr;
@Inject
private EndPointSelector selector;
-
@Inject
protected SnapshotHelper snapshotHelper;
@Inject
VnfTemplateManager vnfTemplateManager;
-
+ @Inject
+ TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
@Inject
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
-
@Inject
private HeuristicRuleHelper heuristicRuleHelper;
+ private List<TemplateAdapter> _adapters;
+
+ ExecutorService _preloadExecutor;
+
protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value();
private TemplateAdapter getAdapter(HypervisorType type) {
@@ -345,14 +344,14 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
if (adapter == null) {
- throw new CloudRuntimeException("Cannot find template adapter for " + type.toString());
+ throw new CloudRuntimeException("Cannot find Template adapter for " + type.toString());
}
return adapter;
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "creating iso")
+ @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "Creating ISO")
public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException {
TemplateAdapter adapter = getAdapter(HypervisorType.None);
Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
@@ -383,7 +382,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template")
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "Creating Template")
public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException {
Account account = CallContext.current().getCallingAccount();
if (cmd.getTemplateTag() != null) {
@@ -408,7 +407,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
TemplateProfile profile = adapter.prepare(cmd);
VMTemplateVO template = adapter.create(profile);
- // Secondary storage resource usage will be incremented in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
+ // Secondary storage resource usage will be recalculated in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
// for HypervisorTemplateAdapter
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
if (secondaryStorageUsage > 0) {
@@ -422,7 +421,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
return template;
} else {
- throw new CloudRuntimeException("Failed to create a template");
+ throw new CloudRuntimeException("Failed to create a Template");
}
}
}
@@ -481,24 +480,42 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
return response;
} else {
- throw new CloudRuntimeException("Unable to register template.");
+ throw new CloudRuntimeException("Unable to register Template.");
}
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "creating post upload iso")
+ @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "Creating post upload ISO")
public GetUploadParamsResponse registerIsoForPostUpload(GetUploadParamsForIsoCmd cmd) throws ResourceAllocationException, MalformedURLException {
- TemplateAdapter adapter = getAdapter(HypervisorType.None);
- TemplateProfile profile = adapter.prepare(cmd);
- return registerPostUploadInternal(adapter, profile);
+ Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
+
+ try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr)) {
+ TemplateAdapter adapter = getAdapter(HypervisorType.None);
+ TemplateProfile profile = adapter.prepare(cmd);
+
+ GetUploadParamsResponse response = registerPostUploadInternal(adapter, profile);
+
+ _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
+
+ return response;
+ }
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating post upload template")
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "Creating post upload Template")
public GetUploadParamsResponse registerTemplateForPostUpload(GetUploadParamsForTemplateCmd cmd) throws ResourceAllocationException, MalformedURLException {
- TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
- TemplateProfile profile = adapter.prepare(cmd);
- return registerPostUploadInternal(adapter, profile);
+ Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
+
+ try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr)) {
+ TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
+ TemplateProfile profile = adapter.prepare(cmd);
+
+ GetUploadParamsResponse response = registerPostUploadInternal(adapter, profile);
+
+ _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
+
+ return response;
+ }
}
@Override
@@ -536,7 +553,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_EXTRACT, eventDescription = "extracting template", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_EXTRACT, eventDescription = "Extracting Template", async = true)
public String extract(ExtractTemplateCmd cmd) {
Account caller = CallContext.current().getCallingAccount();
Long templateId = cmd.getId();
@@ -547,7 +564,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
VirtualMachineTemplate template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find template with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find Template with id " + templateId);
}
String extractUrl = extract(caller, templateId, url, zoneId, mode, eventId, false);
@@ -560,7 +577,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
VMTemplateVO vmTemplate = _tmpltDao.findById(templateId);
if (vmTemplate == null) {
- throw new InvalidParameterValueException("Unable to find template id=" + templateId);
+ throw new InvalidParameterValueException("Unable to find Template ID=" + templateId);
}
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, vmTemplate);
@@ -571,7 +588,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (pool.getStatus() == StoragePoolStatus.Up && pool.getDataCenterId() == zoneId) {
prepareTemplateInOneStoragePool(vmTemplate, pool);
} else {
- logger.warn("Skip loading template {} into primary storage {} as " +
+ logger.warn("Skip loading Template {} into primary storage {} as " +
"either the pool zone {} is different from the requested zone {} or " +
"the pool is currently not available.",
vmTemplate::toString, pool::toString, () -> _dcDao.findById(pool.getDataCenterId()), () -> _dcDao.findById(zoneId));
@@ -607,7 +624,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
} else {
if (template.getFormat() == ImageFormat.ISO) {
- throw new InvalidParameterValueException("Unsupported format, could not extract the template");
+ throw new InvalidParameterValueException("Unsupported format, could not extract the Template");
}
}
@@ -616,7 +633,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
if (!_accountMgr.isRootAdmin(caller.getId()) && !template.isExtractable()) {
- throw new InvalidParameterValueException(String.format("Unable to extract template %s as it's not extractable", template));
+ throw new InvalidParameterValueException(String.format("Unable to extract Template %s as it's not extractable", template));
}
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template);
@@ -670,7 +687,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (MapUtils.isNotEmpty(storageForDisks)) {
for (StoragePool storagePool : storageForDisks.values()) {
if (poolId != null && storagePool.getId() != poolId) {
- throw new CloudRuntimeException("Cannot determine where to download iso");
+ throw new CloudRuntimeException("Cannot determine where to download ISO");
}
poolId = storagePool.getId();
}
@@ -705,10 +722,10 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
private void prepareTemplateInOneStoragePool(final VMTemplateVO template, final StoragePoolVO pool) {
- logger.info("Schedule to preload template {} into primary storage {}", template, pool);
+ logger.info("Schedule to preload Template {} into primary storage {}", template, pool);
if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {
List<StoragePoolVO> childDataStores = _poolDao.listChildStoragePoolsInDatastoreCluster(pool.getId());
- logger.debug("Schedule to preload template {} into child datastores of DataStore cluster: {}", template, pool);
+ logger.debug("Schedule to preload Template {} into child datastores of DataStore cluster: {}", template, pool);
for (StoragePoolVO childDataStore : childDataStores) {
prepareTemplateInOneStoragePoolInternal(template, childDataStore);
}
@@ -729,10 +746,10 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
private void reallyRun() {
- logger.info("Start to preload template {} into primary storage {}", template, pool);
+ logger.info("Start to preload Template {} into primary storage {}", template, pool);
StoragePool pol = (StoragePool)_dataStoreMgr.getPrimaryDataStore(pool.getId());
prepareTemplateForCreate(template, pol);
- logger.info("End of preloading template {} into primary storage {}", template, pool);
+ logger.info("End of preloading Template {} into primary storage {}", template, pool);
}
});
}
@@ -743,7 +760,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (pool.getDataCenterId() == zoneId) {
prepareTemplateInOneStoragePool(template, pool);
} else {
- logger.info("Skip loading template {} into primary storage {} as pool " +
+ logger.info("Skip loading Template {} into primary storage {} as pool " +
"zone {} is different from the requested zone {}", template::toString, pool::toString,
() -> _dcDao.findById(pool.getDataCenterId()), () -> _dcDao.findById(zoneId));
}
@@ -776,7 +793,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
templateStoreRef = _tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, pool.getDataCenterId(), VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
if (templateStoreRef == null) {
- logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
+ logger.error("Unable to find a secondary storage host who has completely downloaded the Template.");
return null;
}
@@ -787,7 +804,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (templateStoragePoolRef == null) {
if (logger.isDebugEnabled()) {
- logger.debug("Downloading template {} to pool {}", template, pool);
+ logger.debug("Downloading Template {} to pool {}", template, pool);
}
DataStore srcSecStore = _dataStoreMgr.getDataStore(templateStoreRef.getDataStoreId(), DataStoreRole.Image);
TemplateInfo srcTemplate = _tmplFactory.getTemplate(templateId, srcSecStore);
@@ -796,13 +813,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
try {
TemplateApiResult result = future.get();
if (result.isFailed()) {
- logger.debug("prepare template failed:" + result.getResult());
+ logger.debug("Prepare Template failed:" + result.getResult());
return null;
}
return _tmpltPoolDao.findByPoolTemplate(poolId, templateId, null);
} catch (Exception ex) {
- logger.debug("failed to copy template from image store {} to primary storage", srcSecStore);
+ logger.debug("Failed to copy Template from image store {} to primary storage", srcSecStore);
}
}
@@ -865,9 +882,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// find the size of the template to be copied
TemplateDataStoreVO srcTmpltStore = _tmplStoreDao.findByStoreTemplate(srcSecStore.getId(), tmpltId);
- _resourceLimitMgr.checkResourceLimit(account, ResourceType.template);
- _resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltStore.getSize()).longValue());
-
// Event details
String copyEventType;
if (template.getFormat().equals(ImageFormat.ISO)) {
@@ -893,7 +907,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
try {
TemplateApiResult result = future.get();
if (result.isFailed()) {
- logger.debug("copy template failed for image store {}: {}", dstSecStore, result.getResult());
+ logger.debug("Copy Template failed for image store {}: {}", dstSecStore, result.getResult());
+ _tmplStoreDao.removeByTemplateStore(tmpltId, dstSecStore.getId());
continue; // try next image store
}
@@ -908,32 +923,31 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
List<VMTemplateVO> dataDiskTemplates = _tmpltDao.listByParentTemplatetId(template.getId());
if (dataDiskTemplates != null && !dataDiskTemplates.isEmpty()) {
for (VMTemplateVO dataDiskTemplate : dataDiskTemplates) {
- logger.debug("Copying {} for source template {}. Copy all Datadisk templates to destination datastore {}", dataDiskTemplates.size(), template, dstSecStore);
+ logger.debug("Copying {} for source Template {}. Copy all Datadisk Templates to destination datastore {}", dataDiskTemplates.size(), template, dstSecStore);
TemplateInfo srcDataDiskTemplate = _tmplFactory.getTemplate(dataDiskTemplate.getId(), srcSecStore);
AsyncCallFuture<TemplateApiResult> dataDiskCopyFuture = _tmpltSvr.copyTemplate(srcDataDiskTemplate, dstSecStore);
try {
TemplateApiResult dataDiskCopyResult = dataDiskCopyFuture.get();
if (dataDiskCopyResult.isFailed()) {
- logger.error("Copy of datadisk template: {} to image store: {} failed with error: {} , will try copying the next one", srcDataDiskTemplate, dstSecStore, dataDiskCopyResult.getResult());
+ logger.error("Copy of datadisk Template: {} to image store: {} failed with error: {} , will try copying the next one", srcDataDiskTemplate, dstSecStore, dataDiskCopyResult.getResult());
continue; // Continue to copy next Datadisk template
}
_tmpltDao.addTemplateToZone(dataDiskTemplate, dstZoneId);
_resourceLimitMgr.incrementResourceCount(dataDiskTemplate.getAccountId(), ResourceType.secondary_storage, dataDiskTemplate.getSize());
} catch (Exception ex) {
- logger.error("Failed to copy datadisk template: {} to image store: {} , will try copying the next one", srcDataDiskTemplate, dstSecStore);
+ logger.error("Failed to copy datadisk Template: {} to image store: {} , will try copying the next one", srcDataDiskTemplate, dstSecStore);
}
}
}
} catch (Exception ex) {
- logger.debug("failed to copy template to image store:{} ,will try next one", dstSecStore);
+ logger.debug("Failed to copy Template to image store:{} ,will try next one", dstSecStore, ex);
}
}
return true;
-
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_COPY, eventDescription = "copying template", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_COPY, eventDescription = "Copying Template", async = true)
public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException {
Long templateId = cmd.getId();
Long userId = CallContext.current().getCallingUserId();
@@ -944,12 +958,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// Verify parameters
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null || template.getRemoved() != null) {
- throw new InvalidParameterValueException("Unable to find template with id");
+ throw new InvalidParameterValueException("Unable to find Template with id");
}
// Verify template is not Datadisk template
if (template.getTemplateType().equals(TemplateType.DATADISK)) {
- throw new InvalidParameterValueException(String.format("Template %s is of type Datadisk. Cannot copy Datadisk templates.", template));
+ throw new InvalidParameterValueException(String.format("Template %s is of type Datadisk. Cannot copy Datadisk Templates.", template));
}
if (sourceZoneId != null) {
@@ -999,40 +1013,40 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
if (srcSecStore == null) {
- throw new InvalidParameterValueException(String.format("There is no template %s ready on image store.", template));
+ throw new InvalidParameterValueException(String.format("There is no Template %s ready on image store.", template));
}
if (template.isCrossZones()) {
// sync template from cache store to region store if it is not there, for cases where we are going to migrate existing NFS to S3.
_tmpltSvr.syncTemplateToRegionStore(template, srcSecStore);
}
+
+ AccountVO templateOwner = _accountDao.findById(template.getAccountId());
+
for (Long destZoneId : destZoneIds) {
DataStore dstSecStore = getImageStore(destZoneId, templateId);
if (dstSecStore != null) {
- logger.debug("There is template {} in secondary storage {} in zone {} , don't need to copy", template, dstSecStore, dataCenterVOs.get(destZoneId));
+ logger.debug("There is Template {} in secondary storage {} in zone {} , don't need to copy", template, dstSecStore, dataCenterVOs.get(destZoneId));
continue;
}
- if (!copy(userId, template, srcSecStore, dataCenterVOs.get(destZoneId))) {
- failedZones.add(dataCenterVOs.get(destZoneId).getName());
- }
- else{
- if (template.getSize() != null) {
- // increase resource count
- long accountId = template.getAccountId();
- _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.secondary_storage, template.getSize());
+ try (CheckedReservation secondaryStorageReservation = new CheckedReservation(templateOwner, ResourceType.secondary_storage, null, null, template.getSize(), reservationDao, _resourceLimitMgr)) {
+ if (!copy(userId, template, srcSecStore, dataCenterVOs.get(destZoneId))) {
+ failedZones.add(dataCenterVOs.get(destZoneId).getName());
+ continue;
}
+ _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage, template.getSize());
}
}
}
if ((destZoneIds != null) && (destZoneIds.size() > failedZones.size())){
if (!failedZones.isEmpty()) {
- logger.debug("There were failures when copying template to zones: " +
+ logger.debug("There were failures when copying Template to zones: " +
StringUtils.listToCsvTags(failedZones));
}
return template;
} else {
- throw new CloudRuntimeException("Failed to copy template");
+ throw new CloudRuntimeException("Failed to copy Template");
}
}
@@ -1043,14 +1057,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
AccountVO account = _accountDao.findById(template.getAccountId());
-
- _resourceLimitMgr.checkResourceLimit(account, ResourceType.template);
-
try {
_tmpltDao.addTemplateToZone(template, dstZoneId);
return true;
} catch (Exception ex) {
- logger.debug("failed to copy template from Zone: {} to Zone: {}", sourceZone, dstZone);
+ logger.debug("Failed to copy Template from Zone: {} to Zone: {}", sourceZone, dstZone);
}
return false;
}
@@ -1059,7 +1070,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
public boolean delete(long userId, long templateId, Long zoneId) {
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null || template.getRemoved() != null) {
- throw new InvalidParameterValueException("Please specify a valid template.");
+ throw new InvalidParameterValueException("Please specify a valid Template.");
}
TemplateAdapter adapter = getAdapter(template.getHypervisorType());
@@ -1121,7 +1132,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.acquireInLockTable(templatePoolVO.getId());
if (templatePoolRef == null) {
- logger.debug("Can't acquire the lock for template pool ref: {}", templatePoolVO);
+ logger.debug("Can't acquire the lock for Template pool ref: {}", templatePoolVO);
return;
}
@@ -1140,11 +1151,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
TemplateApiResult result = future.get();
if (result.isFailed()) {
- logger.debug("Failed to delete template {} from storage pool {}", template, pool);
+ logger.debug("Failed to delete Template {} from storage pool {}", template, pool);
} else {
// Remove the templatePoolVO.
if (_tmpltPoolDao.remove(templatePoolVO.getId())) {
- logger.debug("Successfully evicted template {} from storage pool {}", template, pool);
+ logger.debug("Successfully evicted Template {} from storage pool {}", template, pool);
}
}
} else {
@@ -1154,14 +1165,14 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (answer != null && answer.getResult()) {
// Remove the templatePoolVO.
if (_tmpltPoolDao.remove(templatePoolVO.getId())) {
- logger.debug("Successfully evicted template {} from storage pool {}", template, pool);
+ logger.debug("Successfully evicted Template {} from storage pool {}", template, pool);
}
} else {
- logger.info("Will retry evict template {} from storage pool {}", template, pool);
+ logger.info("Will retry evict Template {} from storage pool {}", template, pool);
}
}
} catch (StorageUnavailableException | InterruptedException | ExecutionException e) {
- logger.info("Storage is unavailable currently. Will retry evicte template {} from storage pool {}", template, pool);
+ logger.info("Storage is unavailable currently. Will retry evicte Template {} from storage pool {}", template, pool);
} finally {
_tmpltPoolDao.releaseFromLockTable(templatePoolRef.getId());
}
@@ -1196,7 +1207,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// always be copied to
// primary storage before deploying VM.
if (!userVmUsingIso.isEmpty()) {
- logger.debug("ISO " + templateId + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs");
+ logger.debug("ISO " + templateId + " is not deleteable because it is attached to " + userVmUsingIso.size() + " Instances");
return false;
}
@@ -1222,7 +1233,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Long isoId = !isVirtualRouter ? ((UserVm) virtualMachine).getIsoId() : isoParamId;
if (isoId == null) {
- throw new InvalidParameterValueException("The specified VM has no ISO attached to it.");
+ throw new InvalidParameterValueException("The specified instance has no ISO attached to it.");
}
CallContext.current().setEventDetails("Vm Id: " + virtualMachine.getUuid() + " ISO Id: " + isoId);
@@ -1236,7 +1247,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (result) {
return result;
} else {
- throw new CloudRuntimeException("Failed to detach iso");
+ throw new CloudRuntimeException("Failed to detach ISO");
}
}
@@ -1308,7 +1319,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (result) {
return result;
} else {
- throw new CloudRuntimeException("Failed to attach iso");
+ throw new CloudRuntimeException("Failed to attach ISO");
}
}
@@ -1334,7 +1345,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Scope destScope = new ZoneScope(dcId);
TemplateInfo cacheData = (TemplateInfo)cacheMgr.createCacheObject(tmplt, destScope);
if (cacheData == null) {
- logger.error("Failed in copy iso from S3 to cache storage");
+ logger.error("Failed in copy ISO from S3 to cache storage");
return null;
}
return cacheData;
@@ -1402,14 +1413,14 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "deleting template", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "Deleting Template", async = true)
public boolean deleteTemplate(DeleteTemplateCmd cmd) {
Long templateId = cmd.getId();
Account caller = CallContext.current().getCallingAccount();
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find template with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find Template with id " + templateId);
}
List<VMInstanceVO> vmInstanceVOList;
@@ -1420,7 +1431,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
vmInstanceVOList = _vmInstanceDao.listNonExpungedByTemplate(templateId);
}
if(!cmd.isForced() && CollectionUtils.isNotEmpty(vmInstanceVOList)) {
- final String message = String.format("Unable to delete template: %s because VM instances: [%s] are using it.", template, Joiner.on(",").join(vmInstanceVOList));
+ final String message = String.format("Unable to delete Template: %s because Instance: [%s] are using it.", template, Joiner.on(",").join(vmInstanceVOList));
logger.warn(message);
throw new InvalidParameterValueException(message);
}
@@ -1428,7 +1439,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template);
if (template.getFormat() == ImageFormat.ISO) {
- throw new InvalidParameterValueException("Please specify a valid template.");
+ throw new InvalidParameterValueException("Please specify a valid Template.");
}
VnfTemplateUtils.validateApiCommandParams(cmd, template);
@@ -1439,7 +1450,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_ISO_DELETE, eventDescription = "deleting iso", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_ISO_DELETE, eventDescription = "Deleting ISO", async = true)
public boolean deleteIso(DeleteIsoCmd cmd) {
Long templateId = cmd.getId();
Account caller = CallContext.current().getCallingAccount();
@@ -1447,18 +1458,18 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
VMTemplateVO template = _tmpltDao.findById(templateId);
if (template == null) {
- throw new InvalidParameterValueException("unable to find iso with id " + templateId);
+ throw new InvalidParameterValueException("Unable to find ISO with id " + templateId);
}
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template);
if (template.getFormat() != ImageFormat.ISO) {
- throw new InvalidParameterValueException("Please specify a valid iso.");
+ throw new InvalidParameterValueException("Please specify a valid ISO.");
}
// check if there is any VM using this ISO.
if (!templateIsDeleteable(templateId)) {
- throw new InvalidParameterValueException("Unable to delete iso, as it's used by other vms");
+ throw new InvalidParameterValueException("Unable to delete ISO, as it's used by other instances");
}
if (zoneId != null && (_dataStoreMgr.getImageStoreWithFreeCapacity(zoneId) == null)) {
@@ -1491,11 +1502,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (cmd instanceof ListTemplatePermissionsCmd) {
if (template.getFormat().equals(ImageFormat.ISO)) {
- throw new InvalidParameterValueException("Please provide a valid template");
+ throw new InvalidParameterValueException("Please provide a valid Template");
}
} else if (cmd instanceof ListIsoPermissionsCmd) {
if (!template.getFormat().equals(ImageFormat.ISO)) {
- throw new InvalidParameterValueException("Please provide a valid iso");
+ throw new InvalidParameterValueException("Please provide a valid ISO");
}
}
@@ -1545,13 +1556,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (cmd instanceof UpdateTemplatePermissionsCmd) {
mediaType = "template";
if (template.getFormat().equals(ImageFormat.ISO)) {
- throw new InvalidParameterValueException("Please provide a valid template");
+ throw new InvalidParameterValueException("Please provide a valid Template");
}
}
if (cmd instanceof UpdateIsoPermissionsCmd) {
mediaType = "iso";
if (!template.getFormat().equals(ImageFormat.ISO)) {
- throw new InvalidParameterValueException("Please provide a valid iso");
+ throw new InvalidParameterValueException("Please provide a valid ISO");
}
}
@@ -1593,7 +1604,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// if there is no owner of the template then it's probably already a
// public template (or domain private template) so
// publishing to individual users is irrelevant
- throw new InvalidParameterValueException("Update template permissions is an invalid operation on template " + template.getName());
+ throw new InvalidParameterValueException("Update Template permissions is an invalid operation on Template " + template.getName());
}
if (owner.getType() == Account.Type.PROJECT) {
@@ -1612,14 +1623,14 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (accountNames != null) {
if ((operation == null) || (!operation.equalsIgnoreCase("add") && !operation.equalsIgnoreCase("remove") && !operation.equalsIgnoreCase("reset"))) {
throw new InvalidParameterValueException(
- "Invalid operation on accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." + " Given operation is: '" +
+ "Invalid operation on Accounts, the operation must be either 'add' or 'remove' in order to modify launch permissions." + " Given operation is: '" +
operation + "'");
}
}
//Only admin or owner of the template should be able to change its permissions
if (caller.getId() != ownerId && !isAdmin) {
- throw new InvalidParameterValueException("Unable to grant permission to account " + caller.getAccountName() + " as it is neither admin nor owner or the template");
+ throw new InvalidParameterValueException("Unable to grant permission to Account " + caller.getAccountName() + " as it is neither admin nor owner or the Template");
}
VMTemplateVO updatedTemplate = _tmpltDao.createForUpdate();
@@ -1635,7 +1646,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (isExtractable != null) {
// Only Root admins and owners are allowed to change it for templates
if (!template.getFormat().equals(ImageFormat.ISO) && caller.getId() != ownerId && !isAdmin) {
- throw new InvalidParameterValueException("Only ROOT admins and template owners are allowed to modify isExtractable attribute.");
+ throw new InvalidParameterValueException("Only ROOT admins and Template owners are allowed to modify isExtractable attribute.");
} else {
// For Isos normal user can change it, as their are no derivatives.
updatedTemplate.setExtractable(isExtractable.booleanValue());
@@ -1646,7 +1657,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
//when operation is add/remove, accountNames can not be null
if (("add".equalsIgnoreCase(operation) || "remove".equalsIgnoreCase(operation)) && accountNames == null) {
- throw new InvalidParameterValueException("Operation " + operation + " requires accounts or projectIds to be passed in");
+ throw new InvalidParameterValueException("Operation " + operation + " requires Accounts or projectIds to be passed in");
}
//Derive the domain id from the template owner as updateTemplatePermissions is not cross domain operation
@@ -1671,8 +1682,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
_launchPermissionDao.persist(launchPermission);
}
} else {
- throw new InvalidParameterValueException("Unable to grant a launch permission to account " + accountName + " in domain id=" +
- domain.getUuid() + ", account not found. " + "No permissions updated, please verify the account names and retry.");
+ throw new InvalidParameterValueException("Unable to grant a launch permission to Account " + accountName + " in domain id=" +
+ domain.getUuid() + ", Account not found. " + "No permissions updated, please verify the Account names and retry.");
}
}
}
@@ -1716,7 +1727,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
@Override
@DB
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", async = true)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "Creating Template", async = true)
public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command) throws CloudRuntimeException {
final long templateId = command.getEntityId();
Long volumeId = command.getVolumeId();
@@ -1809,8 +1820,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (result.isFailed()) {
privateTemplate = null;
- logger.debug("Failed to create template" + result.getResult());
- throw new CloudRuntimeException("Failed to create template" + result.getResult());
+ logger.debug("Failed to create Template" + result.getResult());
+ throw new CloudRuntimeException("Failed to create Template" + result.getResult());
}
// create entries in template_zone_ref table
@@ -1829,11 +1840,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
privateTemplate.getSourceTemplateId(), srcTmpltStore.getPhysicalSize(), privateTemplate.getSize());
_usageEventDao.persist(usageEvent);
} catch (InterruptedException e) {
- logger.debug("Failed to create template", e);
- throw new CloudRuntimeException("Failed to create template", e);
+ logger.debug("Failed to create Template", e);
+ throw new CloudRuntimeException("Failed to create Template", e);
} catch (ExecutionException e) {
- logger.debug("Failed to create template", e);
- throw new CloudRuntimeException("Failed to create template", e);
+ logger.debug("Failed to create Template", e);
+ throw new CloudRuntimeException("Failed to create Template", e);
}
} finally {
@@ -1857,7 +1868,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// decrement resource count
if (accountId != null) {
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
- _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(volumeFinal != null ? volumeFinal.getSize()
+ _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, (long)(volumeFinal != null ? volumeFinal.getSize()
: snapshotFinal.getSize()));
}
}
@@ -1873,12 +1884,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (privateTemplate != null) {
return privateTemplate;
} else {
- throw new CloudRuntimeException("Failed to create a template");
+ throw new CloudRuntimeException("Failed to create a Template");
}
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "Creating Template", create = true)
public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
Account caller = CallContext.current().getCallingAccount();
boolean isAdmin = (_accountMgr.isAdmin(caller.getId()));
@@ -1916,7 +1927,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
boolean allowPublicUserTemplates = AllowPublicUserTemplates.valueIn(templateOwner.getId());
final Long zoneId = cmd.getZoneId();
if (!isAdmin && !allowPublicUserTemplates && isPublic) {
- throw new PermissionDeniedException("Failed to create template " + name + ", only private templates can be created.");
+ throw new PermissionDeniedException("Failed to create Template " + name + ", only private Templates can be created.");
}
Long volumeId = cmd.getVolumeId();
@@ -1925,11 +1936,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
throw new InvalidParameterValueException("Failed to create private template record, zone ID can only be specified together with snapshot ID.");
}
if ((volumeId == null) && (snapshotId == null)) {
- throw new InvalidParameterValueException("Failed to create private template record, neither volume ID nor snapshot ID were specified.");
+ throw new InvalidParameterValueException("Failed to create private Template record, neither volume ID nor Snapshot ID were specified.");
}
if ((volumeId != null) && (snapshotId != null)) {
- throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId +
- ") and snapshot ID (" + snapshotId + ")");
+ throw new InvalidParameterValueException("Failed to create private Template record, please specify only one of volume ID (" + volumeId +
+ ") and Snapshot ID (" + snapshotId + ")");
}
CPU.CPUArch arch = cmd.getArch();
@@ -1940,21 +1951,21 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (volumeId != null) { // create template from volume
volume = _volumeDao.findById(volumeId);
if (volume == null) {
- throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId);
+ throw new InvalidParameterValueException("Failed to create private Template record, unable to find volume " + volumeId);
}
// check permissions
_accountMgr.checkAccess(caller, null, true, volume);
// Don't support creating templates from encrypted volumes (yet)
if (volume.getPassphraseId() != null) {
- throw new UnsupportedOperationException("Cannot create templates from encrypted volumes");
+ throw new UnsupportedOperationException("Cannot create Templates from encrypted volumes");
}
// If private template is created from Volume, check that the volume
// will not be active when the private template is
// created
if (!_volumeMgr.volumeInactive(volume)) {
- String msg = String.format("Unable to create private template for volume: %s; volume is attached to a non-stopped VM, please stop the VM first", volume);
+ String msg = String.format("Unable to create private Template for volume: %s; volume is attached to a non-stopped Instance, please stop the Instance first", volume);
if (logger.isInfoEnabled()) {
logger.info(msg);
}
@@ -1968,21 +1979,21 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
} else { // create template from snapshot
snapshot = _snapshotDao.findById(snapshotId);
if (snapshot == null) {
- throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId);
+ throw new InvalidParameterValueException("Failed to create private Template record, unable to find Snapshot " + snapshotId);
}
// Volume could be removed so find including removed to record source template id.
volume = _volumeDao.findByIdIncludingRemoved(snapshot.getVolumeId());
// Don't support creating templates from encrypted volumes (yet)
if (volume != null && volume.getPassphraseId() != null) {
- throw new UnsupportedOperationException("Cannot create templates from snapshots of encrypted volumes");
+ throw new UnsupportedOperationException("Cannot create Templates from Snapshots of encrypted volumes");
}
// check permissions
_accountMgr.checkAccess(caller, null, true, snapshot);
if (snapshot.getState() != Snapshot.State.BackedUp) {
- throw new InvalidParameterValueException(String.format("Snapshot %s is not in %s state yet and can't be used for template creation",
+ throw new InvalidParameterValueException(String.format("Snapshot %s is not in %s state yet and can't be used for Template creation",
snapshot, Snapshot.State.BackedUp));
}
@@ -2008,107 +2019,106 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
}
- _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);
- _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.secondary_storage, new Long(volume != null ? volume.getSize() : snapshot.getSize()).longValue());
+ long templateSize = volume != null ? volume.getSize() : snapshot.getSize();
+ try (CheckedReservation templateReservation = new CheckedReservation(templateOwner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr);
+ CheckedReservation secondaryStorageReservation = new CheckedReservation(templateOwner, ResourceType.secondary_storage, null, null, templateSize, reservationDao, _resourceLimitMgr)) {
- if (!isAdmin || featured == null) {
- featured = Boolean.FALSE;
- }
- Long guestOSId = cmd.getOsTypeId();
- GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
- if (guestOS == null) {
- throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
- }
-
- Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id");
- String description = cmd.getDisplayText();
- boolean isExtractable = false;
- Long sourceTemplateId = null;
- if (volume != null) {
- VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
- isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
- if (template != null) {
- arch = template.getArch();
- }
- if (volume.getIsoId() != null && volume.getIsoId() != 0) {
- sourceTemplateId = volume.getIsoId();
- } else if (volume.getTemplateId() != null) {
- sourceTemplateId = volume.getTemplateId();
+ if (!isAdmin || featured == null) {
+ featured = Boolean.FALSE;
}
- }
- String templateTag = cmd.getTemplateTag();
- if (templateTag != null) {
- if (logger.isDebugEnabled()) {
- logger.debug("Adding template tag: " + templateTag);
+ Long guestOSId = cmd.getOsTypeId();
+ GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
+ if (guestOS == null) {
+ throw new InvalidParameterValueException("GuestOS with ID: " + guestOSId + " does not exist.");
}
- }
- privateTemplate = new VMTemplateVO(nextTemplateId, name, ImageFormat.RAW, isPublic, featured, isExtractable,
- TemplateType.USER, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description,
- passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails(), sshKeyEnabledValue, isDynamicScalingEnabled, false, false, arch, null);
- if (sourceTemplateId != null) {
- if (logger.isDebugEnabled()) {
- logger.debug("This template is getting created from other template, setting source template Id to: " + sourceTemplateId);
+ Long nextTemplateId = _tmpltDao.getNextInSequence(Long.class, "id");
+ String description = cmd.getDisplayText();
+ boolean isExtractable = false;
+ Long sourceTemplateId = null;
+ if (volume != null) {
+ VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
+ isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
+ if (template != null) {
+ arch = template.getArch();
+ }
+ if (volume.getIsoId() != null && volume.getIsoId() != 0) {
+ sourceTemplateId = volume.getIsoId();
+ } else if (volume.getTemplateId() != null) {
+ sourceTemplateId = volume.getTemplateId();
+ }
}
- }
+ String templateTag = cmd.getTemplateTag();
+ if (templateTag != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Adding Template tag: " + templateTag);
+ }
+ }
+ privateTemplate = new VMTemplateVO(nextTemplateId, name, ImageFormat.RAW, isPublic, featured, isExtractable,
+ TemplateType.USER, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description,
+ passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails(), sshKeyEnabledValue, isDynamicScalingEnabled, false, false, arch, null);
+ if (sourceTemplateId != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("This Template is getting created from other Template, setting source Template ID to: " + sourceTemplateId);
+ }
+ }
- // for region wide storage, set cross zones flag
- List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores();
- if (!CollectionUtils.isEmpty(stores)) {
- privateTemplate.setCrossZones(true);
- }
+ // for region wide storage, set cross zones flag
+ List<ImageStoreVO> stores = _imgStoreDao.findRegionImageStores();
+ if (!CollectionUtils.isEmpty(stores)) {
+ privateTemplate.setCrossZones(true);
+ }
- privateTemplate.setSourceTemplateId(sourceTemplateId);
+ privateTemplate.setSourceTemplateId(sourceTemplateId);
- VMTemplateVO template = _tmpltDao.persist(privateTemplate);
- // Increment the number of templates
- if (template != null) {
- Map<String, String> details = new HashMap<String, String>();
+ VMTemplateVO template = _tmpltDao.persist(privateTemplate);
+ // Increment the number of templates
+ if (template != null) {
+ Map<String, String> details = new HashMap<String, String>();
- if (sourceTemplateId != null) {
- VMTemplateVO sourceTemplate = _tmpltDao.findById(sourceTemplateId);
- if (sourceTemplate != null && sourceTemplate.getDetails() != null) {
- details.putAll(sourceTemplate.getDetails());
+ if (sourceTemplateId != null) {
+ VMTemplateVO sourceTemplate = _tmpltDao.findById(sourceTemplateId);
+ if (sourceTemplate != null && sourceTemplate.getDetails() != null) {
+ details.putAll(sourceTemplate.getDetails());
+ }
}
- }
- if (volume != null) {
- Long vmId = volume.getInstanceId();
- if (vmId != null) {
- UserVmVO userVm = _userVmDao.findById(vmId);
- if (userVm != null) {
- _userVmDao.loadDetails(userVm);
- Map<String, String> vmDetails = userVm.getDetails();
- vmDetails = vmDetails.entrySet()
- .stream()
- .filter(map -> map.getValue() != null)
- .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
- details.putAll(vmDetails);
+ if (volume != null) {
+ Long vmId = volume.getInstanceId();
+ if (vmId != null) {
+ UserVmVO userVm = _userVmDao.findById(vmId);
+ if (userVm != null) {
+ _userVmDao.loadDetails(userVm);
+ Map<String, String> vmDetails = userVm.getDetails();
+ vmDetails = vmDetails.entrySet()
+ .stream()
+ .filter(map -> map.getValue() != null)
+ .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
+ details.putAll(vmDetails);
+ }
}
}
- }
- if (cmd.getDetails() != null) {
- details.remove(VmDetailConstants.ENCRYPTED_PASSWORD); // new password will be generated during vm deployment from password enabled template
- details.putAll(cmd.getDetails());
- }
- if (!details.isEmpty()) {
- privateTemplate.setDetails(details);
- _tmpltDao.saveDetails(privateTemplate);
- }
+ if (cmd.getDetails() != null) {
+ details.remove(VmDetailConstants.ENCRYPTED_PASSWORD); // new password will be generated during vm deployment from password enabled template
+ details.putAll(cmd.getDetails());
+ }
+ if (!details.isEmpty()) {
+ privateTemplate.setDetails(details);
+ _tmpltDao.saveDetails(privateTemplate);
+ }
- _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
- _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage,
- new Long(volume != null ? volume.getSize() : snapshot.getSize()));
- }
+ _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
+ _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage, templateSize);
+ }
- if (template != null) {
- CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
- return template;
- } else {
- throw new CloudRuntimeException("Failed to create a template");
+ if (template != null) {
+ CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
+ return template;
+ } else {
+ throw new CloudRuntimeException("Failed to create a Template");
+ }
}
-
}
@Override
@@ -2196,13 +2206,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_ISO_UPDATE, eventDescription = "updating iso", async = false)
+ @ActionEvent(eventType = EventTypes.EVENT_ISO_UPDATE, eventDescription = "Updating ISO", async = false)
public VMTemplateVO updateTemplate(UpdateIsoCmd cmd) {
return updateTemplateOrIso(cmd);
}
@Override
- @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_UPDATE, eventDescription = "updating template", async = false)
+ @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_UPDATE, eventDescription = "Updating Template", async = false)
public VMTemplateVO updateTemplate(UpdateTemplateCmd cmd) {
return updateTemplateOrIso(cmd);
}
@@ -2229,7 +2239,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
// verify that template exists
VMTemplateVO template = _tmpltDao.findById(id);
if (template == null || template.getRemoved() != null) {
- InvalidParameterValueException ex = new InvalidParameterValueException("unable to find template/iso with specified id");
+ InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Template/ISO with specified id");
ex.addProxyObject(String.valueOf(id), "templateId");
throw ex;
}
@@ -2275,7 +2285,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
templateTag == null &&
forCks == null &&
arch == null &&
- (! cleanupDetails && details == null) //update details in every case except this one
+ (! cleanupDetails && details == null) // update details in every case except this one
);
if (!updateNeeded) {
return template;
@@ -2434,9 +2444,9 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
validateExternalHypervisorTemplateType(hypervisorType, templateType);
if (templateType != null && !isAdmin && !Arrays.asList(TemplateType.USER, TemplateType.VNF).contains(templateType)) {
if (cmd instanceof RegisterTemplateCmd) {
- throw new InvalidParameterValueException(String.format("Users can not register template with template type %s.", templateType));
+ throw new InvalidParameterValueException(String.format("Users can not register Template with template type %s.", templateType));
} else if (cmd instanceof UpdateTemplateCmd) {
- throw new InvalidParameterValueException(String.format("Users can not update template to template type %s.", templateType));
+ throw new InvalidParameterValueException(String.format("Users can not update Template to template type %s.", templateType));
}
}
return templateType;
@@ -2455,13 +2465,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
if (MapUtils.isEmpty(details)) {
return;
}
-
String bootMode = details.get(ApiConstants.BootType.UEFI.toString());
if (bootMode == null) {
return;
}
if (template.isDeployAsIs()) {
- String msg = String.format("Deploy-as-is template %s can not have the UEFI setting. Settings are read directly from the template", template);
+ String msg = String.format("Deploy-as-is Template %s can not have the UEFI setting. Settings are read directly from the Template", template);
throw new InvalidParameterValueException(msg);
}
try {
@@ -2480,7 +2489,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
void verifyTemplateId(Long id) {
// Don't allow to modify system template
if (id.equals(Long.valueOf(1))) {
- InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id");
+ InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update Template/ISO of specified ID");
ex.addProxyObject(String.valueOf(id), "templateId");
throw ex;
}
@@ -2513,7 +2522,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
long templateId = template.getId();
TemplateInfo templateObject = _tmplFactory.getTemplate(templateId, role);
if (templateObject == null) {
- String msg = String.format("Could not find template %s downloaded on store with role %s", template, role.toString());
+ String msg = String.format("Could not find Template %s downloaded on store with role %s", template, role.toString());
logger.error(msg);
throw new CloudRuntimeException(msg);
}
@@ -2529,10 +2538,10 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
Account caller = CallContext.current().getCallingAccount();
if (templateId != null && isoId != null) {
- throw new InvalidParameterValueException("Both template ID and ISO ID are passed, API accepts only one");
+ throw new InvalidParameterValueException("Both Template ID and ISO ID are passed, API accepts only one");
}
if (templateId == null && isoId == null) {
- throw new InvalidParameterValueException("Atleast one of template ID or ISO ID needs to be passed");
+ throw new InvalidParameterValueException("At least one of Template ID or ISO ID needs to be passed");
}
VMTemplateVO template = null;
@@ -2542,7 +2551,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
template = _tmpltDao.findById(isoId);
}
if (template == null) {
- throw new InvalidParameterValueException(String.format("unable to find template/ISO with id %s", templateId == null? isoId : templateId));
+ throw new InvalidParameterValueException(String.format("Unable to find Template/ISO with ID %s", templateId == null? isoId : templateId));
}
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template);
diff --git a/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java b/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
index 99e4512ccef..f5e281a9516 100755
--- a/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
+++ b/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
@@ -22,8 +22,8 @@ package com.cloud.template;
import com.cloud.agent.AgentManager;
import com.cloud.api.query.dao.SnapshotJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
-import com.cloud.configuration.Resource;
import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
@@ -33,6 +33,7 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.projects.ProjectManager;
+import com.cloud.resourcelimit.CheckedReservation;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.Snapshot;
@@ -63,12 +64,14 @@ import com.cloud.user.User;
import com.cloud.user.UserData;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
-import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+
+import junit.framework.TestCase;
+
import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
@@ -104,14 +107,21 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.heuristics.HeuristicRuleHelper;
import org.apache.cloudstack.storage.template.VnfTemplateManager;
+
import org.apache.cloudstack.test.utils.SpringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedConstruction;
import org.mockito.Mockito;
+import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@@ -120,11 +130,7 @@ import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.support.AnnotationConfigContextLoader;
-import javax.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -137,81 +143,81 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
-public class TemplateManagerImplTest {
+@RunWith(MockitoJUnitRunner.class)
+public class TemplateManagerImplTest extends TestCase {
- @Inject
- TemplateManagerImpl templateManager = new TemplateManagerImpl();
+ @Spy
+ @InjectMocks
+ TemplateManagerImpl templateManager;
- @Inject
+ @Mock
DataStoreManager dataStoreManager;
- @Inject
+ @Mock
VMTemplateDao vmTemplateDao;
- @Inject
+ @Mock
VMTemplatePoolDao vmTemplatePoolDao;
- @Inject
+ @Mock
TemplateDataStoreDao templateDataStoreDao;
- @Inject
+ @Mock
StoragePoolHostDao storagePoolHostDao;
- @Inject
+ @Mock
PrimaryDataStoreDao primaryDataStoreDao;
- @Inject
+ @Mock
ResourceLimitService resourceLimitMgr;
- @Inject
+ @Mock
ImageStoreDao imgStoreDao;
- @Inject
+ @Mock
GuestOSDao guestOSDao;
- @Inject
- VMTemplateDao tmpltDao;
-
- @Inject
+ @Mock
SnapshotDao snapshotDao;
- @Inject
+ @Mock
+ VolumeDao volumeDao;
+
+ @Mock
VMTemplateDetailsDao tmpltDetailsDao;
- @Inject
+ @Mock
StorageStrategyFactory storageStrategyFactory;
- @Inject
+ @Mock
VMInstanceDao _vmInstanceDao;
- @Inject
- private VMTemplateDao _tmpltDao;
+ @Mock
+ ReservationDao reservationDao;
- @Inject
+ @Mock
HypervisorGuruManager _hvGuruMgr;
- @Inject
+ @Mock
AccountManager _accountMgr;
- @Inject
+
+ @Mock
VnfTemplateManager vnfTemplateManager;
- @Inject
+ @Mock
SnapshotJoinDao snapshotJoinDao;
- @Inject
- ReservationDao reservationDao;
+ @Mock
+ TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
- @Inject
+ @Mock
HeuristicRuleHelper heuristicRuleHelperMock;
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
@@ -241,7 +247,6 @@ public class TemplateManagerImplTest {
@Before
public void setUp() {
- ComponentContext.initComponentsLifeCycle();
AccountVO account = new AccountVO("admin", 1L, "networkDomain", Account.Type.NORMAL, "uuid");
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
CallContext.register(user, account);
@@ -275,7 +280,7 @@ public class TemplateManagerImplTest {
List<TemplateAdapter> adapters = new ArrayList<TemplateAdapter>();
adapters.add(templateAdapter);
when(cmd.getId()).thenReturn(0L);
- when(_tmpltDao.findById(cmd.getId())).thenReturn(template);
+ when(vmTemplateDao.findById(cmd.getId())).thenReturn(template);
when(cmd.getZoneId()).thenReturn(null);
when(template.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None);
@@ -296,7 +301,6 @@ public class TemplateManagerImplTest {
//case 2.2: When Force delete flag is 'false' and VM instance VO list is non empty.
when(cmd.isForced()).thenReturn(false);
VMInstanceVO vmInstanceVO = mock(VMInstanceVO.class);
- when(vmInstanceVO.getInstanceName()).thenReturn("mydDummyVM");
vmInstanceVOList.add(vmInstanceVO);
when(_vmInstanceDao.listNonExpungedByTemplate(anyLong())).thenReturn(vmInstanceVOList);
try {
@@ -311,7 +315,6 @@ public class TemplateManagerImplTest {
when(mockTemplate.getId()).thenReturn(202l);
StoragePoolVO mockPool = mock(StoragePoolVO.class);
- when(mockPool.getId()).thenReturn(2l);
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
when(mockPrimaryDataStore.getId()).thenReturn(2l);
@@ -319,7 +322,6 @@ public class TemplateManagerImplTest {
VMTemplateStoragePoolVO mockTemplateStore = mock(VMTemplateStoragePoolVO.class);
when(mockTemplateStore.getDownloadState()).thenReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
- when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
@@ -335,13 +337,11 @@ public class TemplateManagerImplTest {
when(mockTemplate.getId()).thenReturn(202l);
StoragePoolVO mockPool = mock(StoragePoolVO.class);
- when(mockPool.getId()).thenReturn(2l);
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
when(mockPrimaryDataStore.getId()).thenReturn(2l);
when(mockPrimaryDataStore.getDataCenterId()).thenReturn(1l);
- when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(null);
when(templateDataStoreDao.findByTemplateZoneDownloadStatus(202l, 1l, VMTemplateStorageResourceAssoc.Status.DOWNLOADED)).thenReturn(null);
@@ -356,7 +356,6 @@ public class TemplateManagerImplTest {
when(mockTemplate.getId()).thenReturn(202l);
StoragePoolVO mockPool = mock(StoragePoolVO.class);
- when(mockPool.getId()).thenReturn(2l);
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
when(mockPrimaryDataStore.getId()).thenReturn(2l);
@@ -364,7 +363,6 @@ public class TemplateManagerImplTest {
TemplateDataStoreVO mockTemplateDataStore = mock(TemplateDataStoreVO.class);
- when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(null);
when(templateDataStoreDao.findByTemplateZoneDownloadStatus(202l, 1l, VMTemplateStorageResourceAssoc.Status.DOWNLOADED)).thenReturn(mockTemplateDataStore);
@@ -415,20 +413,10 @@ public class TemplateManagerImplTest {
PrimaryDataStore mockPrimaryDataStore = mock(PrimaryDataStore.class);
VMTemplateStoragePoolVO mockTemplateStore = mock(VMTemplateStoragePoolVO.class);
- when(mockPrimaryDataStore.getId()).thenReturn(2l);
- when(mockPool.getId()).thenReturn(2l);
when(mockPool.getStatus()).thenReturn(StoragePoolStatus.Disabled);
- when(mockPool.getDataCenterId()).thenReturn(1l);
- when(mockTemplate.getId()).thenReturn(202l);
- when(mockTemplateStore.getDownloadState()).thenReturn(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
when(vmTemplateDao.findById(anyLong())).thenReturn(mockTemplate);
- when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
- when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
- when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
when(primaryDataStoreDao.findById(anyLong())).thenReturn(mockPool);
- doNothing().when(mockTemplateStore).setMarkedForGC(anyBoolean());
-
ExecutorService preloadExecutor = new CustomThreadPoolExecutor(8, 8, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(),
new NamedThreadFactory("Template-Preloader"));
templateManager._preloadExecutor = preloadExecutor;
@@ -446,15 +434,10 @@ public class TemplateManagerImplTest {
StoragePoolVO mockPool1 = mock(StoragePoolVO.class);
when(mockPool1.getId()).thenReturn(2l);
- when(mockPool1.getStatus()).thenReturn(StoragePoolStatus.Up);
when(mockPool1.getDataCenterId()).thenReturn(1l);
StoragePoolVO mockPool2 = mock(StoragePoolVO.class);
- when(mockPool2.getId()).thenReturn(3l);
- when(mockPool2.getStatus()).thenReturn(StoragePoolStatus.Up);
when(mockPool2.getDataCenterId()).thenReturn(1l);
StoragePoolVO mockPool3 = mock(StoragePoolVO.class);
- when(mockPool3.getId()).thenReturn(4l);
- when(mockPool3.getStatus()).thenReturn(StoragePoolStatus.Up);
when(mockPool3.getDataCenterId()).thenReturn(2l);
pools.add(mockPool1);
pools.add(mockPool2);
@@ -467,9 +450,6 @@ public class TemplateManagerImplTest {
when(dataStoreManager.getPrimaryDataStore(anyLong())).thenReturn(mockPrimaryDataStore);
when(vmTemplateDao.findById(anyLong(), anyBoolean())).thenReturn(mockTemplate);
when(vmTemplatePoolDao.findByPoolTemplate(anyLong(), anyLong(), nullable(String.class))).thenReturn(mockTemplateStore);
- when(primaryDataStoreDao.findById(2l)).thenReturn(mockPool1);
- when(primaryDataStoreDao.findById(3l)).thenReturn(mockPool2);
- when(primaryDataStoreDao.findById(4l)).thenReturn(mockPool3);
when(primaryDataStoreDao.listByStatus(StoragePoolStatus.Up)).thenReturn(pools);
doNothing().when(mockTemplateStore).setMarkedForGC(anyBoolean());
@@ -497,7 +477,6 @@ public class TemplateManagerImplTest {
when(mockCreateCmd.getVolumeId()).thenReturn(null);
when(mockCreateCmd.getSnapshotId()).thenReturn(1L);
when(mockCreateCmd.getOsTypeId()).thenReturn(1L);
- when(mockCreateCmd.getEventDescription()).thenReturn("test");
when(mockCreateCmd.getDetails()).thenReturn(null);
when(mockCreateCmd.getZoneId()).thenReturn(null);
@@ -510,20 +489,17 @@ public class TemplateManagerImplTest {
when(mockSnapshot.getState()).thenReturn(Snapshot.State.BackedUp);
when(mockSnapshot.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer);
- doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.template));
- doNothing().when(resourceLimitMgr).checkResourceLimit(any(Account.class), eq(Resource.ResourceType.secondary_storage), anyLong());
-
GuestOSVO mockGuestOS = mock(GuestOSVO.class);
when(guestOSDao.findById(anyLong())).thenReturn(mockGuestOS);
- when(tmpltDao.getNextInSequence(eq(Long.class), eq("id"))).thenReturn(1L);
+ when(vmTemplateDao.getNextInSequence(eq(Long.class), eq("id"))).thenReturn(1L);
List<ImageStoreVO> mockRegionStores = new ArrayList<>();
ImageStoreVO mockRegionStore = mock(ImageStoreVO.class);
mockRegionStores.add(mockRegionStore);
when(imgStoreDao.findRegionImageStores()).thenReturn(mockRegionStores);
- when(tmpltDao.persist(any(VMTemplateVO.class))).thenAnswer(new Answer<VMTemplateVO>() {
+ when(vmTemplateDao.persist(any(VMTemplateVO.class))).thenAnswer(new Answer<VMTemplateVO>() {
@Override
public VMTemplateVO answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments();
@@ -531,8 +507,10 @@ public class TemplateManagerImplTest {
}
});
- VMTemplateVO template = templateManager.createPrivateTemplateRecord(mockCreateCmd, mockTemplateOwner);
- assertTrue("Template in a region store should have cross zones set", template.isCrossZones());
+ try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
+ VMTemplateVO template = templateManager.createPrivateTemplateRecord(mockCreateCmd, mockTemplateOwner);
+ assertTrue("Template in a region store should have cross zones set", template.isCrossZones());
+ }
}
@Test
@@ -544,7 +522,7 @@ public class TemplateManagerImplTest {
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
- when(_tmpltDao.findById(anyLong())).thenReturn(template);
+ when(vmTemplateDao.findById(anyLong())).thenReturn(template);
VirtualMachineTemplate resultTemplate = templateManager.linkUserDataToTemplate(cmd);
@@ -560,7 +538,6 @@ public class TemplateManagerImplTest {
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
- when(_tmpltDao.findById(1L)).thenReturn(template);
templateManager.linkUserDataToTemplate(cmd);
}
@@ -574,7 +551,6 @@ public class TemplateManagerImplTest {
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
- when(_tmpltDao.findById(1L)).thenReturn(template);
templateManager.linkUserDataToTemplate(cmd);
}
@@ -587,7 +563,7 @@ public class TemplateManagerImplTest {
when(cmd.getUserdataId()).thenReturn(2L);
when(cmd.getUserdataPolicy()).thenReturn(UserData.UserDataOverridePolicy.ALLOWOVERRIDE);
- when(_tmpltDao.findById(anyLong())).thenReturn(null);
+ when(vmTemplateDao.findById(anyLong())).thenReturn(null);
templateManager.linkUserDataToTemplate(cmd);
}
@@ -602,7 +578,7 @@ public class TemplateManagerImplTest {
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
when(template.getId()).thenReturn(1L);
- when(_tmpltDao.findById(1L)).thenReturn(template);
+ when(vmTemplateDao.findById(1L)).thenReturn(template);
VirtualMachineTemplate resultTemplate = templateManager.linkUserDataToTemplate(cmd);
@@ -633,7 +609,6 @@ public class TemplateManagerImplTest {
DataStore dataStore = Mockito.mock(DataStore.class);
VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
- Mockito.when(dataStoreManager.getDataStore(Mockito.anyString(), Mockito.any(DataStoreRole.class))).thenReturn(null);
Mockito.when(heuristicRuleHelperMock.getImageStoreIfThereIsHeuristicRule(Mockito.anyLong(), Mockito.any(HeuristicType.class), Mockito.any(VolumeVO.class))).thenReturn(null);
Mockito.when(dataStoreManager.getImageStoreWithFreeCapacity(Mockito.anyLong())).thenReturn(dataStore);
@@ -646,7 +621,6 @@ public class TemplateManagerImplTest {
DataStore dataStore = Mockito.mock(DataStore.class);
VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
- Mockito.when(dataStoreManager.getDataStore(Mockito.anyString(), Mockito.any(DataStoreRole.class))).thenReturn(null);
Mockito.when(heuristicRuleHelperMock.getImageStoreIfThereIsHeuristicRule(Mockito.anyLong(), Mockito.any(HeuristicType.class), Mockito.any(VolumeVO.class))).thenReturn(dataStore);
templateManager.getImageStore(null, 1L, volumeVO);