This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit da54234585543b292fa57bff11625b8975c8c6c1
Merge: 52e7b41a54e 7cfeab1a6b1
Author: Daan Hoogland <[email protected]>
AuthorDate: Tue Dec 3 16:32:15 2024 +0100

    Merge branch '4.19' into 4.20.merge

 .../cloud/agent/api/to/PortForwardingRuleTO.java   |  13 +
 .../java/com/cloud/network/rules/RulesService.java |   5 +-
 .../org/apache/cloudstack/api/ApiConstants.java    |   2 +
 .../api/command/admin/vm/ImportVmCmd.java          |  12 +-
 .../user/firewall/CreatePortForwardingRuleCmd.java |  22 +-
 .../user/firewall/UpdatePortForwardingRuleCmd.java |  15 +-
 .../loadbalancer/CreateLoadBalancerRuleCmd.java    |   2 +-
 .../com/cloud/agent/api/ConvertInstanceAnswer.java |  11 +
 ...wer.java => ImportConvertedInstanceAnswer.java} |   8 +-
 .../agent/api/ImportConvertedInstanceCommand.java  |  63 +++++
 .../facade/SetPortForwardingRulesConfigItem.java   |   2 +-
 .../virtualnetwork/model/ForwardingRule.java       |   9 +-
 .../cloud/network/dao/FirewallRulesCidrsDao.java   |   2 +
 .../network/dao/FirewallRulesCidrsDaoImpl.java     |  21 +-
 .../cloud/network/dao/FirewallRulesDaoImpl.java    |   3 -
 .../cloud/network/rules/PortForwardingRuleVO.java  |  29 +-
 .../rules/dao/PortForwardingRulesDaoImpl.java      |  44 +++-
 .../src/main/java/com/cloud/storage/VolumeVO.java  |  11 +
 .../resources/META-INF/db/schema-41900to41910.sql  |   3 +
 .../motion/StorageSystemDataMotionStrategy.java    |   2 +
 .../storage/volume/VolumeServiceImpl.java          |   1 +
 .../kvm/resource/LibvirtComputingResource.java     |  31 ++-
 .../kvm/resource/LibvirtDomainXMLParser.java       |  24 +-
 .../hypervisor/kvm/resource/LibvirtVMDef.java      |  24 +-
 .../LibvirtConvertInstanceCommandWrapper.java      |  27 +-
 ...virtImportConvertedInstanceCommandWrapper.java} | 164 +-----------
 .../kvm/storage/KVMStorageProcessor.java           |   5 +-
 .../kvm/storage/LibvirtStorageAdaptor.java         |   6 +-
 .../LibvirtConvertInstanceCommandWrapperTest.java  |  47 ----
 ...ImportConvertedInstanceCommandWrapperTest.java} | 115 +++-----
 ...ernetesClusterResourceModifierActionWorker.java |   2 +-
 plugins/storage/volume/linstor/CHANGELOG.md        |   6 +
 .../kvm/storage/LinstorStorageAdaptor.java         |  59 ++++-
 .../network/firewall/FirewallManagerImpl.java      |  78 ++++--
 .../cloud/network/router/CommandSetupHelper.java   |   2 +
 .../com/cloud/network/rules/RulesManagerImpl.java  |  52 +++-
 .../cloudstack/vm/UnmanagedVMsManagerImpl.java     | 163 ++++++++++--
 .../network/firewall/FirewallManagerTest.java      | 132 +++++++---
 .../cloudstack/vm/UnmanagedVMsManagerImplTest.java | 293 +++++++++++++++++++--
 systemvm/debian/opt/cloud/bin/configure.py         |  10 +-
 systemvm/debian/opt/cloud/bin/cs/CsNetfilter.py    |   2 +-
 .../debian/opt/cloud/bin/cs_forwardingrules.py     |  22 +-
 ui/public/locales/en.json                          |   9 +-
 ui/public/locales/pt_BR.json                       |   3 +-
 ui/src/components/view/InfoCard.vue                |  20 +-
 ui/src/views/auth/Login.vue                        |   2 +-
 ui/src/views/network/LoadBalancing.vue             |   6 +-
 ui/src/views/network/PortForwarding.vue            |  27 +-
 ui/src/views/project/AddAccountOrUserToProject.vue |  95 ++++---
 ui/src/views/tools/ImportUnmanagedInstance.vue     |  59 ++++-
 ui/src/views/tools/ManageInstances.vue             |   3 +-
 51 files changed, 1237 insertions(+), 531 deletions(-)

diff --cc api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 8f78fe5c4b4,b2042c116a7..bf8b79b29d0
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@@ -464,9 -426,9 +465,10 @@@ public class ApiConstants 
      public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
      public static final String SNAPSHOT_TYPE = "snapshottype";
      public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
 -    public static final String SUPPORTS_STORAGE_SNAPSHOT = 
"supportsstoragesnapshot";
+     public static final String SOURCE_CIDR_LIST = "sourcecidrlist";
      public static final String SOURCE_ZONE_ID = "sourcezoneid";
 +    public static final String SSL_VERIFICATION = "sslverification";
 +    public static final String START_ASN = "startasn";
      public static final String START_DATE = "startdate";
      public static final String START_ID = "startid";
      public static final String START_IP = "startip";
diff --cc core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java
index 829888570a6,8092ab9b43f..174348f4f18
--- a/core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java
+++ b/core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java
@@@ -16,25 -16,20 +16,36 @@@
  // under the License.
  package com.cloud.agent.api;
  
 +import org.apache.cloudstack.vm.UnmanagedInstanceTO;
 +
  public class ConvertInstanceAnswer extends Answer {
  
+     private String temporaryConvertUuid;
+ 
      public ConvertInstanceAnswer() {
          super();
      }
 +    private UnmanagedInstanceTO convertedInstance;
 +
 +    public ConvertInstanceAnswer(Command command, boolean success, String 
details) {
 +        super(command, success, details);
 +    }
 +
 +    public ConvertInstanceAnswer(Command command, UnmanagedInstanceTO 
convertedInstance) {
 +        super(command, true, "");
 +        this.convertedInstance = convertedInstance;
 +    }
  
+     public ConvertInstanceAnswer(Command command, String 
temporaryConvertUuid) {
+         super(command, true, "");
+         this.temporaryConvertUuid = temporaryConvertUuid;
+     }
+ 
+     public String getTemporaryConvertUuid() {
+         return temporaryConvertUuid;
+     }
++
 +    public UnmanagedInstanceTO getConvertedInstance() {
 +        return convertedInstance;
 +    }
  }
diff --cc 
engine/schema/src/main/java/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java
index fdd1e0ec43a,4630925ddee..6279289bdfe
--- 
a/engine/schema/src/main/java/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java
+++ 
b/engine/schema/src/main/java/com/cloud/network/dao/FirewallRulesCidrsDaoImpl.java
@@@ -20,6 -20,8 +20,7 @@@ import java.util.ArrayList
  import java.util.List;
  
  
+ import org.apache.commons.collections4.CollectionUtils;
 -import org.apache.log4j.Logger;
  import org.springframework.stereotype.Component;
  
  import com.cloud.utils.db.DB;
@@@ -45,7 -48,7 +46,7 @@@ public class FirewallRulesCidrsDaoImpl 
          sc.setParameters("firewallRuleId", firewallRuleId);
  
          List<FirewallRulesCidrsVO> results = search(sc, null);
--        List<String> cidrs = new ArrayList<String>(results.size());
++        List<String> cidrs = new ArrayList<>(results.size());
          for (FirewallRulesCidrsVO result : results) {
              cidrs.add(result.getCidr());
          }
diff --cc 
engine/schema/src/main/java/com/cloud/network/rules/PortForwardingRuleVO.java
index e1a698881f3,28d12fb24b4..576e2f8172e
--- 
a/engine/schema/src/main/java/com/cloud/network/rules/PortForwardingRuleVO.java
+++ 
b/engine/schema/src/main/java/com/cloud/network/rules/PortForwardingRuleVO.java
@@@ -57,13 -61,9 +61,19 @@@ public class PortForwardingRuleVO exten
          this.virtualMachineId = instanceId;
          this.destinationPortStart = dstPortStart;
          this.destinationPortEnd = dstPortEnd;
