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 09:56:00 UTC
(cloudstack) 02/02: Merge branch '22.0.1' into 4.22
This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 2b84ddb9b1d0d735b3eb882d82e238041dc681c6
Merge: 7c7b2ae75d1 d6f4fc3ac40
Author: Daan Hoogland <da...@apache.org>
AuthorDate: Mon Apr 13 11:55:17 2026 +0200
Merge branch '22.0.1' into 4.22
.../main/java/com/cloud/agent/api/to/BucketTO.java | 7 +
.../java/com/cloud/projects/ProjectService.java | 4 +-
.../storage/VMTemplateStorageResourceAssoc.java | 3 +-
.../java/com/cloud/user/ResourceLimitService.java | 20 +-
.../org/apache/cloudstack/api/ApiConstants.java | 1 +
.../user/account/AddAccountToProjectCmd.java | 3 +-
.../command/user/account/AddUserToProjectCmd.java | 3 +-
.../RestoreVolumeFromBackupAndAttachToVMCmd.java | 4 +
.../api/command/user/vm/CreateVMFromBackupCmd.java | 1 +
.../cloudstack/api/response/ExtensionResponse.java | 10 +
.../cloudstack/extension/ExtensionHelper.java | 3 +
.../Reserver.java} | 16 +-
.../command/test/AddAccountToProjectCmdTest.java | 3 +
.../cloud/agent/api/storage/DownloadAnswer.java | 2 +-
.../download/DirectTemplateDownloaderImpl.java | 11 +-
.../download/MetalinkDirectTemplateDownloader.java | 2 +-
.../download/NfsDirectTemplateDownloader.java | 2 +-
.../command/TemplateOrVolumePostUploadCommand.java | 8 +
.../storage/command/UploadStatusCommand.java | 10 +
.../service/NetworkOrchestrationService.java | 2 +-
.../service/VolumeOrchestrationService.java | 2 +-
.../com/cloud/vm/VirtualMachineManagerImpl.java | 26 +-
.../engine/orchestration/NetworkOrchestrator.java | 46 +-
.../engine/orchestration/VolumeOrchestrator.java | 24 +-
.../java/com/cloud/dc/dao/AccountVlanMapDao.java | 2 +-
.../com/cloud/dc/dao/AccountVlanMapDaoImpl.java | 4 +-
.../java/com/cloud/dc/dao/DomainVlanMapDao.java | 2 +-
.../com/cloud/dc/dao/DomainVlanMapDaoImpl.java | 4 +-
.../META-INF/db/views/cloud.user_vm_view.sql | 1 +
.../storage/image/BaseImageStoreDriverImpl.java | 26 +-
.../extensions/api/CreateExtensionCmd.java | 10 +
.../extensions/api/UpdateExtensionCmd.java | 10 +
.../extensions/manager/ExtensionsManagerImpl.java | 98 +++-
.../extensions/api/CreateExtensionCmdTest.java | 14 +
.../extensions/api/UpdateExtensionCmdTest.java | 15 +
.../manager/ExtensionsManagerImplTest.java | 167 +++++-
.../manager/BareMetalTemplateAdapter.java | 1 -
.../driver/MinIOObjectStoreDriverImpl.java | 81 ++-
.../driver/MinIOObjectStoreDriverImplTest.java | 7 +-
server/src/main/java/com/cloud/api/ApiDBUtils.java | 4 +
.../com/cloud/api/query/dao/UserVmJoinDaoImpl.java | 23 +-
.../java/com/cloud/api/query/vo/UserVmJoinVO.java | 7 +
.../configuration/ConfigurationManagerImpl.java | 128 +++--
.../java/com/cloud/network/NetworkServiceImpl.java | 26 +-
.../java/com/cloud/network/vpc/VpcManagerImpl.java | 51 +-
.../com/cloud/projects/ProjectManagerImpl.java | 52 +-
.../cloud/resourcelimit/CheckedReservation.java | 117 +++-
.../com/cloud/resourcelimit/ReservationHelper.java | 21 +-
.../resourcelimit/ResourceLimitManagerImpl.java | 212 +++----
.../cloud/storage/ImageStoreUploadMonitorImpl.java | 180 +++++-
.../com/cloud/storage/VolumeApiServiceImpl.java | 636 +++++++++++----------
.../storage/download/DownloadActiveState.java | 5 +
.../cloud/storage/download/DownloadErrorState.java | 5 +
.../storage/download/DownloadInactiveState.java | 6 +
.../download/DownloadLimitReachedState.java | 54 ++
.../cloud/storage/download/DownloadListener.java | 89 ++-
.../com/cloud/storage/download/DownloadState.java | 6 +-
.../storage/snapshot/SnapshotManagerImpl.java | 214 +++----
.../cloud/template/HypervisorTemplateAdapter.java | 39 +-
.../com/cloud/template/TemplateAdapterBase.java | 4 +-
.../com/cloud/template/TemplateManagerImpl.java | 256 +++++----
.../main/java/com/cloud/vm/UserVmManagerImpl.java | 322 ++++++++---
.../cloud/vm/snapshot/VMSnapshotManagerImpl.java | 21 +-
.../cloudstack/backup/BackupManagerImpl.java | 129 +++--
.../storage/object/BucketApiServiceImpl.java | 114 ++--
.../volume/VolumeImportUnmanageManagerImpl.java | 20 +-
.../cloudstack/vm/UnmanagedVMsManagerImpl.java | 425 ++++++++------
.../cloud/api/query/dao/UserVmJoinDaoImplTest.java | 1 +
.../com/cloud/network/vpc/VpcManagerImplTest.java | 14 +-
.../resourcelimit/CheckedReservationTest.java | 17 +-
.../ResourceLimitManagerImplTest.java | 108 +---
.../cloud/storage/VolumeApiServiceImplTest.java | 52 +-
.../storage/snapshot/SnapshotManagerImplTest.java | 4 +-
.../storage/snapshot/SnapshotManagerTest.java | 55 +-
.../cloud/template/TemplateManagerImplTest.java | 132 ++---
.../java/com/cloud/vm/UserVmManagerImplTest.java | 43 +-
.../cloud/vm/snapshot/VMSnapshotManagerTest.java | 2 +-
.../java/com/cloud/vpc/MockNetworkManagerImpl.java | 2 +-
.../cloud/vpc/MockResourceLimitManagerImpl.java | 41 +-
.../cloudstack/backup/BackupManagerTest.java | 127 +++-
.../storage/object/BucketApiServiceImplTest.java | 137 ++++-
.../VolumeImportUnmanageManagerImplTest.java | 3 -
.../cloudstack/vm/UnmanagedVMsManagerImplTest.java | 57 +-
.../storage/resource/HttpUploadServerHandler.java | 2 +
.../resource/NfsSecondaryStorageResource.java | 33 +-
.../storage/template/DownloadManagerImpl.java | 2 +-
ui/public/locales/en.json | 1 +
ui/src/config/section/extension.js | 2 +-
ui/src/views/extension/CreateExtension.vue | 11 +
ui/src/views/extension/UpdateExtension.vue | 17 +-
90 files changed, 3015 insertions(+), 1669 deletions(-)
diff --cc api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVolumeFromBackupAndAttachToVMCmd.java
index cee367a149c,e0398d4f49b..90ebbd5a595
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVolumeFromBackupAndAttachToVMCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVolumeFromBackupAndAttachToVMCmd.java
@@@ -57,9 -59,10 +59,10 @@@ public class RestoreVolumeFromBackupAnd
type = CommandType.UUID,
entityType = BackupResponse.class,
required = true,
- description = "ID of the VM backup")
+ description = "ID of the Instance backup")
private Long backupId;
+ @ACL
@Parameter(name = ApiConstants.VOLUME_ID,
type = CommandType.STRING,
required = true,
diff --cc engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
index af8ff83396d,2cf919c39e3..933accbda52
--- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
+++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
@@@ -901,9 -903,9 +903,9 @@@ public class VolumeOrchestrator extend
saveVolumeDetails(offering.getId(), vol.getId());
// Save usage event and update resource count for user vm volumes
- if (vm.getType() == VirtualMachine.Type.User) {
+ if (vm.getType() == VirtualMachine.Type.User && incrementResourceCount) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
- Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
+ Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
}
DiskProfile diskProfile = toDiskProfile(vol, offering);
diff --cc server/src/main/java/com/cloud/network/NetworkServiceImpl.java
index dea8a7ec83e,d872317fa28..b610867275e
--- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
@@@ -1150,17 -1154,12 +1154,12 @@@ public class NetworkServiceImpl extend
}
Long ipDedicatedAccountId = getIpDedicatedAccountId(ipVO.getVlanId());
if (ipDedicatedAccountId != null && !ipDedicatedAccountId.equals(account.getAccountId())) {
- throw new InvalidParameterValueException("Unable to reserve a IP because it is dedicated to another account.");
+ throw new InvalidParameterValueException("Unable to reserve a IP because it is dedicated to another Account.");
}
- if (ipDedicatedAccountId == null) {
- // Check that the maximum number of public IPs for the given accountId will not be exceeded
- try {
- _resourceLimitMgr.checkResourceLimit(account, Resource.ResourceType.public_ip);
- } catch (ResourceAllocationException ex) {
- logger.warn("Failed to allocate resource of type " + ex.getResourceType() + " for account " + account);
- throw new AccountLimitException("Maximum number of public IP addresses for account: " + account.getAccountName() + " has been exceeded.");
- }
- }
+
+ long reservedIpAddressesAmount = ipDedicatedAccountId == null ? 1L : 0L;
+ try (CheckedReservation publicIpAddressReservation = new CheckedReservation(account, Resource.ResourceType.public_ip, reservedIpAddressesAmount, reservationDao, _resourceLimitMgr)) {
+
List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(ipVO.getVlanId());
ipVO.setAllocatedTime(new Date());
ipVO.setAllocatedToAccountId(account.getAccountId());
diff --cc server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
index f4548ed5e8f,37976523a34..9e7c644cf65
--- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
+++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java
@@@ -1236,12 -1246,10 +1247,11 @@@ public class ResourceLimitManagerImpl e
List<ResourceCountVO> resourceCounts = _resourceCountDao.lockRows(rowIdsToLock);
long oldResourceCount = 0L;
+ long newResourceCount = 0L;
ResourceCountVO domainRC = null;
- // calculate project count here
- if (type == ResourceType.project) {
- newResourceCount += _projectDao.countProjectsForDomain(domainId);
+ if (type == ResourceType.network) {
+ newResourceCount += networkDomainDao.listDomainNetworkMapByDomain(domainId).size();
}
// TODO make sure that the resource counts are not null
diff --cc server/src/main/java/com/cloud/template/TemplateManagerImpl.java
index a2cb82a0a6b,38fd9ab205b..527f8037c35
--- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
@@@ -318,10 -317,8 +317,9 @@@ public class TemplateManagerImpl extend
VnfTemplateManager vnfTemplateManager;
@Inject
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
+
@Inject
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
-
@Inject
private HeuristicRuleHelper heuristicRuleHelper;
@@@ -380,17 -397,32 +398,35 @@@
}
TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
- TemplateProfile profile = adapter.prepare(cmd);
- VMTemplateVO template = adapter.create(profile);
+ Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId());
- if (template != null) {
- CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
- if (cmd instanceof RegisterVnfTemplateCmd) {
- vnfTemplateManager.persistVnfTemplate(template.getId(), (RegisterVnfTemplateCmd) cmd);
+ long secondaryStorageUsage = adapter instanceof HypervisorTemplateAdapter && !cmd.isDirectDownload() ?
+ UriUtils.getRemoteSize(cmd.getUrl(), StorageManager.DataStoreDownloadFollowRedirects.value()) : 0L;
+
+ try (CheckedReservation templateReservation = new CheckedReservation(owner, ResourceType.template, null, null, 1L, reservationDao, _resourceLimitMgr);
+ CheckedReservation secondaryStorageReservation = new CheckedReservation(owner, ResourceType.secondary_storage, null, null, secondaryStorageUsage, reservationDao, _resourceLimitMgr)) {
+ TemplateProfile profile = adapter.prepare(cmd);
+ VMTemplateVO template = adapter.create(profile);
+
+ // Secondary storage resource usage will be recalculated in com.cloud.template.HypervisorTemplateAdapter.createTemplateAsyncCallBack
+ // for HypervisorTemplateAdapter
+ _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
+ if (secondaryStorageUsage > 0) {
+ _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, secondaryStorageUsage);
+ }
+
+ if (template != null) {
+ CallContext.current().putContextParameter(VirtualMachineTemplate.class, template.getUuid());
+ if (cmd instanceof RegisterVnfTemplateCmd) {
+ vnfTemplateManager.persistVnfTemplate(template.getId(), (RegisterVnfTemplateCmd) cmd);
+ }
+ return template;
+ } else {
+ throw new CloudRuntimeException("Failed to create a Template");
}
+ return template;
+ } else {
+ throw new CloudRuntimeException("Failed to create a Template");
}
}
@@@ -1990,107 -2019,106 +2038,106 @@@
}
}
- _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 (!isAdmin || featured == null) {
+ featured = Boolean.FALSE;
}
- if (volume.getIsoId() != null && volume.getIsoId() != 0) {
- sourceTemplateId = volume.getIsoId();
- } else if (volume.getTemplateId() != null) {
- sourceTemplateId = volume.getTemplateId();
+ 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();
- }
+ }
+ String templateTag = cmd.getTemplateTag();
+ if (templateTag != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Adding Template tag: " + templateTag);
}
- 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);
}
- }
+ 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, templateSize);
}
- _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template);
- _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.secondary_storage,
- new Long(volume != null ? volume.getSize() : snapshot.getSize()));
+ 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
diff --cc server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 9cec033d07c,7050da266c7..1653c44fb2e
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@@ -1192,9 -1192,9 +1192,9 @@@ public class UserVmManagerImpl extends
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
//List all networks of vm
List<Long> vmNetworks = _vmNetworkMapDao.getNetworks(vmId);
- List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
+ List<DomainRouterVO> routers = new ArrayList<>();
//List the stopped routers
- for(long vmNetworkId : vmNetworks) {
+ for (long vmNetworkId : vmNetworks) {
List<DomainRouterVO> router = _routerDao.listStopped(vmNetworkId);
routers.addAll(router);
}
@@@ -5769,133 -5824,21 +5923,142 @@@
if (owner.getState() == Account.State.DISABLED) {
throw new PermissionDeniedException(String.format("The owner of %s is disabled: %s", vm, owner));
}
+ boolean isRootAdmin = _accountService.isRootAdmin(callerAccount.getId());
+
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
if (VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
- // check if account/domain is with in resource limits to start a new vm
ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
- resourceLimitService.checkVmResourceLimit(owner, vm.isDisplayVm(), offering, template);
+ List<String> resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(offering, template);
+ try (CheckedReservation vmReservation = new CheckedReservation(owner, ResourceType.user_vm, resourceLimitHostTags, 1l, reservationDao, resourceLimitService);
+ CheckedReservation cpuReservation = new CheckedReservation(owner, ResourceType.cpu, resourceLimitHostTags, Long.valueOf(offering.getCpu()), reservationDao, resourceLimitService);
+ CheckedReservation memReservation = new CheckedReservation(owner, ResourceType.memory, resourceLimitHostTags, Long.valueOf(offering.getRamSize()), reservationDao, resourceLimitService);
+ ) {
+ return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
+ }
+ } else {
+ return startVirtualMachineUnchecked(vm, template, podId, clusterId, hostId, additionalParams, deploymentPlannerToUse, isExplicitHost, isRootAdmin);
}
+ // check if vm is security group enabled
+ if (_securityGroupMgr.isVmSecurityGroupEnabled(vmId) && _securityGroupMgr.getSecurityGroupsForVm(vmId).isEmpty()
+ && !_securityGroupMgr.isVmMappedToDefaultSecurityGroup(vmId) && _networkModel.canAddDefaultSecurityGroup()) {
+ // if vm is not mapped to security group, create a mapping
+ if (logger.isDebugEnabled()) {
+ logger.debug("Vm " + vm + " is security group enabled, but not mapped to default security group; creating the mapping automatically");
+ }
+
+ SecurityGroup defaultSecurityGroup = _securityGroupMgr.getDefaultSecurityGroup(vm.getAccountId());
+ if (defaultSecurityGroup != null) {
+ List<Long> groupList = new ArrayList<Long>();
+ groupList.add(defaultSecurityGroup.getId());
+ _securityGroupMgr.addInstanceToGroups(vm, groupList);
+ }
+ }
+ // Choose deployment planner
+ // Host takes 1st preference, Cluster takes 2nd preference and Pod takes 3rd
+ // Default behaviour is invoked when host, cluster or pod are not specified
+ boolean isRootAdmin = _accountService.isRootAdmin(callerAccount.getId());
+ Pod destinationPod = getDestinationPod(podId, isRootAdmin);
+ Cluster destinationCluster = getDestinationCluster(clusterId, isRootAdmin);
+ HostVO destinationHost = getDestinationHost(hostId, isRootAdmin, isExplicitHost);
+ DataCenterDeployment plan = null;
+ boolean deployOnGivenHost = false;
+ if (destinationHost != null) {
+ logger.debug("Destination Host to deploy the VM is specified, specifying a deployment plan to deploy the VM");
+ _hostDao.loadHostTags(destinationHost);
+ validateStrictHostTagCheck(vm, destinationHost);
+
+ final ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());
+ Pair<Boolean, Boolean> cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(destinationHost, offering, false);
+ if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) {
+ String errorMsg;
+ if (!cpuCapabilityAndCapacity.first()) {
+ errorMsg = String.format("Cannot deploy the VM to specified host %s, requested CPU and speed is more than the host capability", destinationHost);
+ } else {
+ errorMsg = String.format("Cannot deploy the VM to specified host %s, host does not have enough free CPU or RAM, please check the logs", destinationHost);
+ }
+ logger.info(errorMsg);
+ if (!AllowDeployVmIfGivenHostFails.value()) {
+ throw new InvalidParameterValueException(errorMsg);
+ };
+ } else {
+ plan = new DataCenterDeployment(vm.getDataCenterId(), destinationHost.getPodId(), destinationHost.getClusterId(), destinationHost.getId(), null, null);
+ if (!AllowDeployVmIfGivenHostFails.value()) {
+ deployOnGivenHost = true;
+ }
+ }
+ } else if (destinationCluster != null) {
+ logger.debug("Destination Cluster to deploy the VM is specified, specifying a deployment plan to deploy the VM");
+ plan = new DataCenterDeployment(vm.getDataCenterId(), destinationCluster.getPodId(), destinationCluster.getId(), null, null, null);
+ if (!AllowDeployVmIfGivenHostFails.value()) {
+ deployOnGivenHost = true;
+ }
+ } else if (destinationPod != null) {
+ logger.debug("Destination Pod to deploy the VM is specified, specifying a deployment plan to deploy the VM");
+ plan = new DataCenterDeployment(vm.getDataCenterId(), destinationPod.getId(), null, null, null, null);
+ if (!AllowDeployVmIfGivenHostFails.value()) {
+ deployOnGivenHost = true;
+ }
+ }
+
+ // Set parameters
+ Map<VirtualMachineProfile.Param, Object> params = null;
+ if (vm.isUpdateParameters()) {
+ _vmDao.loadDetails(vm);
+
+ String password = getCurrentVmPasswordOrDefineNewPassword(String.valueOf(additionalParams.getOrDefault(VirtualMachineProfile.Param.VmPassword, "")), vm, template);
+
+ if (!validPassword(password)) {
+ throw new InvalidParameterValueException("A valid password for this virtual machine was not provided.");
+ }
+
+ // Check if an SSH key pair was selected for the instance and if so
+ // use it to encrypt & save the vm password
+ encryptAndStorePassword(vm, password);
+
+ params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.VmPassword, password);
+ }
+
+ if (additionalParams.containsKey(VirtualMachineProfile.Param.BootIntoSetup)) {
+ if (! HypervisorType.VMware.equals(vm.getHypervisorType())) {
+ throw new InvalidParameterValueException(ApiConstants.BOOT_INTO_SETUP + " makes no sense for " + vm.getHypervisorType());
+ }
+ Object paramValue = additionalParams.get(VirtualMachineProfile.Param.BootIntoSetup);
+ if (logger.isTraceEnabled()) {
+ logger.trace("It was specified whether to enter setup mode: " + paramValue.toString());
+ }
+ params = createParameterInParameterMap(params, additionalParams, VirtualMachineProfile.Param.BootIntoSetup, paramValue);
+ }
+
+ VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
+
+ DeploymentPlanner planner = null;
+ if (deploymentPlannerToUse != null) {
+ // if set to null, the deployment planner would be later figured out either from global config var, or from
+ // the service offering
+ planner = _planningMgr.getDeploymentPlannerByName(deploymentPlannerToUse);
+ if (planner == null) {
+ throw new InvalidParameterValueException("Can't find a planner by name " + deploymentPlannerToUse);
+ }
+ }
+ vmEntity.setParamsToEntity(additionalParams);
+
+ String reservationId = vmEntity.reserve(planner, plan, new ExcludeList(), Long.toString(callerUser.getId()));
+ vmEntity.deploy(reservationId, Long.toString(callerUser.getId()), params, deployOnGivenHost);
+
+ Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);
+ if (vm != null && vm.isUpdateParameters()) {
+ // this value is not being sent to the backend; need only for api
+ // display purposes
+ if (template.isEnablePassword()) {
+ if (vm.getDetail(VmDetailConstants.PASSWORD) != null) {
+ vmInstanceDetailsDao.removeDetail(vm.getId(), VmDetailConstants.PASSWORD);
+ }
+ vm.setUpdateParameters(false);
+ _vmDao.update(vm.getId(), vm);
+ }
+ }
+
+ return vmParamPair;
}
/**
diff --cc server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 6f7b96453ac,b2e820bce94..f61d1930c1b
--- a/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@@ -845,12 -844,12 +851,12 @@@ public class VMSnapshotManagerImpl exte
* @param vmSnapshotVo vm snapshot
*/
protected void changeUserVmServiceOffering(UserVm userVm, VMSnapshotVO vmSnapshotVo) {
- Map<String, String> vmDetails = getVmMapDetails(userVm);
+ Map<String, String> vmDetails = getVmMapDetails(vmSnapshotVo);
boolean result = upgradeUserVmServiceOffering(userVm, vmSnapshotVo.getServiceOfferingId(), vmDetails);
if (! result){
- throw new CloudRuntimeException("VM Snapshot reverting failed due to vm service offering couldn't be changed to the one used when snapshot was taken");
+ throw new CloudRuntimeException("Instance Snapshot reverting failed because the Instance service offering couldn't be changed to the one used when Snapshot was taken");
}
- logger.debug("Successfully changed service offering to {} for vm {}", _serviceOfferingDao.findById(vmSnapshotVo.getServiceOfferingId()), userVm);
+ logger.debug("Successfully changed service offering to {} for Instance {}", _serviceOfferingDao.findById(vmSnapshotVo.getServiceOfferingId()), userVm);
}
/**
@@@ -942,8 -941,8 +948,9 @@@
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<CloudRuntimeException>() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) throws CloudRuntimeException {
+ revertCustomServiceOfferingDetailsFromVmSnapshot(userVm, vmSnapshotVo);
updateUserVmServiceOffering(userVm, vmSnapshotVo);
+ revertUserVmDetailsFromVmSnapshot(userVm, vmSnapshotVo);
}
});
return userVm;
diff --cc server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index e9ed8e42eaa,088517e705b..152d6286969
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@@ -1538,33 -1549,37 +1549,49 @@@ public class BackupManagerImpl extends
throw new CloudRuntimeException(String.format("Backup offering with ID [%s] does not exist.", backup.getBackupOfferingId()));
}
final BackupProvider backupProvider = getBackupProvider(backup.getZoneId());
- boolean result = backupProvider.deleteBackup(backup, forced);
- if (result) {
- resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
- Long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
- resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
- if (backupDao.remove(backup.getId())) {
- checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
- return true;
- } else {
- return false;
+ return deleteCheckedBackup(forced, backupProvider, backup, vm);
+ }
+
+ private boolean deleteCheckedBackup(Boolean forced, BackupProvider backupProvider, BackupVO backup, VMInstanceVO vm) {
+ Account owner = accountManager.getAccount(backup.getAccountId());
+ long backupSize = backup.getSize() != null ? backup.getSize() : 0L;
+ try (CheckedReservation backupReservation = new CheckedReservation(owner, Resource.ResourceType.backup,
+ backup.getId(), null, -1L, reservationDao, resourceLimitMgr);
+ CheckedReservation backupStorageReservation = new CheckedReservation(owner,
+ Resource.ResourceType.backup_storage, backup.getId(), null, -1 * backupSize,
+ reservationDao, resourceLimitMgr)) {
+ boolean result = backupProvider.deleteBackup(backup, forced);
+ if (result) {
+ resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup);
+ resourceLimitMgr.decrementResourceCount(backup.getAccountId(), Resource.ResourceType.backup_storage, backupSize);
+ if (backupDao.remove(backup.getId())) {
+ checkAndGenerateUsageForLastBackupDeletedAfterOfferingRemove(vm, backup);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ throw new CloudRuntimeException("Failed to delete the backup");
+ } catch (Exception e) {
+ if (e instanceof CloudRuntimeException) {
+ throw (CloudRuntimeException) e;
}
+ throw new CloudRuntimeException("Failed to delete the backup due to: " + e.getMessage(), e);
}
- throw new CloudRuntimeException("Failed to delete the backup");
}
+ private void checkForPendingBackupJobs(final BackupVO backup) {
+ String backupUuid = backup.getUuid();
+ long pendingJobs = asyncJobManager.countPendingJobs(backupUuid,
+ CreateVMFromBackupCmd.class.getName(),
+ CreateVMFromBackupCmdByAdmin.class.getName(),
+ RestoreBackupCmd.class.getName(),
+ RestoreVolumeFromBackupAndAttachToVMCmd.class.getName());
+ if (pendingJobs > 0) {
+ throw new CloudRuntimeException("Cannot delete Backup while a create Instance from Backup or restore Backup operation is in progress, please try again later.");
+ }
+ }
+
/**
* Get the pair: hostIp, datastoreUuid in which to restore the volume, based on the VM to be attached information
*/
diff --cc server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
index e043791c6bf,75f87931591..d48b9e17d83
--- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
@@@ -1135,99 -1171,103 +1107,185 @@@ public class UnmanagedVMsManagerImpl im
allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size));
}
+ List<Reserver> reservations = new ArrayList<>();
try {
- checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed);
+ checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations);
if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present
- checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed);
+ checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations);
allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController());
}
- checkUnmanagedDiskLimits(owner, rootDisk, serviceOffering, dataDisks, dataDiskOfferingMap);
- } catch (ResourceAllocationException e) {
+
+ // Check NICs and supplied networks
+ Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
+ Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType());
+ if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
+ allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
+ }
+
+ if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) {
+ allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword());
+ }
+
+ addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails);
+
+ VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
+ if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) {
+ powerState = VirtualMachine.PowerState.PowerOn;
+ }
+
+ try {
+ userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner,
+ null, caller, true, null, owner.getAccountId(), userId,
+ validatedServiceOffering, null, hostName,
+ cluster.getHypervisorType(), allDetails, powerState, null);
+ } catch (InsufficientCapacityException ice) {
+ String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage());
+ logger.error(errorMsg, ice);
+ throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg);
+ }
+
+ if (userVm == null) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName));
+ }
+ List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
+ try {
+ if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
+ throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
+ }
+ Long minIops = null;
+ if (details.containsKey(MIN_IOPS)) {
+ minIops = Long.parseLong(details.get(MIN_IOPS));
+ }
+ Long maxIops = null;
+ if (details.containsKey(MAX_IOPS)) {
+ maxIops = Long.parseLong(details.get(MAX_IOPS));
+ }
+ DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
+ diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
+ rootDisk.getCapacity(), minIops, maxIops, template, owner, null));
+ long deviceId = 1L;
+ for (UnmanagedInstanceTO.Disk disk : dataDisks) {
+ if (disk.getCapacity() == null || disk.getCapacity() == 0) {
+ throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId()));
+ }
+ DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
+ diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()),
+ disk.getCapacity(), offering.getMinIops(), offering.getMaxIops(),
+ template, owner, deviceId));
+ deviceId++;
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e);
+ cleanupFailedImportVM(userVm);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
+ }
+ try {
+ int nicIndex = 0;
+ for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
+ Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
+ Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
+ importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex == 0, forced);
+ nicIndex++;
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e);
+ cleanupFailedImportVM(userVm);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
+ }
+ if (migrateAllowed) {
+ userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList);
+ }
+ publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template);
+ return userVm;
+
+ } catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet
logger.error("Volume resource allocation error for owner: {}", owner, e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage())));
+ } finally {
+ ReservationHelper.closeAll(reservations);
}
+ // Check NICs and supplied networks
+ Map<String, Network.IpAddresses> nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap);
+ Map<String, Long> allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType());
+ if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) {
+ allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType());
+ }
+
+ if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) {
+ allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword());
+ }
+
+ addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails);
+
+ VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
+ if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) {
+ powerState = VirtualMachine.PowerState.PowerOn;
+ }
+
+ try {
+ userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner,
+ null, caller, true, null, owner.getAccountId(), userId,
+ validatedServiceOffering, null, guestOsId, hostName,
+ cluster.getHypervisorType(), allDetails, powerState, null);
+ } catch (InsufficientCapacityException ice) {
+ String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage());
+ logger.error(errorMsg, ice);
+ throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg);
+ }
+
+ if (userVm == null) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName));
+ }
+ List<Pair<DiskProfile, StoragePool>> diskProfileStoragePoolList = new ArrayList<>();
+ try {
+ if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) {
+ throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId()));
+ }
+ Long minIops = null;
+ if (details.containsKey(MIN_IOPS)) {
+ minIops = Long.parseLong(details.get(MIN_IOPS));
+ }
+ Long maxIops = null;
+ if (details.containsKey(MAX_IOPS)) {
+ maxIops = Long.parseLong(details.get(MAX_IOPS));
+ }
+ DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId());
+ diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()),
+ rootDisk.getCapacity(), minIops, maxIops, template, owner, null));
+ long deviceId = 1L;
+ for (UnmanagedInstanceTO.Disk disk : dataDisks) {
+ if (disk.getCapacity() == null || disk.getCapacity() == 0) {
+ throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId()));
+ }
+ DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId()));
+ diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()),
+ disk.getCapacity(), offering.getMinIops(), offering.getMaxIops(),
+ template, owner, deviceId));
+ deviceId++;
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e);
+ cleanupFailedImportVM(userVm);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
+ }
+ try {
+ int nicIndex = 0;
+ for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) {
+ Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId()));
+ Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId());
+ importNic(nic, userVm, network, ipAddresses, nicIndex, nicIndex == 0, forced);
+ nicIndex++;
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e);
+ cleanupFailedImportVM(userVm);
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage())));
+ }
+ if (migrateAllowed) {
+ userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList);
+ }
+ publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template);
+ return userVm;
}
private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map<String, String> allDetails) {
diff --cc server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
index 7bdc1e7c604,f5e281a9516..a1528297395
--- a/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
+++ b/server/src/test/java/com/cloud/template/TemplateManagerImplTest.java
@@@ -147,71 -152,72 +152,78 @@@ 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
+ VnfTemplateManager vnfTemplateManager;
+ @Inject
+ SnapshotJoinDao snapshotJoinDao;
+ @Inject
+ TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
- @Inject
+ @Mock
+ VnfTemplateManager vnfTemplateManager;
+ @Mock
+ SnapshotJoinDao snapshotJoinDao;
+ @Mock
+ TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
+
+ @Mock
HeuristicRuleHelper heuristicRuleHelperMock;
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
diff --cc server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 2c9d11612c4,7395f222a86..681eecdf052
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@@ -68,68 -132,11 +132,68 @@@ import com.cloud.utils.fsm.NoTransition
import com.cloud.vm.VMInstanceDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
- import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
- import com.cloud.vm.dao.VMInstanceDetailsDao;
+ import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.dao.VMInstanceDao;
+ import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.google.gson.Gson;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
+import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
+import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
+import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
+import org.apache.cloudstack.api.response.BackupResponse;
+import org.apache.cloudstack.backup.dao.BackupDao;
+import org.apache.cloudstack.backup.dao.BackupDetailsDao;
+import org.apache.cloudstack.backup.dao.BackupOfferingDao;
+import org.apache.cloudstack.backup.dao.BackupScheduleDao;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.atLeastOnce;
@RunWith(MockitoJUnitRunner.class)
public class BackupManagerTest {
@@@ -1491,9 -1541,9 +1601,10 @@@
when(backup.getVmId()).thenReturn(vmId);
when(backup.getZoneId()).thenReturn(zoneId);
when(backup.getAccountId()).thenReturn(accountId);
+ when(accountManager.getAccount(accountId)).thenReturn(accountVOMock);
when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
when(backup.getSize()).thenReturn(100L);
+ when(backup.getUuid()).thenReturn("backup-uuid");
overrideBackupFrameworkConfigValue();