Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e63cde4
Create/Export OVA file of the VM on external vCenter host, to tempora…
sureshanaparti Mar 11, 2024
01d8cad
Fixed ova issue on untar/extract ovf from ova file
sureshanaparti Mar 11, 2024
42287cd
Updated VMware to KVM instance migration using OVA
sureshanaparti Mar 15, 2024
ca580f5
Refactoring and cleanup
sureshanaparti Mar 18, 2024
36cfeb7
test fixes
sureshanaparti Mar 18, 2024
f1bfd63
Consider zone wide pools in the destination cluster for instance conv…
sureshanaparti Mar 18, 2024
dbe9f01
Remove local storage pool support as temporary conversion location
sureshanaparti Mar 19, 2024
b76092b
cleanup unused code
sureshanaparti Mar 21, 2024
52e74e3
some improvements, and refactoring
sureshanaparti Mar 22, 2024
e449311
import nic unit tests
sureshanaparti Mar 27, 2024
9808e5c
vmware guru unit tests
sureshanaparti Apr 5, 2024
d187a12
Separate clone VM and create template file for VMware migration
sureshanaparti Apr 8, 2024
8f3141f
Check conversion support on host before clone vm / create template on…
sureshanaparti Apr 10, 2024
d3d3b2f
minor code improvements
sureshanaparti Apr 15, 2024
8df808c
Auto select the host with instance conversion capability
sureshanaparti Apr 15, 2024
55a35a4
Skip instance conversion supported response param for non-KVM hosts
sureshanaparti Apr 16, 2024
8c294da
Show supported conversion hosts in the UI
sureshanaparti Apr 16, 2024
97e9e5d
Skip persistence map update if network doesn't exist
sureshanaparti Apr 22, 2024
70e7af5
Added support to export OVA from KVM host, through ovftool (when inst…
sureshanaparti May 27, 2024
2dd2cd3
Updated importvm api param 'usemsforovaexport' to 'forcemstodownloadv…
sureshanaparti May 28, 2024
afcf445
Updated hardcoded UI messages with message labels
sureshanaparti May 28, 2024
38ebaba
Updated UI to support importvm api param - forcemstodownloadvmfiles
sureshanaparti May 28, 2024
6ca1000
Improved instance conversion support checks on ubuntu hosts, and for …
sureshanaparti May 31, 2024
5779b04
Use OVF template (VM disks and spec files) for instance conversion fr…
sureshanaparti Jun 10, 2024
3f653b0
OVF export tool parallel threads code improvements
sureshanaparti Jun 15, 2024
438da6d
Updated 'convert.vmware.instance.to.kvm.timeout' config default value…
sureshanaparti Jun 16, 2024
c402ca5
Config values check & code improvements
sureshanaparti Jun 16, 2024
2f14225
Updated import log, with time taken and vm details
sureshanaparti Jun 16, 2024
257e229
Support for parallel downloads of VMware VM disk files while exportin…
sureshanaparti Jun 17, 2024
a1926a2
rebase fixes
sureshanaparti Jun 19, 2024
15ea501
rebase fixes
sureshanaparti Jun 21, 2024
4bff115
minor improvement
sureshanaparti Jun 24, 2024
26d017c
code improvements - threads configuration, and api parameter changes …
sureshanaparti Jun 24, 2024
df7816a
typo fix in error msg
sureshanaparti Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ public Property<Integer> getWorkers() {
public static final Property<Integer> IOTHREADS = new Property<>("iothreads", 1);

/**
* Enable verbose mode for virt-v2v Instance Conversion from Vmware to KVM
* Enable verbose mode for virt-v2v Instance Conversion from VMware to KVM
* Data type: Boolean.<br>
* Default value: <code>false</code>
*/
Expand Down
29 changes: 10 additions & 19 deletions api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,39 @@
*/
package com.cloud.agent.api.to;

import java.io.Serializable;

import com.cloud.agent.api.LogLevel;
import com.cloud.hypervisor.Hypervisor;

import java.io.Serializable;

public class RemoteInstanceTO implements Serializable {

private Hypervisor.HypervisorType hypervisorType;
private String hostName;
private String instanceName;

// Vmware Remote Instances parameters
// VMware Remote Instances parameters (required for exporting OVA through ovftool)
// TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes
private String vcenterUsername;
@LogLevel(LogLevel.Log4jLevel.Off)
private String vcenterPassword;
private String vcenterHost;
private String datacenterName;
private String clusterName;

public RemoteInstanceTO() {
}

public RemoteInstanceTO(String hostName, String instanceName, String vcenterHost,
String datacenterName, String clusterName,
String vcenterUsername, String vcenterPassword) {
public RemoteInstanceTO(String instanceName) {
this.hypervisorType = Hypervisor.HypervisorType.VMware;
this.instanceName = instanceName;
}

public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
this.hypervisorType = Hypervisor.HypervisorType.VMware;
this.hostName = hostName;
this.instanceName = instanceName;
this.vcenterHost = vcenterHost;
this.datacenterName = datacenterName;
this.clusterName = clusterName;
this.vcenterUsername = vcenterUsername;
this.vcenterPassword = vcenterPassword;
this.datacenterName = datacenterName;
}

public Hypervisor.HypervisorType getHypervisorType() {
Expand All @@ -62,10 +61,6 @@ public String getInstanceName() {
return this.instanceName;
}

public String getHostName() {
return this.hostName;
}

public String getVcenterUsername() {
return vcenterUsername;
}
Expand All @@ -81,8 +76,4 @@ public String getVcenterHost() {
public String getDatacenterName() {
return datacenterName;
}

public String getClusterName() {
return clusterName;
}
}
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/host/Host.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static String[] toStrings(Host.Type... types) {
}
public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion";

/**
* @return name of the machine.
Expand Down
33 changes: 25 additions & 8 deletions api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.cloudstack.framework.config.ConfigKey;

import com.cloud.agent.api.Command;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
Expand Down Expand Up @@ -101,21 +102,20 @@ boolean attachRestoredVolumeToVirtualMachine(long zoneId, String location, Backu
* Will generate commands to migrate a vm to a pool. For now this will only work for stopped VMs on Vmware.
*
* @param vm the stopped vm to migrate
* @param destination the primary storage pool to migrate to
* @param volumeToPool the primary storage pools to migrate to
* @return a list of commands to perform for a successful migration
*/
List<Command> finalizeMigrate(VirtualMachine vm, Map<Volume, StoragePool> volumeToPool);


/**
* Will perform a clone of a VM on an external host (if the guru can handle)
* Will return the hypervisor VM (clone VM for PowerOn VMs), performs a clone of a VM if required on an external host (if the guru can handle)
* @param hostIp VM's source host IP
* @param vmName name of the source VM to clone from
* @param vmName name of the source VM (clone VM name if cloned)
* @param params hypervisor specific additional parameters
* @return a reference to the cloned VM
* @return a reference to the hypervisor or cloned VM, and cloned flag
*/
UnmanagedInstanceTO cloneHypervisorVMOutOfBand(String hostIp, String vmName,
Map<String, String> params);
Pair<UnmanagedInstanceTO, Boolean> getHypervisorVMOutOfBandAndCloneIfRequired(String hostIp, String vmName, Map<String, String> params);

/**
* Removes a VM created as a clone of a VM on an external host
Expand All @@ -124,6 +124,23 @@ UnmanagedInstanceTO cloneHypervisorVMOutOfBand(String hostIp, String vmName,
* @param params hypervisor specific additional parameters
* @return true if the operation succeeds, false if not
*/
boolean removeClonedHypervisorVMOutOfBand(String hostIp, String vmName,
Map<String, String> params);
boolean removeClonedHypervisorVMOutOfBand(String hostIp, String vmName, Map<String, String> params);

/**
* Create an OVA/OVF template of a VM on an external host (if the guru can handle)
* @param hostIp VM's source host IP
* @param vmName name of the source VM to create template from
* @param params hypervisor specific additional parameters
* @param templateLocation datastore to create the template file
* @return the created template dir/name
*/
String createVMTemplateOutOfBand(String hostIp, String vmName, Map<String, String> params, DataStoreTO templateLocation, int threadsCountToExportOvf);

/**
* Removes the template on the location
* @param templateLocation datastore to remove the template file
* @param templateDir the template dir to remove from datastore
* @return true if the operation succeeds, false if not
*/
boolean removeVMTemplateOutOfBand(DataStoreTO templateLocation, String templateDir);
}
2 changes: 2 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ public class ApiConstants {
public static final String FORCED = "forced";
public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
public static final String FORCE_DELETE_HOST = "forcedeletehost";
public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles";
public static final String FORMAT = "format";
public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork";
public static final String FOR_SYSTEM_VMS = "forsystemvms";
Expand Down Expand Up @@ -236,6 +237,7 @@ public class ApiConstants {
public static final String NEXT_ACL_RULE_ID = "nextaclruleid";
public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash";
public static final String IMAGE_PATH = "imagepath";
public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported";
public static final String INTERNAL_DNS1 = "internaldns1";
public static final String INTERNAL_DNS2 = "internaldns2";
public static final String INTERNET_PROTOCOL = "internetprotocol";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.vm.VmImportService;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
Expand Down Expand Up @@ -118,40 +119,44 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
description = "Temp Path on external host for disk image copy" )
private String tmpPath;

// Import from Vmware to KVM migration parameters
// Import from VMware to KVM migration parameters

@Parameter(name = ApiConstants.EXISTING_VCENTER_ID,
type = CommandType.UUID,
entityType = VmwareDatacenterResponse.class,
description = "(only for importing migrated VMs from Vmware to KVM) UUID of a linked existing vCenter")
description = "(only for importing VMs from VMware to KVM) UUID of a linked existing vCenter")
private Long existingVcenterId;

@Parameter(name = ApiConstants.HOST_IP,
type = BaseCmd.CommandType.STRING,
description = "(only for importing migrated VMs from Vmware to KVM) VMware ESXi host IP/Name.")
description = "(only for importing VMs from VMware to KVM) VMware ESXi host IP/Name.")
private String hostip;

@Parameter(name = ApiConstants.VCENTER,
type = CommandType.STRING,
description = "(only for importing migrated VMs from Vmware to KVM) The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
description = "(only for importing VMs from VMware to KVM) The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vcenter;

@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING,
description = "(only for importing migrated VMs from Vmware to KVM) Name of VMware datacenter.")
description = "(only for importing VMs from VMware to KVM) Name of VMware datacenter.")
private String datacenterName;

@Parameter(name = ApiConstants.CLUSTER_NAME, type = CommandType.STRING,
description = "(only for importing migrated VMs from Vmware to KVM) Name of VMware cluster.")
description = "(only for importing VMs from VMware to KVM) Name of VMware cluster.")
private String clusterName;