+         this.sourceCidrs = sourceCidrs;
      }
  
-     public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip 
dstIp, int dstPort, String protocol, List<String> sourceCidrs, long networkId, 
long accountId,
-             long domainId, long instanceId) {
-         this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, 
protocol.toLowerCase(), networkId, accountId, domainId, instanceId);
++    public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, 
int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, 
long networkId,
++                                long accountId, long domainId, long 
instanceId) {
++        this(xId, srcIpId, srcPortStart, srcPortEnd, dstIp, dstPortStart, 
dstPortEnd, protocol.toLowerCase(), networkId, accountId, domainId, instanceId, 
null);
++    }
++
++    public PortForwardingRuleVO(String xId, long srcIpId, int srcPort, Ip 
dstIp, int dstPort, String protocol, long networkId, long accountId,
++                                long domainId, long instanceId) {
++        this(xId, srcIpId, srcPort, srcPort, dstIp, dstPort, dstPort, 
protocol.toLowerCase(), networkId, accountId, domainId, instanceId, null);
 +    }
 +
      @Override
      public Ip getDestinationIpAddress() {
          return destinationIpAddress;
diff --cc 
engine/schema/src/main/java/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
index 3a404b3f2df,1ddecaa8a17..1b3df06e1a2
--- 
a/engine/schema/src/main/java/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
+++ 
b/engine/schema/src/main/java/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
@@@ -31,6 -33,6 +31,9 @@@ import com.cloud.utils.db.GenericDaoBas
  import com.cloud.utils.db.SearchBuilder;
  import com.cloud.utils.db.SearchCriteria;
  import com.cloud.utils.db.SearchCriteria.Op;
++import com.cloud.utils.db.Transaction;
++import com.cloud.utils.db.TransactionCallback;
++import com.cloud.utils.db.TransactionLegacy;
  
  @Component
  public class PortForwardingRulesDaoImpl extends 
GenericDaoBase<PortForwardingRuleVO, Long> implements PortForwardingRulesDao {
@@@ -173,14 -175,42 +176,53 @@@
      }
  
      @Override
 +    public int expungeByVmList(List<Long> vmIds, Long batchSize) {
 +        if (CollectionUtils.isEmpty(vmIds)) {
 +            return 0;
 +        }
 +        SearchBuilder<PortForwardingRuleVO> sb = createSearchBuilder();
 +        sb.and("vmIds", sb.entity().getVirtualMachineId(), 
SearchCriteria.Op.IN);
 +        SearchCriteria<PortForwardingRuleVO> sc = sb.create();
 +        sc.setParameters("vmIds", vmIds.toArray());
 +        return batchExpunge(sc, batchSize);
 +    }
++
+     public PortForwardingRuleVO persist(PortForwardingRuleVO 
portForwardingRule) {
+         return 
Transaction.execute((TransactionCallback<PortForwardingRuleVO>) 
transactionStatus -> {
+             PortForwardingRuleVO dbPfRule = super.persist(portForwardingRule);
+ 
+             portForwardingRulesCidrsDao.persist(portForwardingRule.getId(), 
portForwardingRule.getSourceCidrList());
+             List<String> cidrList = 
portForwardingRulesCidrsDao.getSourceCidrs(portForwardingRule.getId());
+             portForwardingRule.setSourceCidrList(cidrList);
+ 
+             return dbPfRule;
+         });
+ 
+     }
+ 
+     @Override
+     public boolean update(Long id, PortForwardingRuleVO entity) {
+         TransactionLegacy txn = TransactionLegacy.currentTxn();
+         txn.start();
+ 
+         boolean success = super.update(id, entity);
+         if (!success) {
+             return false;
+         }
+ 
+         portForwardingRulesCidrsDao.updateSourceCidrsForRule(entity.getId(), 
entity.getSourceCidrList());
+         txn.commit();
+ 
+         return true;
+     }
+ 
+     @Override
+     public PortForwardingRuleVO findById(Long id) {
+         PortForwardingRuleVO rule = super.findById(id);
+ 
+         List<String> sourceCidrList = 
portForwardingRulesCidrsDao.getSourceCidrs(id);
+         rule.setSourceCidrList(sourceCidrList);
+ 
+         return rule;
+     }
  }
diff --cc engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
index c105acf40b8,5ccbf746b7e..3e6999fad36
--- a/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
+++ b/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
@@@ -682,12 -681,11 +685,20 @@@ public class VolumeVO implements Volum
  
      public void setEncryptFormat(String encryptFormat) { this.encryptFormat = 
encryptFormat; }
  
 +    @Override
 +    public boolean isDeleteProtection() {
 +        return deleteProtection;
 +    }
 +
 +    public void setDeleteProtection(boolean deleteProtection) {
 +        this.deleteProtection = deleteProtection;
 +    }
++
+     public long getLastId() {
+         return lastId;
+     }
+ 
+     public void setLastId(long lastId) {
+         this.lastId = lastId;
+     }
  }
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index 0f11c12f101,ec940942082..a67294ecadb
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@@ -914,14 -853,14 +914,14 @@@ public class LibvirtVMDef 
              _diskCacheMode = DiskCacheMode.NONE;
          }
  
