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) {