@Parameter(name = ApiConstants.CONVERT_INSTANCE_HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
description = "(only for importing migrated VMs from Vmware to KVM) optional - the host to perform the virt-v2v migration from VMware to KVM.")
description = "(only for importing VMs from VMware to KVM) optional - the host to perform the virt-v2v migration from VMware to KVM.")
private Long convertInstanceHostId;

@Parameter(name = ApiConstants.CONVERT_INSTANCE_STORAGE_POOL_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class,
description = "(only for importing migrated VMs from Vmware to KVM) optional - the temporary storage pool to perform the virt-v2v migration from VMware to KVM.")
description = "(only for importing VMs from VMware to KVM) optional - the temporary storage pool to perform the virt-v2v migration from VMware to KVM.")
private Long convertStoragePoolId;

@Parameter(name = ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, type = CommandType.BOOLEAN,
description = "(only for importing VMs from VMware to KVM) optional - if true, forces MS to import VM file(s) to temporary storage, else uses KVM Host if ovftool is available, falls back to MS if not.")
private Boolean forceMsToImportVmFiles;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -200,6 +205,10 @@ public Long getConvertStoragePoolId() {
return convertStoragePoolId;
}

public Boolean getForceMsToImportVmFiles() {
return BooleanUtils.toBooleanDefaultIfNull(forceMsToImportVmFiles, false);
}