-         public void defISODisk(String volPath, Integer devId) {
-             defISODisk(volPath, devId, null);
+         public void defISODisk(String volPath, Integer devId, DiskType 
diskType) {
+             defISODisk(volPath, devId, null, diskType);
          }
  
-         public void defISODisk(String volPath, Integer devId, String 
diskLabel) {
+         public void defISODisk(String volPath, Integer devId, String 
diskLabel, DiskType diskType) {
              if (devId == null && StringUtils.isBlank(diskLabel)) {
 -                s_logger.debug(String.format("No ID or label informed for 
volume [%s].", volPath));
 +                LOGGER.debug(String.format("No ID or label informed for 
volume [%s].", volPath));
-                 defISODisk(volPath);
+                 defISODisk(volPath, diskType);
                  return;
              }
  
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java
index cc955e86d8a,e6654b1ffc5..3ba1bc11975
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java
@@@ -134,39 -119,29 +135,29 @@@ public class LibvirtConvertInstanceComm
              boolean result = performInstanceConversion(sourceOVFDirPath, 
temporaryConvertPath, temporaryConvertUuid,
                      timeout, verboseModeEnabled);
              if (!result) {
-                 String err = String.format("The virt-v2v conversion for the 
OVF %s failed. " +
-                                 "Please check the agent logs for the virt-v2v 
output", ovfTemplateDirOnConversionLocation);
+                 String err = String.format(
+                         "The virt-v2v conversion for the OVF %s failed. 
Please check the agent logs " +
+                                 "for the virt-v2v output. Please try on a 
different kvm host which " +
+                                 "has a different virt-v2v version.",
+                         ovfTemplateDirOnConversionLocation);
 -                s_logger.error(err);
 -                return new Answer(cmd, false, err);
 +                logger.error(err);
 +                return new ConvertInstanceAnswer(cmd, false, err);
              }
-             String convertedBasePath = String.format("%s/%s", 
temporaryConvertPath, temporaryConvertUuid);
-             LibvirtDomainXMLParser xmlParser = 
parseMigratedVMXmlDomain(convertedBasePath);
- 
-             List<KVMPhysicalDisk> temporaryDisks = xmlParser == null ?
-                     
getTemporaryDisksWithPrefixFromTemporaryPool(temporaryStoragePool, 
temporaryConvertPath, temporaryConvertUuid) :
-                     getTemporaryDisksFromParsedXml(temporaryStoragePool, 
xmlParser, convertedBasePath);
- 
-             List<KVMPhysicalDisk> destinationDisks = 
moveTemporaryDisksToDestination(temporaryDisks,
-                     destinationStoragePools, storagePoolMgr);
- 
-             cleanupDisksAndDomainFromTemporaryLocation(temporaryDisks, 
temporaryStoragePool, temporaryConvertUuid);
- 
-             UnmanagedInstanceTO convertedInstanceTO = 
getConvertedUnmanagedInstance(temporaryConvertUuid,
-                     destinationDisks, xmlParser);
-             return new ConvertInstanceAnswer(cmd, convertedInstanceTO);
+             return new ConvertInstanceAnswer(cmd, temporaryConvertUuid);
          } catch (Exception e) {
              String error = String.format("Error converting instance %s from 
%s, due to: %s",
                      sourceInstanceName, sourceHypervisorType, e.getMessage());
 -            s_logger.error(error, e);
 +            logger.error(error, e);
+             cleanupSecondaryStorage = true;
 -            return new Answer(cmd, false, error);
 +            return new ConvertInstanceAnswer(cmd, false, error);
          } finally {
              if (ovfExported && 
StringUtils.isNotBlank(ovfTemplateDirOnConversionLocation)) {
                  String sourceOVFDir = String.format("%s/%s", 
temporaryConvertPath, ovfTemplateDirOnConversionLocation);
 -                s_logger.debug("Cleaning up exported OVA at dir " + 
sourceOVFDir);
 +                logger.debug("Cleaning up exported OVA at dir " + 
sourceOVFDir);
                  FileUtil.deletePath(sourceOVFDir);
              }
-             if (conversionTemporaryLocation instanceof NfsTO) {
+             if (cleanupSecondaryStorage && conversionTemporaryLocation 
instanceof NfsTO) {
 -                s_logger.debug("Cleaning up secondary storage temporary 
location");
 +                logger.debug("Cleaning up secondary storage temporary 
location");
                  
storagePoolMgr.deleteStoragePool(temporaryStoragePool.getType(), 
temporaryStoragePool.getUuid());
              }
          }
diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapper.java
index cc955e86d8a,3af41253b92..0eec15cf733
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapper.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapper.java
@@@ -35,10 -34,11 +34,10 @@@ import org.apache.cloudstack.vm.Unmanag
  import org.apache.commons.collections.CollectionUtils;
  import org.apache.commons.io.IOUtils;
  import org.apache.commons.lang3.StringUtils;
 -import org.apache.log4j.Logger;
  
  import com.cloud.agent.api.Answer;
- import com.cloud.agent.api.ConvertInstanceAnswer;
- import com.cloud.agent.api.ConvertInstanceCommand;
+ import com.cloud.agent.api.ImportConvertedInstanceAnswer;
+ import com.cloud.agent.api.ImportConvertedInstanceCommand;
  import com.cloud.agent.api.to.DataStoreTO;
  import com.cloud.agent.api.to.NfsTO;
  import com.cloud.agent.api.to.RemoteInstanceTO;
@@@ -55,17 -55,15 +54,13 @@@ import com.cloud.storage.Storage
  import com.cloud.utils.FileUtil;
  import com.cloud.utils.Pair;
  import com.cloud.utils.exception.CloudRuntimeException;
- import com.cloud.utils.script.OutputInterpreter;
  import com.cloud.utils.script.Script;
  
- @ResourceWrapper(handles =  ConvertInstanceCommand.class)
- public class LibvirtConvertInstanceCommandWrapper extends 
CommandWrapper<ConvertInstanceCommand, Answer, LibvirtComputingResource> {
- 
-     private static final List<Hypervisor.HypervisorType> 
supportedInstanceConvertSourceHypervisors =
-             List.of(Hypervisor.HypervisorType.VMware);
+ @ResourceWrapper(handles =  ImportConvertedInstanceCommand.class)
+ public class LibvirtImportConvertedInstanceCommandWrapper extends 
CommandWrapper<ImportConvertedInstanceCommand, Answer, 
LibvirtComputingResource> {
  
 -    private static final Logger s_logger = 
Logger.getLogger(LibvirtImportConvertedInstanceCommandWrapper.class);
 -
      @Override
-     public Answer execute(ConvertInstanceCommand cmd, 
LibvirtComputingResource serverResource) {
+     public Answer execute(ImportConvertedInstanceCommand cmd, 
LibvirtComputingResource serverResource) {
          RemoteInstanceTO sourceInstance = cmd.getSourceInstance();
          Hypervisor.HypervisorType sourceHypervisorType = 
sourceInstance.getHypervisorType();
          String sourceInstanceName = sourceInstance.getInstanceName();
@@@ -157,16 -94,11 +91,11 @@@
          } catch (Exception e) {
              String error = String.format("Error converting instance %s from 
%s, due to: %s",
                      sourceInstanceName, sourceHypervisorType, e.getMessage());
 -            s_logger.error(error, e);
 +            logger.error(error, e);
-             return new ConvertInstanceAnswer(cmd, false, error);
+             return new ImportConvertedInstanceAnswer(cmd, false, error);
          } finally {
-             if (ovfExported && 
StringUtils.isNotBlank(ovfTemplateDirOnConversionLocation)) {
-                 String sourceOVFDir = String.format("%s/%s", 
temporaryConvertPath, ovfTemplateDirOnConversionLocation);
-                 logger.debug("Cleaning up exported OVA at dir " + 
sourceOVFDir);
-                 FileUtil.deletePath(sourceOVFDir);
-             }
              if (conversionTemporaryLocation instanceof NfsTO) {
 -                s_logger.debug("Cleaning up secondary storage temporary 
location");
 +                logger.debug("Cleaning up secondary storage temporary 
location");
                  
storagePoolMgr.deleteStoragePool(temporaryStoragePool.getType(), 
temporaryStoragePool.getUuid());
              }
          }
diff --cc 
plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapperTest.java
index f0e94e59485,55789a837b2..343a15b367d
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapperTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtImportConvertedInstanceCommandWrapperTest.java
@@@ -168,6 -149,7 +149,7 @@@ public class LibvirtImportConvertedInst
      @Test
      public void testMoveTemporaryDisksToDestination() {
          KVMPhysicalDisk sourceDisk = Mockito.mock(KVMPhysicalDisk.class);
 -        Mockito.when(sourceDisk.getPool()).thenReturn(temporaryPool);
++        
Mockito.lenient().when(sourceDisk.getPool()).thenReturn(temporaryPool);
          List<KVMPhysicalDisk> disks = List.of(sourceDisk);
          String destinationPoolUuid = UUID.randomUUID().toString();
          List<String> destinationPools = List.of(destinationPoolUuid);
diff --cc 
plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
index 4148dcfbf4c,1f71a54a4f3..8d99af0dd20
--- 
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
+++ 
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
@@@ -57,8 -58,11 +59,10 @@@ import com.linbit.linstor.api.model.Sto
  import com.linbit.linstor.api.model.Volume;
  import com.linbit.linstor.api.model.VolumeDefinition;
  
+ import java.io.File;
+ 
 -@StorageAdaptorInfo(storagePoolType=Storage.StoragePoolType.Linstor)
  public class LinstorStorageAdaptor implements StorageAdaptor {
 -    private static final Logger s_logger = 
Logger.getLogger(LinstorStorageAdaptor.class);
 +    protected Logger logger = LogManager.getLogger(getClass());
      private static final Map<String, KVMStoragePool> 
MapStorageUuidToStoragePool = new HashMap<>();
      private final String localNodeName;
  
@@@ -566,15 -567,9 +570,9 @@@
              name, QemuImg.PhysicalDiskFormat.RAW, provisioningType, 
disk.getVirtualSize(), null);
  
          final DevelopersApi api = getLinstorAPI(destPools);
-         final String rscName = LinstorUtil.RSC_PREFIX + name;
-         try {
-             LinstorUtil.applyAuxProps(api, rscName, disk.getDispName(), 
disk.getVmName());
-         } catch (ApiException apiExc) {
-             logger.error("Error setting aux properties for {}", rscName);
-             logLinstorAnswers(apiExc.getApiCallRcList());
-         }
+         applyAuxProps(api, name, disk.getDispName(), disk.getVmName());
  
 -        s_logger.debug(String.format("Linstor.copyPhysicalDisk: dstPath: %s", 
dstDisk.getPath()));
 +        logger.debug("Linstor.copyPhysicalDisk: dstPath: {}", 
dstDisk.getPath());
          final QemuImgFile destFile = new QemuImgFile(dstDisk.getPath());
          destFile.setFormat(dstDisk.getFormat());
          destFile.setSize(disk.getVirtualSize());
@@@ -623,13 -618,57 +621,58 @@@
          return null;
      }
  
+     private void fileExistsOrThrow(String templateFilePath) {
+         File sourceFile = new File(templateFilePath);
+         if (!sourceFile.exists()) {
+             throw new CloudRuntimeException("Direct download template file " 
+ sourceFile +
+                     " does not exist on this host");
+         }
+     }
+ 
+     private String getFinalDirectDownloadPath(String templateFilePath, 
KVMStoragePool destPool) {
+         String finalSourcePath = templateFilePath;
+         if (LibvirtStorageAdaptor.isTemplateExtractable(templateFilePath)) {
+             finalSourcePath = templateFilePath.substring(0, 
templateFilePath.lastIndexOf('.'));
+             LibvirtStorageAdaptor.extractDownloadedTemplate(templateFilePath, 
destPool, finalSourcePath);
+         }
+         return finalSourcePath;
+     }
+ 
+     private void applyAuxProps(DevelopersApi api, String csPath, String 
csName, String csVMName) {
+         final String rscName = getLinstorRscName(csPath);
+         try {
+             LinstorUtil.applyAuxProps(api, rscName, csName, csVMName);
+         } catch (ApiException apiExc) {
 -            s_logger.error(String.format("Error setting aux properties for 
%s", rscName));
++            logger.error(String.format("Error setting aux properties for %s", 
rscName));
+             logLinstorAnswers(apiExc.getApiCallRcList());
+         }
+     }
+ 
      @Override
      public KVMPhysicalDisk createTemplateFromDirectDownloadFile(String 
templateFilePath, String destTemplatePath,
                                                                  
KVMStoragePool destPool, Storage.ImageFormat format,
                                                                  int timeout)
      {
 -        s_logger.debug(String.format("Linstor: 
createTemplateFromDirectDownloadFile: %s/%s", templateFilePath, format));
 +        logger.debug("Linstor: createTemplateFromDirectDownloadFile");
-         return null;
++
+         fileExistsOrThrow(templateFilePath);
+         String name = UUID.randomUUID().toString();
+ 
+         String finalSourcePath = getFinalDirectDownloadPath(templateFilePath, 
destPool);
+ 
+         File finalSourceFile = new File(finalSourcePath);
+         final KVMPhysicalDisk dstDisk = destPool.createPhysicalDisk(
+                 name, QemuImg.PhysicalDiskFormat.RAW, 
Storage.ProvisioningType.THIN, finalSourceFile.length(), null);
+ 
+         final DevelopersApi api = getLinstorAPI(destPool);
+         applyAuxProps(api, name, finalSourceFile.getName(), null);
+ 
+         Script.runSimpleBashScript(
+                 String.format("dd if=\"%s\" of=\"%s\" bs=64k 
conv=nocreat,sparse oflag=direct",
+                         finalSourcePath, dstDisk.getPath()));
+ 
+         Script.runSimpleBashScript("rm " + finalSourcePath);
+         return dstDisk;
      }
  
      public long getCapacity(LinstorStoragePool pool) {
diff --cc 
server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java
index 7194b86e3e1,4d4a8b30a56..6b98fc00c59
--- a/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java
@@@ -30,17 -28,14 +30,19 @@@ import java.util.Set
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
++import org.apache.commons.lang3.ObjectUtils;
++import org.springframework.stereotype.Component;
++
 +import com.cloud.dc.DataCenter;
 +import com.cloud.network.dao.NsxProviderDao;
 +import com.cloud.network.element.NsxProviderVO;
 +import com.cloud.utils.db.EntityManager;
  import org.apache.cloudstack.api.command.user.firewall.IListFirewallRulesCmd;
  import org.apache.cloudstack.api.command.user.ipv6.ListIpv6FirewallRulesCmd;
  import org.apache.cloudstack.context.CallContext;
  import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
  import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 -import org.apache.commons.lang3.ObjectUtils;
 -import org.apache.log4j.Logger;
 -import org.springframework.stereotype.Component;
 +import org.apache.cloudstack.network.RoutedIpv4Manager;
- import org.springframework.stereotype.Component;
  
  import com.cloud.configuration.Config;
  import com.cloud.domain.dao.DomainDao;
@@@ -489,6 -482,45 +494,45 @@@ public class FirewallManagerImpl extend
          }
      }
  
+     protected boolean checkIfRulesHaveConflictingPortRanges(FirewallRule 
newRule, FirewallRule rule, boolean oneOfRulesIsFirewall, boolean 
bothRulesFirewall, boolean bothRulesPortForwarding, boolean duplicatedCidrs) {
+         String rulesAsString = String.format("[%s] and [%s]", rule, newRule);
+ 
+         if (oneOfRulesIsFirewall) {
 -            s_logger.debug(String.format("Only one of the rules (%s) is 
firewall; therefore, their port ranges will not conflict.",
++            logger.debug(String.format("Only one of the rules (%s) is 
firewall; therefore, their port ranges will not conflict.",
+                     rulesAsString));
+             return false;
+         }
+ 
+         if ((bothRulesFirewall || bothRulesPortForwarding) && 
!duplicatedCidrs) {
 -            s_logger.debug(String.format("Both rules (%s) are firewall/port 
forwarding, but they do not have duplicated CIDRs; therefore, their port ranges 
will not conflict.",
++            logger.debug(String.format("Both rules (%s) are firewall/port 
forwarding, but they do not have duplicated CIDRs; therefore, their port ranges 
will not conflict.",
+                     rulesAsString));
+             return false;
+         }
+ 
+         if (rule.getSourcePortStart() <= newRule.getSourcePortStart() && 
rule.getSourcePortEnd() >= newRule.getSourcePortStart()) {
 -            s_logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
++            logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
+             return true;
+         }
+ 
+         if (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && 
rule.getSourcePortEnd() >= newRule.getSourcePortEnd()) {
 -            s_logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
++            logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
+             return true;
+         }
+ 
+         if (newRule.getSourcePortStart() <= rule.getSourcePortStart() && 
newRule.getSourcePortEnd() >= rule.getSourcePortStart()) {
 -            s_logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
++            logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
+             return true;
+         }
+ 
+         if (newRule.getSourcePortStart() <= rule.getSourcePortEnd() && 
newRule.getSourcePortEnd() >= rule.getSourcePortEnd()) {
 -            s_logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
++            logger.debug(String.format("Rules (%s) have conflicting port 
ranges.", rulesAsString));
+             return true;
+         }
+ 
 -        s_logger.debug(String.format("Rules (%s) do not have conflicting port 
ranges.", rulesAsString));
++        logger.debug(String.format("Rules (%s) do not have conflicting port 
ranges.", rulesAsString));
+         return false;
+     }
+ 
      @Override
      public void validateFirewallRule(Account caller, IPAddressVO ipAddress, 
Integer portStart, Integer portEnd, String proto, Purpose purpose, 
FirewallRuleType type,
          Long networkId, FirewallRule.TrafficType trafficType) {
diff --cc server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java
index 55f7609f9c6,1b7177ec416..404c1c88f5a
--- a/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java
@@@ -33,8 -33,10 +33,9 @@@ import com.cloud.vm.VirtualMachineProfi
  import com.cloud.vm.VirtualMachineProfileImpl;
  import org.apache.cloudstack.acl.SecurityChecker;
  import 
org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd;
+ import 
org.apache.cloudstack.api.command.user.firewall.UpdatePortForwardingRuleCmd;
  import org.apache.cloudstack.context.CallContext;
  import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 -import org.apache.log4j.Logger;
  
  import com.cloud.configuration.ConfigurationManager;
  import com.cloud.domain.dao.DomainDao;
@@@ -102,8 -104,10 +103,9 @@@ import com.cloud.vm.dao.NicSecondaryIpD
  import com.cloud.vm.dao.NicSecondaryIpVO;
  import com.cloud.vm.dao.UserVmDao;
  import com.cloud.vm.dao.VMInstanceDao;
+ import org.apache.commons.collections.CollectionUtils;
  
  public class RulesManagerImpl extends ManagerBase implements RulesManager, 
RulesService {
 -    private static final Logger s_logger = 
Logger.getLogger(RulesManagerImpl.class);
  
      @Inject
      IpAddressManager _ipAddrMgr;
diff --cc 
server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
index fc982668e73,67139120fa0..bd3a5655e91
--- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java
@@@ -1630,12 -1604,14 +1637,14 @@@ public class UnmanagedVMsManagerImpl im
          DataStoreTO temporaryConvertLocation = null;
          String ovfTemplateOnConvertLocation = null;
          try {
-             HostVO convertHost = 
selectInstanceConversionKVMHostInCluster(destinationCluster, 
convertInstanceHostId);
+             HostVO convertHost = 
selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId);
+             HostVO importHost = 
selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId);
              CheckConvertInstanceAnswer conversionSupportAnswer = 
checkConversionSupportOnHost(convertHost, sourceVMName, false);
 -            LOGGER.debug(String.format("The host %s (%s) is selected to 
execute the conversion of the instance %s" +
 +            logger.debug(String.format("The host %s (%s) is selected to 
execute the conversion of the instance %s" +
                      " from VMware to KVM ", convertHost.getId(), 
convertHost.getName(), sourceVMName));
  
-             temporaryConvertLocation = 
selectInstanceConversionTemporaryLocation(destinationCluster, 
convertStoragePoolId);
+             temporaryConvertLocation = 
selectInstanceConversionTemporaryLocation(
+                     destinationCluster, convertHost, convertStoragePoolId);
              List<StoragePoolVO> convertStoragePools = 
findInstanceConversionStoragePoolsInCluster(destinationCluster);
              long importStartTime = System.currentTimeMillis();
              Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = 
getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, 
clusterName, sourceHostName, sourceVMName);
@@@ -1814,20 -1792,77 +1825,77 @@@
          return params;
      }
  
-     private HostVO selectInstanceConversionKVMHostInCluster(Cluster 
destinationCluster, Long convertInstanceHostId) {
+     HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, 
Long importInstanceHostId) {
+         if (importInstanceHostId != null) {
+             String err = null;
+             HostVO selectedHost = hostDao.findById(importInstanceHostId);
+             if (selectedHost == null) {
+                 err = String.format("Cannot find host with ID %s to import 
the instance",
+                         importInstanceHostId);
+             } else if (selectedHost.getResourceState() != 
ResourceState.Enabled) {
+                 err = String.format(
+                         "Cannot import the converted instance on the host %s 
as it is not in Enabled state",
+                         selectedHost.getName());
+             } else if (selectedHost.getStatus() != Status.Up) {
+                 err = String.format(
+                         "Cannot import the converted instance on the host %s 
as it is not running",
+                         selectedHost.getName());
+             } else if (selectedHost.getType() != Host.Type.Routing) {
+                 err = String.format(
+                         "Cannot import the converted instance on the host %s 
as it is not a routing host",
+                         selectedHost.getName());
+             } else if (destinationCluster.getId() != 
selectedHost.getClusterId()) {
+                 err = String.format(
+                         "Cannot import the converted instance on the host %s 
as it is not in the same cluster as the destination cluster",
+                         selectedHost.getName());
+             }
+ 
+             if (err != null) {
 -                LOGGER.error(err);
++                logger.error(err);
+                 throw new CloudRuntimeException(err);
+             }
+             return selectedHost;
+         }
+ 
+         List<HostVO> hosts = 
hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), 
destinationCluster.getHypervisorType());
+         if (CollectionUtils.isNotEmpty(hosts)) {
+             return hosts.get(new Random().nextInt(hosts.size()));
+         }
+ 
+         String err = String.format(
+                 "Could not find any suitable %s host in cluster %s to import 
the converted instance",
+                 destinationCluster.getHypervisorType(), 
destinationCluster.getName());
 -        LOGGER.error(err);
++        logger.error(err);
+         throw new CloudRuntimeException(err);
+     }
+ 
+     HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, 
Long convertInstanceHostId) {
          if (convertInstanceHostId != null) {
              HostVO selectedHost = hostDao.findById(convertInstanceHostId);
+             String err = null;
              if (selectedHost == null) {
-                 String msg = String.format("Cannot find host with ID %s", 
convertInstanceHostId);
-                 logger.error(msg);
-                 throw new CloudRuntimeException(msg);
-             }
-             if (selectedHost.getResourceState() != ResourceState.Enabled ||
-                     selectedHost.getStatus() != Status.Up || 
selectedHost.getType() != Host.Type.Routing ||
-                     selectedHost.getClusterId() != 
destinationCluster.getId()) {
-                 String msg = String.format("Cannot perform the conversion on 
the host %s as it is not a running and Enabled host", selectedHost.getName());
-                 logger.error(msg);
-                 throw new CloudRuntimeException(msg);
+                 err = String.format("Cannot find host with ID %s for 
conversion",
+                         convertInstanceHostId);
+             } else if (!List.of(ResourceState.Enabled, 
ResourceState.Disabled).contains(selectedHost.getResourceState())) {
+                 err = String.format(
+                         "Cannot perform the conversion on the host %s as the 
host is in %s state",
+                         selectedHost.getName(), 
selectedHost.getResourceState());
+             } else if (selectedHost.getStatus() != Status.Up) {
+                 err = String.format(
+                         "Cannot perform the conversion on the host %s as it 
is not running",
+                         selectedHost.getName());
+             } else if (selectedHost.getType() != Host.Type.Routing) {
+                 err = String.format(
+                         "Cannot perform the conversion on the host %s as it 
is not a routing host",
+                         selectedHost.getName());
+             } else if (destinationCluster.getDataCenterId() != 
selectedHost.getDataCenterId()) {
+                 err = String.format(
+                         "Cannot perform the conversion on the host %s as it 
is not in the same zone as the destination cluster",
+                         selectedHost.getName());
+             }
+             if (err != null) {
 -                LOGGER.error(err);
++                logger.error(err);
+                 throw new CloudRuntimeException(err);
              }
              return selectedHost;
          }
@@@ -1875,10 -1911,13 +1944,13 @@@
          return checkConvertInstanceAnswer;
      }
  
-     private UnmanagedInstanceTO 
convertVmwareInstanceToKVMWithOVFOnConvertLocation(String sourceVM, 
UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
-                                                                               
     List<StoragePoolVO> convertStoragePools, DataStoreTO 
temporaryConvertLocation,
-                                                                               
     String ovfTemplateDirConvertLocation) {
-         logger.debug(String.format("Delegating the conversion of instance %s 
from VMware to KVM to the host %s (%s) using OVF %s on conversion datastore",
+     private UnmanagedInstanceTO 
convertVmwareInstanceToKVMWithOVFOnConvertLocation(
+             String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
+             HostVO convertHost, HostVO importHost,
+             List<StoragePoolVO> convertStoragePools, DataStoreTO 
temporaryConvertLocation,
+             String ovfTemplateDirConvertLocation
+     ) {
 -        LOGGER.debug(String.format("Delegating the conversion of instance %s 
from VMware to KVM to the host %s (%s) using OVF %s on conversion datastore",
++            logger.debug(String.format("Delegating the conversion of instance 
%s from VMware to KVM to the host %s (%s) using OVF %s on conversion datastore",
                  sourceVM, convertHost.getId(), convertHost.getName(), 
ovfTemplateDirConvertLocation));
  
          RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM);
@@@ -1888,29 -1927,17 +1960,32 @@@
          int timeoutSeconds = 
UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60;
          cmd.setWait(timeoutSeconds);
  
 -        return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM,
 -                remoteInstanceTO, destinationStoragePools, 
temporaryConvertLocation);
 +        Answer convertAnswer;
 +        try {
 +             convertAnswer = agentManager.send(convertHost.getId(), cmd);
 +        } catch (AgentUnavailableException | OperationTimedoutException e) {
 +            String err = String.format("Could not send the convert instance 
command to host %s (%s) due to: %s",
 +                    convertHost.getId(), convertHost.getName(), 
e.getMessage());
 +            logger.error(err, e);
 +            throw new CloudRuntimeException(err);
 +        }
 +
 +        if (!convertAnswer.getResult()) {
 +            String err = String.format("The convert process failed for 
instance %s from VMware to KVM on host %s: %s",
 +                    sourceVM, convertHost.getName(), 
convertAnswer.getDetails());
 +            logger.error(err);
 +            throw new CloudRuntimeException(err);
 +        }
 +        return ((ConvertInstanceAnswer) convertAnswer).getConvertedInstance();
      }
  
-     private UnmanagedInstanceTO 
convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(String sourceVM, 
UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost,
-                                                                               
               List<StoragePoolVO> convertStoragePools, DataStoreTO 
temporaryConvertLocation,
-                                                                               
               String vcenterHost, String vcenterUsername, String 
vcenterPassword, String datacenterName) {
+     private UnmanagedInstanceTO 
convertVmwareInstanceToKVMAfterExportingOVFToConvertLocation(
+             String sourceVM, UnmanagedInstanceTO sourceVMwareInstance,
+             HostVO convertHost, HostVO importHost, List<StoragePoolVO> 
convertStoragePools,
+             DataStoreTO temporaryConvertLocation, String vcenterHost,
+             String vcenterUsername, String vcenterPassword, String 
datacenterName
+     ) {
 -        LOGGER.debug(String.format("Delegating the conversion of instance %s 
from VMware to KVM to the host %s (%s) after OVF export through ovftool",
 +        logger.debug(String.format("Delegating the conversion of instance %s 
from VMware to KVM to the host %s (%s) after OVF export through ovftool",
                  sourceVM, convertHost.getId(), convertHost.getName()));
  
          RemoteInstanceTO remoteInstanceTO = new 
RemoteInstanceTO(sourceVMwareInstance.getName(), vcenterHost, vcenterUsername, 
vcenterPassword, datacenterName);
@@@ -1939,10 -1975,33 +2023,33 @@@
          if (!convertAnswer.getResult()) {
              String err = String.format("The convert process failed for 
instance %s from VMware to KVM on host %s: %s",
                      sourceVM, convertHost.getName(), 
convertAnswer.getDetails());
 -            LOGGER.error(err);
 +            logger.error(err);
              throw new CloudRuntimeException(err);
          }
-         return ((ConvertInstanceAnswer) convertAnswer).getConvertedInstance();
+ 
+         Answer importAnswer;
+         try {
+             ImportConvertedInstanceCommand importCmd = new 
ImportConvertedInstanceCommand(
+                     remoteInstanceTO, destinationStoragePools, 
temporaryConvertLocation,
+                     
((ConvertInstanceAnswer)convertAnswer).getTemporaryConvertUuid());
+             importAnswer = agentManager.send(importHost.getId(), importCmd);
+         } catch (AgentUnavailableException | OperationTimedoutException e) {
+             String err = String.format(
+                     "Could not send the import converted instance command to 
host %d (%s) due to: %s",
+                     importHost.getId(), importHost.getName(), e.getMessage());
 -            LOGGER.error(err, e);
++            logger.error(err, e);
+             throw new CloudRuntimeException(err);
+         }
+ 
+         if (!importAnswer.getResult()) {
+             String err = String.format(
+                     "The import process failed for instance %s from VMware to 
KVM on host %s: %s",
+                     sourceVM, importHost.getName(), 
importAnswer.getDetails());
 -            LOGGER.error(err);
++            logger.error(err);
+             throw new CloudRuntimeException(err);
+         }
+ 
+         return ((ImportConvertedInstanceAnswer) 
importAnswer).getConvertedInstance();
      }
  
      private List<StoragePoolVO> 
findInstanceConversionStoragePoolsInCluster(Cluster destinationCluster) {
diff --cc 
server/src/test/java/com/cloud/network/firewall/FirewallManagerTest.java
index 04ef756a3c8,e8f01576e4c..f94fd0c0c3c
--- a/server/src/test/java/com/cloud/network/firewall/FirewallManagerTest.java
+++ b/server/src/test/java/com/cloud/network/firewall/FirewallManagerTest.java
@@@ -35,11 -34,9 +34,9 @@@ import com.cloud.network.vpc.VpcManager
  import com.cloud.user.AccountManager;
  import com.cloud.user.DomainManager;
  import com.cloud.utils.component.ComponentContext;
- import junit.framework.Assert;
  import 
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
- import org.apache.logging.log4j.Logger;
- import org.apache.logging.log4j.LogManager;
 -import org.apache.log4j.Logger;
 +import org.junit.After;
+ import org.junit.Assert;
  import org.junit.Before;
  import org.junit.Ignore;
  import org.junit.Test;
@@@ -62,40 -60,39 +60,8 @@@ import static org.mockito.Mockito.when
  
  @RunWith(MockitoJUnitRunner.class)
  public class FirewallManagerTest {
-     private Logger logger = LogManager.getLogger(FirewallManagerTest.class);
 -    private static final Logger s_logger = 
Logger.getLogger(FirewallManagerTest.class);
 -
 -
 -    @Ignore("Requires database to be set up")
 -    @Test
 -    public void testInjected() {
 -
 -//        FirewallManagerImpl firewallMgr = 
(FirewallManagerImpl)ComponentLocator.getCurrentLocator().getManager(FirewallManager.class);
 -//        
Assert.assertTrue(firewallMgr._firewallElements.enumeration().hasMoreElements());
 -//        
Assert.assertTrue(firewallMgr._pfElements.enumeration().hasMoreElements());
 -//        
Assert.assertTrue(firewallMgr._staticNatElements.enumeration().hasMoreElements());
 -//        
Assert.assertTrue(firewallMgr._networkAclElements.enumeration().hasMoreElements());
 -//        Assert.assertNotNull(firewallMgr._networkModel);
 -//
 -//        
Assert.assertNotNull(firewallMgr._firewallElements.get("VirtualRouter"));
 -//        
Assert.assertNotNull(firewallMgr._firewallElements.get("VpcVirtualRouter"));
 -//        Assert.assertNotNull(firewallMgr._pfElements.get("VirtualRouter"));
 -//        
Assert.assertNotNull(firewallMgr._pfElements.get("VpcVirtualRouter"));
 -//        
Assert.assertNotNull(firewallMgr._staticNatElements.get("VirtualRouter"));
 -//        
Assert.assertNotNull(firewallMgr._staticNatElements.get("VpcVirtualRouter"));
 -//        
Assert.assertNotNull(firewallMgr._networkAclElements.get("VpcVirtualRouter"));
 -//        
Assert.assertNull(firewallMgr._networkAclElements.get("VirtualRouter"));
 -//
 -//
 -//        
Assert.assertTrue(firewallMgr._firewallElements.get("VirtualRouter") instanceof 
FirewallServiceProvider);
 -//        Assert.assertTrue(firewallMgr._pfElements.get("VirtualRouter") 
instanceof PortForwardingServiceProvider);
 -//        
Assert.assertTrue(firewallMgr._staticNatElements.get("VirtualRouter") 
instanceof StaticNatServiceProvider);
 -//        
Assert.assertTrue(firewallMgr._networkAclElements.get("VpcVirtualRouter") 
instanceof NetworkACLServiceProvider);
 -
 -        s_logger.info("Done testing injection of service elements into 
firewall manager");
 -
 -    }
 +    private AutoCloseable closeable;
  
- 
-     @Ignore("Requires database to be set up")
-     @Test
-     public void testInjected() {
- 
- //        FirewallManagerImpl firewallMgr = 
(FirewallManagerImpl)ComponentLocator.getCurrentLocator().getManager(FirewallManager.class);
- //        
Assert.assertTrue(firewallMgr._firewallElements.enumeration().hasMoreElements());
- //        
Assert.assertTrue(firewallMgr._pfElements.enumeration().hasMoreElements());
- //        
Assert.assertTrue(firewallMgr._staticNatElements.enumeration().hasMoreElements());
- //        
Assert.assertTrue(firewallMgr._networkAclElements.enumeration().hasMoreElements());
- //        Assert.assertNotNull(firewallMgr._networkModel);
- //
- //        
Assert.assertNotNull(firewallMgr._firewallElements.get("VirtualRouter"));
- //        
Assert.assertNotNull(firewallMgr._firewallElements.get("VpcVirtualRouter"));
- //        Assert.assertNotNull(firewallMgr._pfElements.get("VirtualRouter"));
- //        
Assert.assertNotNull(firewallMgr._pfElements.get("VpcVirtualRouter"));
- //        
Assert.assertNotNull(firewallMgr._staticNatElements.get("VirtualRouter"));
- //        
Assert.assertNotNull(firewallMgr._staticNatElements.get("VpcVirtualRouter"));
- //        
Assert.assertNotNull(firewallMgr._networkAclElements.get("VpcVirtualRouter"));
- //        
Assert.assertNull(firewallMgr._networkAclElements.get("VirtualRouter"));
- //
- //
- //        
Assert.assertTrue(firewallMgr._firewallElements.get("VirtualRouter") instanceof 
FirewallServiceProvider);
- //        Assert.assertTrue(firewallMgr._pfElements.get("VirtualRouter") 
instanceof PortForwardingServiceProvider);
- //        
Assert.assertTrue(firewallMgr._staticNatElements.get("VirtualRouter") 
instanceof StaticNatServiceProvider);
- //        
Assert.assertTrue(firewallMgr._networkAclElements.get("VpcVirtualRouter") 
instanceof NetworkACLServiceProvider);
- 
-         logger.info("Done testing injection of service elements into firewall 
manager");
- 
-     }
- 
      @Mock
      AccountManager _accountMgr;
      @Mock
@@@ -116,14 -123,22 +92,27 @@@
  
      @Before
      public void initMocks() {
 -        MockitoAnnotations.initMocks(this);
 +        closeable = MockitoAnnotations.openMocks(this);
+ 
+         fwRule50to150 = createFirewallRule(50, 150, Purpose.Firewall);
+         fwRule100to200 = createFirewallRule(100, 150, Purpose.Firewall);
+         fwRule151to200 = createFirewallRule(151, 200, Purpose.Firewall);
+ 
+         pfRule50to150 = createFirewallRule(50, 150, Purpose.PortForwarding);
+         pfRule100to200 = createFirewallRule(100, 150, Purpose.PortForwarding);
+         pfRule151to200 = createFirewallRule(151, 200, Purpose.PortForwarding);
      }
  
 +    @After
 +    public void tearDown() throws Exception {
 +        closeable.close();
 +    }
 +
+     private FirewallRule createFirewallRule(int startPort, int endPort, 
Purpose purpose) {
+         return new FirewallRuleVO("xid", 1L, startPort, endPort, "TCP", 2, 3, 
4, purpose, new ArrayList<>(),
+                 new ArrayList<>(), 5, 6, null, 
FirewallRule.TrafficType.Ingress);
+     }
+ 
      @Ignore("Requires database to be set up")
      @Test
      public void testApplyRules() {
diff --cc 
server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java
index f3ba600817f,e9a58760828..d80bbffaaf4
--- 
a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java
+++ 
b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java
@@@ -364,16 -366,16 +367,16 @@@ public class UnmanagedVMsManagerImplTes
          when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2);
          
when(networkVO.getBroadcastUri()).thenReturn(URI.create(String.format("vlan://%d",
 instanceNic.getVlan())));
          when(networkVO.getDataCenterId()).thenReturn(1L);
 -        when(networkDao.findById(Mockito.anyLong())).thenReturn(networkVO);
 +        when(networkDao.findById(anyLong())).thenReturn(networkVO);
          List<NetworkVO> networks = new ArrayList<>();
          networks.add(networkVO);
 -        when(networkDao.listByZone(Mockito.anyLong())).thenReturn(networks);
 -        
doNothing().when(networkModel).checkNetworkPermissions(Mockito.any(Account.class),
 Mockito.any(Network.class));
 +        when(networkDao.listByZone(anyLong())).thenReturn(networks);
 +        
doNothing().when(networkModel).checkNetworkPermissions(any(Account.class), 
any(Network.class));
          NicProfile profile = Mockito.mock(NicProfile.class);
          Integer deviceId = 100;
-         Pair<NicProfile, Integer> pair = new Pair<NicProfile, 
Integer>(profile, deviceId);
-         when(networkOrchestrationService.importNic(nullable(String.class), 
nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), 
nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), 
nullable(DataCenter.class), anyBoolean())).thenReturn(pair);
-         when(volumeDao.findByInstance(anyLong())).thenReturn(volumes);
+         Pair<NicProfile, Integer> pair = new Pair<>(profile, deviceId);
+         when(networkOrchestrationService.importNic(nullable(String.class), 
nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), 
nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), 
nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair);
+         when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes);
          List<UserVmResponse> userVmResponses = new ArrayList<>();
          UserVmResponse userVmResponse = new UserVmResponse();
          userVmResponse.setInstanceName(instance.getName());
@@@ -695,10 -703,13 +704,14 @@@
          }
  
          ConvertInstanceAnswer convertInstanceAnswer = 
mock(ConvertInstanceAnswer.class);
-         when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter 
!= VcenterParameter.CONVERT_FAILURE);
+         ImportConvertedInstanceAnswer convertImportedInstanceAnswer = 
mock(ImportConvertedInstanceAnswer.class);
 +        
when(convertInstanceAnswer.getConvertedInstance()).thenReturn(instance);
+         when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter 
!= VcenterParameter.CONVERT_FAILURE);
 -        
when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance);
 -        
when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter != 
VcenterParameter.CONVERT_FAILURE);
++        
Mockito.lenient().when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance);
++        
Mockito.lenient().when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter
 != VcenterParameter.CONVERT_FAILURE);
          if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) {
              when(agentManager.send(Mockito.eq(convertHostId), 
Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer);
 -            when(agentManager.send(Mockito.eq(convertHostId), 
Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer);
++            
Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), 
Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer);
          }
  
          try (MockedStatic<UsageEventUtils> ignored = 
Mockito.mockStatic(UsageEventUtils.class)) {
@@@ -853,43 -880,239 +882,275 @@@
      @Test(expected = CloudRuntimeException.class)
      public void 
testSelectInstanceConversionTemporaryLocationNoPoolAvailable() {
          ClusterVO cluster = getClusterForTests();
-         Mockito.when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), 
anyString())).thenReturn(null);
-         
unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null);
+         when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), 
anyString())).thenReturn(null);
+         
unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, 
null);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdSuccess() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Routing);
+         when(host.getClusterId()).thenReturn(1L);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForImportingInClusterWithNullImportInstanceIdSuccess() {
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(hostDao.listByClusterAndHypervisorType(cluster.getId(), 
cluster.getHypervisorType())).thenReturn(List.of(host));
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void testSelectKVMHostForImportingInClusterFailure() {
+         ClusterVO cluster = getClusterForTests();
+         when(hostDao.listByClusterAndHypervisorType(cluster.getId(), 
cluster.getHypervisorType())).thenReturn(List.of());
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidCluster() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Routing);
+         when(host.getClusterId()).thenReturn(2L);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidType() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Storage);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidStatus() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Alert);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidResourceState()
 {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Disabled);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidHostId() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+ 
+         when(hostDao.findById(hostId)).thenReturn(null);
+ 
+         unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, 
hostId);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdEnabledHost() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Routing);
+         when(host.getDataCenterId()).thenReturn(1L);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdDisabledHost() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Disabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Routing);
+         when(host.getDataCenterId()).thenReturn(1L);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessCompatible() {
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+ 
+         
when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(),
+                 cluster.getHypervisorType(), 
Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host));
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessNonCompatible()
 {
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+ 
+         
when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(),
+                 cluster.getHypervisorType(), 
Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of());
+ 
+         when(hostDao.listByClusterAndHypervisorType(cluster.getId(), 
cluster.getHypervisorType())).thenReturn(List.of(host));
+ 
+         HostVO returnedHost = 
unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null);
+         Assert.assertEquals(host, returnedHost);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdFailure() {
+         ClusterVO cluster = getClusterForTests();
+ 
+         
when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(),
+                 cluster.getHypervisorType(), 
Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of());
+ 
+         when(hostDao.listByClusterAndHypervisorType(cluster.getId(), 
cluster.getHypervisorType())).thenReturn(List.of());
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
null);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidZone() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.Routing);
+         when(host.getDataCenterId()).thenReturn(2L);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidType() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Up);
+         when(host.getType()).thenReturn(Host.Type.SecondaryStorage);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidStatus() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Enabled);
+         when(host.getStatus()).thenReturn(Status.Down);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidResourceState()
 {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+         HostVO host = Mockito.mock(HostVO.class);
+         when(host.getResourceState()).thenReturn(ResourceState.Maintenance);
+ 
+         when(hostDao.findById(hostId)).thenReturn(host);
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
hostId);
+     }
+ 
+     @Test(expected = CloudRuntimeException.class)
+     public void 
testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHostId() {
+         Long hostId = 1L;
+         ClusterVO cluster = getClusterForTests();
+ 
+         when(hostDao.findById(hostId)).thenReturn(null);
+ 
+         unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, 
hostId);
      }
 +
 +    @Test
 +    public void testCheckUnmanagedDiskLimits() {
 +        Account owner = Mockito.mock(Account.class);
 +        UnmanagedInstanceTO.Disk disk = 
Mockito.mock(UnmanagedInstanceTO.Disk.class);
 +        Mockito.when(disk.getDiskId()).thenReturn("disk1");
 +        Mockito.when(disk.getCapacity()).thenReturn(100L);
 +        ServiceOffering serviceOffering = Mockito.mock(ServiceOffering.class);
 +        Mockito.when(serviceOffering.getDiskOfferingId()).thenReturn(1L);
 +        UnmanagedInstanceTO.Disk dataDisk = 
Mockito.mock(UnmanagedInstanceTO.Disk.class);
 +        Mockito.when(dataDisk.getDiskId()).thenReturn("disk2");
 +        Mockito.when(dataDisk.getCapacity()).thenReturn(1000L);
 +        Map<String, Long> dataDiskMap = new HashMap<>();
 +        dataDiskMap.put("disk2", 2L);
 +        DiskOfferingVO offering1 = Mockito.mock(DiskOfferingVO.class);
 +        Mockito.when(diskOfferingDao.findById(1L)).thenReturn(offering1);
 +        String tag1 = "tag1";
 +        
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering1)).thenReturn(List.of(tag1));
 +        DiskOfferingVO offering2 = Mockito.mock(DiskOfferingVO.class);
 +        Mockito.when(diskOfferingDao.findById(2L)).thenReturn(offering2);
 +        String tag2 = "tag2";
 +        
Mockito.when(resourceLimitService.getResourceLimitStorageTags(offering2)).thenReturn(List.of(tag2));
 +        try {
 +            
Mockito.doNothing().when(resourceLimitService).checkResourceLimit(any(), any(), 
any());
 +            
Mockito.doNothing().when(resourceLimitService).checkResourceLimitWithTag(any(), 
any(), any(), any());
 +            unmanagedVMsManager.checkUnmanagedDiskLimits(owner, disk, 
serviceOffering, List.of(dataDisk), dataDiskMap);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimit(owner, Resource.ResourceType.volume, 2);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimit(owner, 
Resource.ResourceType.primary_storage, 1100L);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimitWithTag(owner, 
Resource.ResourceType.volume, tag1,1);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimitWithTag(owner, 
Resource.ResourceType.volume, tag2,1);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimitWithTag(owner, 
Resource.ResourceType.primary_storage, tag1,100L);
 +            Mockito.verify(resourceLimitService, 
Mockito.times(1)).checkResourceLimitWithTag(owner, 
Resource.ResourceType.primary_storage, tag2,1000L);
 +        } catch (ResourceAllocationException e) {
 +            Assert.fail("Exception encountered: " + e.getMessage());
 +        }
 +    }
  }
diff --cc ui/public/locales/en.json
index 76334d2b504,8cc17bbb128..d56ab379b3f
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@@ -1564,19 -1456,8 +1564,20 @@@
  "label.noselect": "No thanks",
  "label.not.found": "Not found",
  "label.not.suitable": "Not suitable",
+ "label.not.supported": "Not supported",
  "label.notifications": "Notifications",
 +"label.nsx": "NSX",
 +"label.nsx.provider": "NSX Provider",
 +"label.nsx.provider.name": "NSX provider name",
 +"label.nsx.provider.hostname": "NSX provider hostname",
 +"label.nsx.provider.port": "NSX provider port",
 +"label.nsx.provider.username": "NSX provider username",
 +"label.nsx.provider.password": "NSX provider password",
 +"label.nsx.provider.edgecluster": "NSX provider edge cluster",
 +"label.nsx.provider.tier0gateway": "NSX provider tier-0 gateway",
 +"label.nsx.provider.transportzone": "NSX provider transport zone",
 +"label.nsx.supports.internal.lb": "Enable NSX internal LB service",
 +"label.nsx.supports.lb": "Enable NSX LB service",
  "label.num.cpu.cores": "# of CPU cores",
  "label.number": "#Rule",
  "label.numretries": "Number of retries",
diff --cc ui/src/components/view/InfoCard.vue
index 974a278b456,6b42d68ddc3..5b86cd9ea88
--- a/ui/src/components/view/InfoCard.vue
+++ b/ui/src/components/view/InfoCard.vue
@@@ -186,11 -180,15 +186,18 @@@
            <div class="resource-detail-item__label">{{ $t('label.cpu') }}</div>
            <div class="resource-detail-item__details">
              <appstore-outlined />
-             <span v-if="'cpunumber' in resource && 'cpuspeed' in resource">{{ 
resource.cpunumber }} CPU x {{ parseFloat(resource.cpuspeed / 
1000.0).toFixed(2) }} Ghz</span>
+             <span v-if="'cpunumber' in resource && 'cpuspeed' in resource">{{ 
resource.cpunumber }} CPU x {{ (resource.cpuspeed / 1000.0).toFixed(2) }} GHz
+               <a-tooltip placement="top">
+                 <template #title>
+                   {{ resource.cpuspeed }} MHz
+                 </template>
+                 <QuestionCircleOutlined />
+               </a-tooltip>
+             </span>
              <span v-else>{{ resource.cputotal }}</span>
 +            <a-tag v-if="resource.arch" style="margin-left: 10px">
 +              {{ resource.arch }}
 +            </a-tag>
            </div>
            <div>
              <span v-if="resource.cpuused">
diff --cc ui/src/views/auth/Login.vue
index 13645565557,e2d3ee4c746..10963073c18
--- a/ui/src/views/auth/Login.vue
+++ b/ui/src/views/auth/Login.vue
@@@ -311,17 -300,9 +310,18 @@@ export default 
                this.githubredirecturi = item.redirecturi
              }
            })
+           this.socialLogin = this.googleprovider || this.githubprovider
          }
        })
 +      api('forgotPassword', {}).then(response => {
 +        this.forgotPasswordEnabled = response.forgotpasswordresponse.enabled
 +      }).catch((err) => {
 +        if (err?.response?.data === null) {
 +          this.forgotPasswordEnabled = true
 +        } else {
 +          this.forgotPasswordEnabled = false
 +        }
 +      })
      },
      // handler
      async handleUsernameOrEmail (rule, value) {

Reply via email to