From 73cabcd64167ca4da1f822a047d68b03c1abc479 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 31 Aug 2021 16:10:12 +0530 Subject: [PATCH 1/9] xcp-ng: allow passing vm boot options (#5335) * xenserver: honor vm boot details Signed-off-by: Abhishek Kumar * ui: allow boot option selection for xenserver Signed-off-by: Abhishek Kumar * fix Signed-off-by: Abhishek Kumar * fix case Signed-off-by: Abhishek Kumar * fix Signed-off-by: Abhishek Kumar * host uefi capability Signed-off-by: Abhishek Kumar * change Signed-off-by: Abhishek Kumar * add detail only if uefi supported Signed-off-by: Abhishek Kumar * update host detail Signed-off-by: Abhishek Kumar * fix version comparison Signed-off-by: Abhishek Kumar --- plugins/hypervisors/xenserver/pom.xml | 5 ++++ .../discoverer/XcpServerDiscoverer.java | 15 ++++++++++++ .../resource/CitrixResourceBase.java | 24 +++++++++++++++++++ .../discoverer/XcpServerDiscovererTest.java | 22 +++++++++++++++++ .../allocator/impl/FirstFitAllocator.java | 2 +- ui/src/views/compute/DeployVM.vue | 3 +-- 6 files changed, 68 insertions(+), 3 deletions(-) diff --git a/plugins/hypervisors/xenserver/pom.xml b/plugins/hypervisors/xenserver/pom.xml index 694ebfbaaea..7a2015ac1e5 100644 --- a/plugins/hypervisors/xenserver/pom.xml +++ b/plugins/hypervisors/xenserver/pom.xml @@ -48,5 +48,10 @@ xen-api ${cs.xapi.version} + + org.apache.maven + maven-artifact + 3.6.3 + diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java index c2a0969c9d3..bbf3686750d 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscoverer.java @@ -31,7 +31,9 @@ import javax.naming.ConfigurationException; import javax.persistence.EntityExistsException; import org.apache.cloudstack.hypervisor.xenserver.XenserverConfigs; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; +import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.xmlrpc.XmlRpcException; import com.cloud.agent.AgentManager; @@ -122,6 +124,16 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L private String xenServerIsoName = TemplateManager.XS_TOOLS_ISO; private String xenServerIsoDisplayText = "XenServer Tools Installer ISO (xen-pv-drv-iso)"; + public final static String MIN_UEFI_SUPPORTED_VERSION = "8.2"; + + public static boolean isUefiSupported(String hostProductVersion) { + if (StringUtils.isEmpty(hostProductVersion)) { + return false; + } + ComparableVersion version = new ComparableVersion(hostProductVersion); + return version.compareTo(new ComparableVersion(MIN_UEFI_SUPPORTED_VERSION)) >= 0; + } + protected XcpServerDiscoverer() { } @@ -309,6 +321,9 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L details.put("username", username); params.put("username", username); details.put("password", password); + if (isUefiSupported(prodVersion)) { + details.put(com.cloud.host.Host.HOST_UEFI_ENABLE, Boolean.TRUE.toString()); + } params.put("password", password); params.put("zone", Long.toString(dcId)); params.put("guid", record.uuid); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index f6d95ecbda5..b63480f5cf4 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.hypervisor.xenserver.resource; +import static com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer.isUefiSupported; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; import java.io.BufferedReader; @@ -51,6 +52,7 @@ import javax.naming.ConfigurationException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageAnswer; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageCommand; import org.apache.cloudstack.diagnostics.DiagnosticsService; @@ -1438,6 +1440,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } catch (final Exception e) { throw new CloudRuntimeException("Unable to finalize VM MetaData: " + vmSpec); } + try { + setVmBootDetails(vm, conn, vmSpec.getBootType(), vmSpec.getBootMode()); + } catch (final XenAPIException | XmlRpcException e) { + throw new CloudRuntimeException(String.format("Unable to handle VM boot options: %s", vmSpec), e); + } return vm; } @@ -1784,6 +1791,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } details.put("product_brand", productBrand); details.put("product_version", _host.getProductVersion()); + if (isUefiSupported(_host.getProductVersion())) { + details.put(com.cloud.host.Host.HOST_UEFI_ENABLE, Boolean.TRUE.toString()); + } if (hr.softwareVersion.get("product_version_text_short") != null) { details.put("product_version_text_short", hr.softwareVersion.get("product_version_text_short")); cmd.setHypervisorVersion(hr.softwareVersion.get("product_version_text_short")); @@ -1942,6 +1952,20 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } + protected void setVmBootDetails(final VM vm, final Connection conn, String bootType, String bootMode) throws XenAPIException, XmlRpcException { + if (!ApiConstants.BootType.UEFI.toString().equals(bootType)) { + bootType = ApiConstants.BootType.BIOS.toString(); + } + Boolean isSecure = bootType.equals(ApiConstants.BootType.UEFI.toString()) && + ApiConstants.BootMode.SECURE.toString().equals(bootMode); + final Map bootParams = vm.getHVMBootParams(conn); + bootParams.replace("firmware", bootType.toLowerCase()); + vm.setHVMBootParams(conn, bootParams); + final Map platform = vm.getPlatform(conn); + platform.put("secureboot", isSecure.toString()); + vm.setPlatform(conn, platform); + } + /** * This method just creates a XenServer network following the tunnel network * naming convention diff --git a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscovererTest.java b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscovererTest.java index f8188afd682..26c2e6da625 100644 --- a/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscovererTest.java +++ b/plugins/hypervisors/xenserver/src/test/java/com/cloud/hypervisor/xenserver/discoverer/XcpServerDiscovererTest.java @@ -17,6 +17,7 @@ package com.cloud.hypervisor.xenserver.discoverer; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; @@ -70,4 +71,25 @@ public class XcpServerDiscovererTest { inOrder.verify(vmTemplateVOMock).setDisplayText("XenServer Tools Installer ISO (xen-pv-drv-iso)"); inOrder.verify(vmTemplateDao).update(1L, vmTemplateVOMock); } + + @Test + public void uefiSupportedVersionTest() { + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("8.2")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("8.2.0")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("8.2.1")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("9")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("9.1")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("9.1.0")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("10")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("10.1")); + Assert.assertTrue(XcpServerDiscoverer.isUefiSupported("10.1.0")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported(null)); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("abc")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("0")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("7.4")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("8")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("8.1")); + Assert.assertFalse(XcpServerDiscoverer.isUefiSupported("8.1.0")); + } } diff --git a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 01f7689fea2..df6ea74881e 100644 --- a/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/main/java/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -123,7 +123,7 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator { isVMDeployedWithUefi = true; } } - s_logger.info(" Guest VM is requested with Cusotm[UEFI] Boot Type "+ isVMDeployedWithUefi); + s_logger.info(" Guest VM is requested with Custom[UEFI] Boot Type "+ isVMDeployedWithUefi); if (type == Host.Type.Storage) { diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index b1c24ccdd40..cd91ce263d6 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -491,10 +491,9 @@
+ v-if="vm.templateid && ['KVM', 'VMware', 'XenServer'].includes(hypervisor) && !template.deployasis"> From 4e53997ca2c72c0a7d8d2195708ca0a28135538b Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 31 Aug 2021 18:48:58 +0200 Subject: [PATCH 2/9] server: do not remove volume from DB if fail to expunge it from primary storage or secondary storage (#5373) * server: do not remove volume from DB if fail to expunge it from primary storage or secondary storage * server/VolumeApiServiceImpl.java: move to method * update #5373 --- .../CloudStackPrimaryDataStoreDriverImpl.java | 4 +-- .../cloud/storage/VolumeApiServiceImpl.java | 36 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index cb977de5631..e43bc4621a3 100644 --- a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -138,7 +138,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri EndPoint ep = epSelector.select(volume); Answer answer = null; if (ep == null) { - String errMsg = "No remote endpoint to send DeleteCommand, check if host or ssvm is down?"; + String errMsg = "No remote endpoint to send CreateObjectCommand, check if host or ssvm is down?"; s_logger.error(errMsg); answer = new Answer(cmd, false, errMsg); } else { @@ -280,7 +280,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri EndPoint ep = epSelector.select(srcData, destData); Answer answer = null; if (ep == null) { - String errMsg = "No remote endpoint to send command, check if host or ssvm is down?"; + String errMsg = "No remote endpoint to send CopyCommand, check if host or ssvm is down?"; s_logger.error(errMsg); answer = new Answer(cmd, false, errMsg); } else { diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index abb8265f20f..42026ef9283 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -1407,12 +1407,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * If the volume is not in the primary storage, we do nothing here. */ protected void expungeVolumesInPrimaryStorageIfNeeded(VolumeVO volume) throws InterruptedException, ExecutionException { - VolumeInfo volOnPrimary = volFactory.getVolume(volume.getId(), DataStoreRole.Primary); - if (volOnPrimary != null) { - s_logger.info("Expunging volume " + volume.getId() + " from primary data store"); - AsyncCallFuture future = volService.expungeVolumeAsync(volOnPrimary); - future.get(); - } + expungeVolumesInPrimaryOrSecondary(volume, DataStoreRole.Primary); } /** @@ -1420,16 +1415,29 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * If it is, we will execute an asynchronous call to delete it there. Then, we decrement the {@link ResourceType#secondary_storage} for the account that owns the volume. */ protected void expungeVolumesInSecondaryStorageIfNeeded(VolumeVO volume) throws InterruptedException, ExecutionException { - VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image); - if (volOnSecondary != null) { - s_logger.info("Expunging volume " + volume.getId() + " from secondary data store"); - AsyncCallFuture future2 = volService.expungeVolumeAsync(volOnSecondary); - future2.get(); - - _resourceLimitMgr.decrementResourceCount(volOnSecondary.getAccountId(), ResourceType.secondary_storage, volOnSecondary.getSize()); - } + expungeVolumesInPrimaryOrSecondary(volume, DataStoreRole.Image); } + private void expungeVolumesInPrimaryOrSecondary(VolumeVO volume, DataStoreRole role) throws InterruptedException, ExecutionException { + VolumeInfo volOnStorage = volFactory.getVolume(volume.getId(), role); + if (volOnStorage != null) { + s_logger.info("Expunging volume " + volume.getId() + " from " + role + " data store"); + AsyncCallFuture future = volService.expungeVolumeAsync(volOnStorage); + VolumeApiResult result = future.get(); + if (result.isFailed()) { + String msg = "Failed to expunge the volume " + volume + " in " + role + " data store"; + s_logger.warn(msg); + String details = ""; + if (result.getResult() != null && !result.getResult().isEmpty()) { + details = msg + " : " + result.getResult(); + } + throw new CloudRuntimeException(details); + } + if (DataStoreRole.Image.equals(role)) { + _resourceLimitMgr.decrementResourceCount(volOnStorage.getAccountId(), ResourceType.secondary_storage, volOnStorage.getSize()); + } + } + } /** * Clean volumes cache entries (if they exist). */ From aec034b94282da2acf2360dd15cb6c07615cf7e1 Mon Sep 17 00:00:00 2001 From: davidjumani Date: Wed, 1 Sep 2021 12:16:47 +0530 Subject: [PATCH 3/9] ui: Refresh page on deployvm result (#5393) --- ui/src/views/compute/DeployVM.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index cd91ce263d6..2b415ef95bc 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -1623,6 +1623,7 @@ export default { duration: 0 }) } + eventBus.$emit('vm-refresh-data') }, loadingMessage: `${title} ${this.$t('label.in.progress')}`, catchMessage: this.$t('error.fetching.async.job.result'), From ea2cd07708ea335cdf7a6162cf68de4286454a86 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Thu, 2 Sep 2021 00:08:26 +0700 Subject: [PATCH 4/9] UI - Scale VM - Fix compute offering selection not working (#5392) * scale VM: fix compute offering selection not working * hidden slider when cpuspeed empty & show customiops * remove logs * fix condition * fix condition for coltranned --- ui/src/components/view/InfoCard.vue | 2 +- ui/src/views/compute/ScaleVM.vue | 8 +++++--- ui/src/views/compute/wizard/ComputeSelection.vue | 10 +++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 5fd0fab1a37..51d91c04a52 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -26,7 +26,7 @@ @click="$message.success(`${$t('label.copied.clipboard')} : ${name}`)" v-clipboard:copy="name" > - + diff --git a/ui/src/views/compute/ScaleVM.vue b/ui/src/views/compute/ScaleVM.vue index f2653405151..7b71d2efcbd 100644 --- a/ui/src/views/compute/ScaleVM.vue +++ b/ui/src/views/compute/ScaleVM.vue @@ -32,7 +32,7 @@ @handle-search-filter="($event) => fetchData($event)" /> @@ -120,14 +122,14 @@ export default { if (this.resource.state === 'Running') { return this.resource.cpunumber } - return 'serviceofferingdetails' in this.selectedOffering ? this.selectedOffering.serviceofferingdetails.mincpunumber * 1 : 1 + return this.selectedOffering?.serviceofferingdetails?.mincpunumber * 1 || 1 }, getMinMemory () { // We can only scale up while a VM is running if (this.resource.state === 'Running') { return this.resource.memory } - return 'serviceofferingdetails' in this.selectedOffering ? this.selectedOffering.serviceofferingdetails.minmemory * 1 : 32 + return this.selectedOffering?.serviceofferingdetails?.minmemory * 1 || 32 }, getMessage () { if (this.resource.hypervisor === 'VMware') { diff --git a/ui/src/views/compute/wizard/ComputeSelection.vue b/ui/src/views/compute/wizard/ComputeSelection.vue index 816e0c914b9..6f6e2a42860 100644 --- a/ui/src/views/compute/wizard/ComputeSelection.vue +++ b/ui/src/views/compute/wizard/ComputeSelection.vue @@ -25,7 +25,7 @@ :validate-status="errors.cpu.status" :help="errors.cpu.message"> - + - + Date: Thu, 2 Sep 2021 10:53:29 +0530 Subject: [PATCH 5/9] vmware: check checksum before copying systemvm ISO to decide if it is needed (#5380) * vmware: fix copy systemvm.iso for same version For VMware, systemvm.iso is copied from MS to secondary store. Current server checks if the desired file is present on the secondary store or not. If it is not present ISO is copied. This change adds a check for checksum for source and destination ISO which would allow copying new ISO if there is a mismatch. Useful in case when file is corrupted in secondary store or new systemvm.iso is generated for dev environment. Signed-off-by: Abhishek Kumar * changes Signed-off-by: Abhishek Kumar --- .../vmware/manager/VmwareManagerImpl.java | 109 +++++++++++------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index e1e0d6b24ee..b9eefaf32d3 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -16,6 +16,53 @@ // under the License. package com.cloud.hypervisor.vmware.manager; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.rmi.RemoteException; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd; +import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd; +import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd; +import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.UpdateVmwareDcCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl; +import org.apache.cloudstack.management.ManagementServerHost; +import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + import com.amazonaws.util.CollectionUtils; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; @@ -118,48 +165,6 @@ import com.google.common.base.Strings; import com.vmware.pbm.PbmProfile; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.ManagedObjectReference; -import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; -import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd; -import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd; -import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd; -import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd; -import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; -import org.apache.cloudstack.api.command.admin.zone.UpdateVmwareDcCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.Configurable; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl; -import org.apache.cloudstack.management.ManagementServerHost; -import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.log4j.Logger; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.rmi.RemoteException; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService, Configurable { private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class); @@ -263,6 +268,24 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw _storageMgr = new VmwareStorageManagerImpl(this); } + private boolean isSystemVmIsoCopyNeeded(File srcIso, File destIso) { + if (!destIso.exists()) { + return true; + } + boolean copyNeeded = false; + try { + String srcIsoMd5 = DigestUtils.md5Hex(new FileInputStream(srcIso)); + String destIsoMd5 = DigestUtils.md5Hex(new FileInputStream(destIso)); + copyNeeded = !StringUtils.equals(srcIsoMd5, destIsoMd5); + if (copyNeeded) { + s_logger.debug(String.format("MD5 checksum: %s for source ISO: %s is different from MD5 checksum: %s from destination ISO: %s", srcIsoMd5, srcIso.getAbsolutePath(), destIsoMd5, destIso.getAbsolutePath())); + } + } catch (IOException e) { + s_logger.debug(String.format("Unable to compare MD5 checksum for systemvm.iso at source: %s and destination: %s", srcIso.getAbsolutePath(), destIso.getAbsolutePath()), e); + } + return copyNeeded; + } + @Override public String getConfigComponentName() { return VmwareManagerImpl.class.getSimpleName(); @@ -673,7 +696,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw File srcIso = getSystemVMPatchIsoFile(); File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore()); - if (!destIso.exists()) { + if (isSystemVmIsoCopyNeeded(srcIso, destIso)) { s_logger.info("Inject SSH key pairs before copying systemvm.iso into secondary storage"); _configServer.updateKeyPairs(); From 557dc5e1a021741c5dcd01e90c0b2d5315740047 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 2 Sep 2021 10:58:58 +0530 Subject: [PATCH 6/9] api: List details of template download state for stores corresponding to a zone (#5379) * api: List details of template download state for stores corresponding to a zone * fix test --- .../cloudstack/storage/datastore/db/TemplateDataStoreDao.java | 2 +- .../cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java | 4 +++- .../java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java index 77e88a9466e..f8e210ac326 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java @@ -66,7 +66,7 @@ public interface TemplateDataStoreDao extends GenericDao listByTemplate(long templateId); - List listByTemplateNotBypassed(long templateId); + List listByTemplateNotBypassed(long templateId, Long... storeIds); TemplateDataStoreVO findByTemplateZoneReady(long templateId, Long zoneId); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java index ea53825eab0..8aa411412b3 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -99,6 +99,7 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listByTemplateNotBypassed(long templateId) { + public List listByTemplateNotBypassed(long templateId, Long... storeIds) { SearchCriteria sc = templateSearch.create(); sc.setParameters("template_id", templateId); sc.setParameters("download_state", Status.BYPASSED); sc.setParameters("destroyed", false); + sc.setParameters("storeids", storeIds); return search(sc, null); } diff --git a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java index db79b96800a..d80786352bf 100644 --- a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -156,7 +156,9 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation detailsView, ResponseView view, TemplateJoinVO template) { - List templatesInStore = _templateStoreDao.listByTemplateNotBypassed(template.getId()); + List storesInZone = dataStoreDao.listStoresByZoneId(template.getDataCenterId()); + Long[] storeIds = storesInZone.stream().map(ImageStoreVO::getId).toArray(Long[]::new); + List templatesInStore = _templateStoreDao.listByTemplateNotBypassed(template.getId(), storeIds); List> downloadProgressDetails = new ArrayList(); HashMap downloadDetailInImageStores = null; for (TemplateDataStoreVO templateInStore : templatesInStore) { From fc285e23f38e75dff27e563d0eceb36c546bf049 Mon Sep 17 00:00:00 2001 From: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com> Date: Thu, 2 Sep 2021 11:02:20 +0530 Subject: [PATCH 7/9] vmware: Cancel the pending tasks for worker VM before destroying it (#5374) Co-authored-by: nicolas --- .../manager/VmwareStorageManagerImpl.java | 15 ++---- .../vmware/resource/VmwareResource.java | 4 +- .../resource/VmwareStorageProcessor.java | 43 +++++---------- .../vmware/mo/HypervisorHostHelper.java | 3 +- .../vmware/mo/VirtualMachineMO.java | 34 +++++++++++- .../hypervisor/vmware/util/VmwareClient.java | 52 +++++++++++++++++++ 6 files changed, 106 insertions(+), 45 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index a98032c7fdd..9ed1f7d1579 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -380,8 +380,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { try { if (workerVm != null) { // detach volume and destroy worker vm - workerVm.detachAllDisks(); - workerVm.destroy(); + workerVm.detachAllDisksAndDestroy(); } } catch (Throwable e) { s_logger.warn("Failed to destroy worker VM: " + workerVMName); @@ -670,8 +669,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } vmMo.removeSnapshot(templateUniqueName, false); @@ -923,8 +921,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { clonedVm.detachAllDisks(); } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } } } @@ -980,8 +977,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } } } @@ -1037,8 +1033,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } if (workerVm != null) { //detach volume and destroy worker vm - workerVm.detachAllDisks(); - workerVm.destroy(); + workerVm.detachAllDisksAndDestroy(); } } } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 8e41ed118b2..cafdc74591f 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6099,9 +6099,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (recycle) { s_logger.info("Recycle pending worker VM: " + vmMo.getName()); + vmMo.cancelPendingTasks(); vmMo.powerOff(); - vmMo.detachAllDisks(); - vmMo.destroy(); + vmMo.detachAllDisksAndDestroy(); } } } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 0f221521f47..6536bb7f466 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -429,8 +429,7 @@ public class VmwareStorageProcessor implements StorageProcessor { virtualDeviceBackingInfo = backingInfo.getParent(); } - vmMo.detachAllDisks(); - vmMo.destroy(); + vmMo.detachAllDisksAndDestroy(); VmwareStorageLayoutHelper.moveVolumeToRootFolder(dcMo, backingFiles); @@ -820,8 +819,7 @@ public class VmwareStorageProcessor implements StorageProcessor { if (volume.getDeviceId().equals(0L)) { if (existingVm != null) { s_logger.info("Found existing VM " + vmName + " before cloning from template, destroying it"); - existingVm.detachAllDisks(); - existingVm.destroy(); + existingVm.detachAllDisksAndDestroy(); } s_logger.info("ROOT Volume from deploy-as-is template, cloning template"); cloneVMFromTemplate(hyperHost, template.getPath(), vmName, primaryStore.getUuid()); @@ -853,8 +851,7 @@ public class VmwareStorageProcessor implements StorageProcessor { s_logger.info("Destroy dummy VM after volume creation"); if (vmMo != null) { s_logger.warn("Unable to destroy a null VM ManagedObjectReference"); - vmMo.detachAllDisks(); - vmMo.destroy(); + vmMo.detachAllDisksAndDestroy(); } } } else { @@ -926,8 +923,7 @@ public class VmwareStorageProcessor implements StorageProcessor { String vmdkFileBaseName = vmMo.getVmdkFileBaseNames().get(0); if (volume.getVolumeType() == Volume.Type.DATADISK) { s_logger.info("detach disks from volume-wrapper VM " + vmName); - vmMo.detachAllDisks(); - vmMo.destroy(); + vmMo.detachAllDisksAndDestroy(); } return vmdkFileBaseName; } @@ -961,11 +957,8 @@ public class VmwareStorageProcessor implements StorageProcessor { dsMo.moveDatastoreFile(vmwareLayoutFilePair[i], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[i], dcMo.getMor(), true); } - s_logger.info("detach disks from volume-wrapper VM " + vmdkName); - vmMo.detachAllDisks(); - - s_logger.info("destroy volume-wrapper VM " + vmdkName); - vmMo.destroy(); + s_logger.info("detach disks from volume-wrapper VM and destroy" + vmdkName); + vmMo.detachAllDisksAndDestroy(); String srcFile = dsMo.getDatastorePath(vmdkName, true); @@ -1134,8 +1127,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } if (workerVm != null) { //detach volume and destroy worker vm - workerVm.detachAllDisks(); - workerVm.destroy(); + workerVm.detachAllDisksAndDestroy(); } } } @@ -1272,8 +1264,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } } } @@ -1354,8 +1345,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } finally { try { if (volume.getVmName() == null && workerVmMo != null) { - workerVmMo.detachAllDisks(); - workerVmMo.destroy(); + workerVmMo.detachAllDisksAndDestroy(); } } catch (Throwable e) { s_logger.error("Failed to destroy worker VM created for detached volume"); @@ -1665,8 +1655,7 @@ public class VmwareStorageProcessor implements StorageProcessor { workerVM.exportVm(installFullPath, exportName, false, false); - workerVM.detachAllDisks(); - workerVM.destroy(); + workerVM.detachAllDisksAndDestroy(); } private String getTemplateVmdkName(String installFullPath, String exportName) { @@ -1843,8 +1832,7 @@ public class VmwareStorageProcessor implements StorageProcessor { return new Pair<>(diskDevice, disks); } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } } } @@ -2013,8 +2001,7 @@ public class VmwareStorageProcessor implements StorageProcessor { try { if (workerVm != null) { // detach volume and destroy worker vm - workerVm.detachAllDisks(); - workerVm.destroy(); + workerVm.detachAllDisksAndDestroy(); } } catch (Throwable e) { s_logger.warn("Failed to destroy worker VM: " + workerVMName); @@ -2556,8 +2543,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } finally { s_logger.info("Destroy dummy VM after volume creation"); if (vmMo != null) { - vmMo.detachAllDisks(); - vmMo.destroy(); + vmMo.detachAllDisksAndDestroy(); } } } @@ -3768,8 +3754,7 @@ public class VmwareStorageProcessor implements StorageProcessor { return _storage.getSize(srcOVFFileName); } finally { if (clonedVm != null) { - clonedVm.detachAllDisks(); - clonedVm.destroy(); + clonedVm.detachAllDisksAndDestroy(); } } } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index aafd112b223..0c41263bcef 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -2115,8 +2115,7 @@ public class HypervisorHostHelper { throw e; } } finally { - workerVmMo.detachAllDisks(); - workerVmMo.destroy(); + workerVmMo.detachAllDisksAndDestroy(); } } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index 8db7ff9c963..30396f62fd5 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -39,6 +39,8 @@ import java.util.concurrent.Future; import com.cloud.utils.exception.CloudRuntimeException; import com.vmware.vim25.InvalidStateFaultMsg; import com.vmware.vim25.RuntimeFaultFaultMsg; +import com.vmware.vim25.TaskInfo; +import com.vmware.vim25.TaskInfoState; import com.vmware.vim25.VirtualMachineTicket; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; @@ -1466,6 +1468,11 @@ public class VirtualMachineMO extends BaseMO { return chain; } + public void detachAllDisksAndDestroy() throws Exception { + detachAllDisks(); + destroy(); + } + public void detachAllDisks() throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - detachAllDisk(). target MOR: " + _mor.getValue()); @@ -2016,8 +2023,7 @@ public class VirtualMachineMO extends BaseMO { return clonedVmMo; } finally { if (!bSuccess) { - clonedVmMo.detachAllDisks(); - clonedVmMo.destroy(); + clonedVmMo.detachAllDisksAndDestroy(); } } } @@ -3568,6 +3574,30 @@ public class VirtualMachineMO extends BaseMO { return ticket.getTicket(); } + public void cancelPendingTasks() throws Exception { + String vmName = getVmName(); + s_logger.debug("Checking for pending tasks of the VM: " + vmName); + + ManagedObjectReference taskmgr = _context.getServiceContent().getTaskManager(); + List tasks = _context.getVimClient().getDynamicProperty(taskmgr, "recentTask"); + + int vmTasks = 0, vmPendingTasks = 0; + for (ManagedObjectReference task : tasks) { + TaskInfo info = (TaskInfo) (_context.getVimClient().getDynamicProperty(task, "info")); + if (info.getEntityName().equals(vmName)) { + vmTasks++; + if (!(info.getState().equals(TaskInfoState.SUCCESS) || info.getState().equals(TaskInfoState.ERROR))) { + String taskName = StringUtils.isNotBlank(info.getName()) ? info.getName() : "Unknown"; + s_logger.debug(taskName + " task pending for the VM: " + vmName + ", cancelling it"); + vmPendingTasks++; + _context.getVimClient().cancelTask(task); + } + } + } + + s_logger.debug(vmPendingTasks + " pending tasks for the VM: " + vmName + " found, out of " + vmTasks + " recent VM tasks"); + } + public void tagAsWorkerVM() throws Exception { setCustomFieldValue(CustomFieldConstants.CLOUD_WORKER, "true"); String workerTag = String.format("%d-%s", System.currentTimeMillis(), getContext().getStockObject("noderuninfo")); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java index 2395ccf5326..9d79e5466af 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClient.java @@ -42,6 +42,8 @@ import org.apache.cloudstack.utils.security.SecureSSLSocketFactory; import com.vmware.pbm.PbmPortType; import com.vmware.pbm.PbmService; import com.vmware.pbm.PbmServiceInstanceContent; + +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.w3c.dom.Element; @@ -779,4 +781,54 @@ public class VmwareClient { return vCenterSessionTimeout; } + public void cancelTask(ManagedObjectReference task) throws Exception { + TaskInfo info = (TaskInfo)(getDynamicProperty(task, "info")); + if (info == null) { + s_logger.warn("Unable to get the task info, so couldn't cancel the task"); + return; + } + + String taskName = StringUtils.isNotBlank(info.getName()) ? info.getName() : "Unknown"; + taskName += "(" + info.getKey() + ")"; + + String entityName = StringUtils.isNotBlank(info.getEntityName()) ? info.getEntityName() : ""; + + if (info.getState().equals(TaskInfoState.SUCCESS)) { + s_logger.debug(taskName + " task successfully completed for the entity " + entityName + ", can't cancel it"); + return; + } + + if (info.getState().equals(TaskInfoState.ERROR)) { + s_logger.debug(taskName + " task execution failed for the entity " + entityName + ", can't cancel it"); + return; + } + + s_logger.debug(taskName + " task pending for the entity " + entityName + ", trying to cancel"); + if (!info.isCancelable()) { + s_logger.warn(taskName + " task will continue to run on vCenter because it can't be cancelled"); + return; + } + + s_logger.debug("Cancelling task " + taskName + " of the entity " + entityName); + getService().cancelTask(task); + + // Since task cancellation is asynchronous, wait for the task to be cancelled + Object[] result = waitForValues(task, new String[] {"info.state", "info.error"}, new String[] {"state"}, + new Object[][] {new Object[] {TaskInfoState.SUCCESS, TaskInfoState.ERROR}}); + + if (result != null && result.length == 2) { //result for 2 properties: info.state, info.error + if (result[0].equals(TaskInfoState.SUCCESS)) { + s_logger.warn("Failed to cancel" + taskName + " task of the entity " + entityName + ", the task successfully completed"); + } + + if (result[1] instanceof LocalizedMethodFault) { + MethodFault fault = ((LocalizedMethodFault)result[1]).getFault(); + if (fault instanceof RequestCanceled) { + s_logger.debug(taskName + " task of the entity " + entityName + " was successfully cancelled"); + } + } else { + s_logger.warn("Couldn't cancel " + taskName + " task of the entity " + entityName + " due to " + ((LocalizedMethodFault)result[1]).getLocalizedMessage()); + } + } + } } From 989a46850e430d202692ec60bb89d0a250ba2a68 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Thu, 2 Sep 2021 10:27:20 +0200 Subject: [PATCH 8/9] vr: ipsec/l2tp vpn secret with no ID selectors (#5375) according to https://wiki.strongswan.org/projects/strongswan/wiki/Ipsecsecrets , the ID selector is optional. --- systemvm/debian/opt/cloud/bin/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index cafd739d7ca..3957d0e0f54 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -742,7 +742,7 @@ class CsRemoteAccessVpn(CsDataBag): secret = CsFile(vpnsecretfilte) secret.empty() - secret.addeq("%s %%any : PSK \"%s\"" % (left, psk)) + secret.addeq("%s : PSK \"%s\"" % (left, psk)) secret.commit() xl2tpdconf = CsFile(xl2tpdconffile) From 70f2420e541c3d25929c007994caf409ae415f2b Mon Sep 17 00:00:00 2001 From: Rakesh Date: Thu, 2 Sep 2021 10:29:46 +0200 Subject: [PATCH 9/9] router: Use source IP from subnet for snat (#5376) When snat is configured on a vm in a subnet then the source ip should be taken from the same subnet rather than from random other subnet. Co-authored-by: Rakesh Venkatesh --- systemvm/debian/opt/cloud/bin/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index 3957d0e0f54..53e9452d0b9 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -1008,7 +1008,7 @@ class CsForwardingRules(CsDataBag): # Configure the hairpin snat self.fw.append(["nat", "front", "-A POSTROUTING -s %s -d %s -j SNAT -o %s --to-source %s" % - (self.getNetworkByIp(rule['internal_ip']), rule["internal_ip"], self.getDeviceByIp(rule["internal_ip"]), self.getGuestIp())]) + (self.getNetworkByIp(rule['internal_ip']), rule["internal_ip"], self.getDeviceByIp(rule["internal_ip"]), self.getGuestIpByIp(rule["internal_ip"]))]) class IpTablesExecutor: