From f590d14840747446e0fd9a9e683c7527add0572c Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Mon, 17 Feb 2025 22:36:57 +0530 Subject: [PATCH] VMware Import - Support external VMs in any folders/subfolders other than the root folder ('vm') of datacenter --- .../cloud/agent/api/to/RemoteInstanceTO.java | 8 ++++++- .../cloudstack/vm/UnmanagedInstanceTO.java | 10 +++++++++ .../LibvirtConvertInstanceCommandWrapper.java | 7 +++++++ .../vm/UnmanagedVMsManagerImpl.java | 2 +- .../vmware/mo/VirtualMachineMO.java | 21 +++++++++++++++++++ .../hypervisor/vmware/util/VmwareHelper.java | 1 + 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java index d86eb2a3a7f7..18737c584b34 100644 --- a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java @@ -27,6 +27,7 @@ public class RemoteInstanceTO implements Serializable { private Hypervisor.HypervisorType hypervisorType; private String instanceName; + private String instancePath; // VMware Remote Instances parameters (required for exporting OVA through ovftool) // TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes @@ -44,9 +45,10 @@ public RemoteInstanceTO(String instanceName) { this.instanceName = instanceName; } - public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { + public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { this.hypervisorType = Hypervisor.HypervisorType.VMware; this.instanceName = instanceName; + this.instancePath = instancePath; this.vcenterHost = vcenterHost; this.vcenterUsername = vcenterUsername; this.vcenterPassword = vcenterPassword; @@ -61,6 +63,10 @@ public String getInstanceName() { return this.instanceName; } + public String getInstancePath() { + return this.instancePath; + } + public String getVcenterUsername() { return vcenterUsername; } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index 5697a040b811..6f632853527d 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -33,6 +33,8 @@ public enum PowerState { private String internalCSName; + private String path; + private PowerState powerState; private PowerState cloneSourcePowerState; @@ -75,6 +77,14 @@ public void setInternalCSName(String internalCSName) { this.internalCSName = internalCSName; } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + public PowerState getPowerState() { return powerState; } diff --git 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 index e6654b1ffc5b..504edb9d8882 100644 --- 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 @@ -57,6 +57,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve RemoteInstanceTO sourceInstance = cmd.getSourceInstance(); Hypervisor.HypervisorType sourceHypervisorType = sourceInstance.getHypervisorType(); String sourceInstanceName = sourceInstance.getInstanceName(); + String sourceInstancePath = sourceInstance.getInstancePath(); Hypervisor.HypervisorType destinationHypervisorType = cmd.getDestinationHypervisorType(); DataStoreTO conversionTemporaryLocation = cmd.getConversionTemporaryLocation(); long timeout = (long) cmd.getWait() * 1000; @@ -177,9 +178,15 @@ private String getExportOVAUrlFromRemoteInstance(RemoteInstanceTO vmwareInstance String password = vmwareInstance.getVcenterPassword(); String datacenter = vmwareInstance.getDatacenterName(); String vm = vmwareInstance.getInstanceName(); + String path = vmwareInstance.getInstancePath(); String encodedUsername = encodeUsername(username); String encodedPassword = encodeUsername(password); + if (StringUtils.isNotBlank(path)) { + s_logger.info("VM path: " + path); + return String.format("vi://%s:%s@%s/%s/%s/%s", + encodedUsername, encodedPassword, vcenter, datacenter, path, vm); + } return String.format("vi://%s:%s@%s/%s/vm/%s", encodedUsername, encodedPassword, vcenter, datacenter, vm); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 187afece84fc..0e450efce84c 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -1947,7 +1947,7 @@ private UnmanagedInstanceTO convertVmwareInstanceToKVMAfterExportingOVFToConvert 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); + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName); List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true); 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 20c62c30c0b5..1e824f34fbb6 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 @@ -891,6 +891,27 @@ public VirtualMachineFileLayoutEx getFileLayout() throws Exception { return fileLayout; } + public String getPath() throws Exception { + List subPaths = new ArrayList<>(); + ManagedObjectReference mor = _context.getVimClient().getDynamicProperty(_mor, "parent"); + while (mor != null && mor.getType().equalsIgnoreCase("Folder")) { + String subPath = _context.getVimClient().getDynamicProperty(mor, "name"); + if (StringUtils.isBlank(subPath)) { + return null; + } + subPaths.add(subPath); + mor = _context.getVimClient().getDynamicProperty(mor, "parent"); + } + + if (!subPaths.isEmpty()) { + Collections.reverse(subPaths); + String path = StringUtils.join(subPaths, "/"); + return path; + } + + return null; + } + @Override public ManagedObjectReference getParentMor() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "parent"); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 96b176df5f64..b273688c1629 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -801,6 +801,7 @@ public static UnmanagedInstanceTO getUnmanagedInstance(VmwareHypervisorHost hype instance = new UnmanagedInstanceTO(); instance.setName(vmMo.getVmName()); instance.setInternalCSName(vmMo.getInternalCSName()); + instance.setPath((vmMo.getPath())); instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); instance.setOperatingSystemId(vmMo.getVmGuestInfo().getGuestId()); VirtualMachineConfigSummary configSummary = vmMo.getConfigSummary();