public String getHypervisor() {
return hypervisor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import com.cloud.host.Host;
import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;

Expand Down Expand Up @@ -277,6 +278,10 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Param(description = "true if the host supports encryption", since = "4.18")
private Boolean encryptionSupported;

@SerializedName(ApiConstants.INSTANCE_CONVERSION_SUPPORTED)
@Param(description = "true if the host supports instance conversion (using virt-v2v)", since = "4.19.1")
private Boolean instanceConversionSupported;

@Override
public String getObjectId() {
return this.getId();
Expand Down Expand Up @@ -526,7 +531,7 @@ public void setUsername(String username) {
this.username = username;
}

public void setDetails(Map details) {
public void setDetails(Map details, Hypervisor.HypervisorType hypervisorType) {

if (details == null) {
return;
Expand All @@ -547,6 +552,15 @@ public void setDetails(Map details) {
this.setEncryptionSupported(new Boolean(false)); // default
}

if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) {
if (detailsCopy.containsKey(Host.HOST_INSTANCE_CONVERSION)) {
this.setInstanceConversionSupported(Boolean.parseBoolean((String) detailsCopy.get(Host.HOST_INSTANCE_CONVERSION)));
detailsCopy.remove(Host.HOST_INSTANCE_CONVERSION);
} else {
this.setInstanceConversionSupported(new Boolean(false)); // default
}
}

this.details = detailsCopy;
}

Expand Down Expand Up @@ -737,6 +751,10 @@ public void setEncryptionSupported(Boolean encryptionSupported) {
this.encryptionSupported = encryptionSupported;
}

public void setInstanceConversionSupported(Boolean instanceConversionSupported) {
this.instanceConversionSupported = instanceConversionSupported;
}

public Boolean getIsTagARule() {
return isTagARule;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.apache.cloudstack.vm;

import static com.cloud.utils.NumbersUtil.toHumanReadableSize;

import java.util.List;

public class UnmanagedInstanceTO {
Expand Down Expand Up @@ -317,6 +319,16 @@ public void setDatastorePort(int datastorePort) {
public int getDatastorePort() {
return datastorePort;
}

@Override
public String toString() {
return "Disk {" +
"diskId='" + diskId + '\'' +
", capacity=" + toHumanReadableSize(capacity) +
", controller='" + controller + '\'' +
", controllerUnit=" + controllerUnit +
"}";
}
}

public static class Nic {
Expand Down Expand Up @@ -409,5 +421,14 @@ public String getPciSlot() {
public void setPciSlot(String pciSlot) {
this.pciSlot = pciSlot;
}

@Override
public String toString() {
return "Nic{" +
"nicId='" + nicId + '\'' +
", adapterType='" + adapterType + '\'' +
", macAddress='" + macAddress + '\'' +
"}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,37 @@ public interface UnmanagedVMsManager extends VmImportService, UnmanageVMService,
ConfigKey.Scope.Global,
null);

ConfigKey<Integer> ConvertVmwareInstanceToKvmTimeout = new ConfigKey<>(Integer.class,
"convert.vmware.instance.to.kvm.timeout",
"Advanced",
"3",
"Timeout (in hours) for the instance conversion process from VMware through the virt-v2v binary on a KVM host",
true,
ConfigKey.Scope.Global,
null);

ConfigKey<Integer> ThreadsOnMSToImportVMwareVMFiles = new ConfigKey<>(Integer.class,
"threads.on.ms.to.import.vmware.vm.files",
"Advanced",
"0",
"Threads to use on the management server when importing VM files from VMWare." +
" -1 or 1 disables threads, 0 uses a thread per VM disk (disabled for single disk) and >1 for manual thread configuration." +
" Max number is 10, Default is 0.",
true,
ConfigKey.Scope.Global,
null);

ConfigKey<Integer> ThreadsOnKVMHostToImportVMwareVMFiles = new ConfigKey<>(Integer.class,
"threads.on.kvm.host.to.import.vmware.vm.files",
"Advanced",
"0",
"Threads to use on the KVM host (by the ovftool, if the version is 4.4.0+) when importing VM files from VMWare." +
" -1 or 1 disables threads, 0 uses a thread per VM disk (disabled for single disk) and >1 for manual thread configuration." +
" Max number is 10, Default is 0.",
true,
ConfigKey.Scope.Global,
null);

static boolean isSupported(Hypervisor.HypervisorType hypervisorType) {
return hypervisorType == VMware || hypervisorType == KVM;
}
Expand Down
Loading