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();