Skip to content

Commit 0c86899

Browse files
Added VDDK support in VMware to KVM migrations (#12970)
1 parent 23f633a commit 0c86899

File tree

20 files changed

+1116
-95
lines changed

20 files changed

+1116
-95
lines changed

agent/conf/agent.properties

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,16 @@ iscsi.session.cleanup.enabled=false
460460

461461
# Time, in seconds, to wait before retrying to rebase during the incremental snapshot process.
462462
# incremental.snapshot.retry.rebase.wait=60
463+
464+
# Path to the VDDK library directory for VMware to KVM conversion via VDDK,
465+
# passed to virt-v2v as -io vddk-libdir=<path>
466+
#vddk.lib.dir=
467+
468+
# Ordered VDDK transport preference for VMware to KVM conversion via VDDK, passed as
469+
# -io vddk-transports=<value> to virt-v2v. Example: nbd:nbdssl
470+
#vddk.transports=
471+
472+
# Optional vCenter SHA1 thumbprint for VMware to KVM conversion via VDDK, passed as
473+
# -io vddk-thumbprint=<value>. If unset, CloudStack computes it on the KVM host via openssl.
474+
#vddk.thumbprint=
475+

agent/src/main/java/com/cloud/agent/properties/AgentProperties.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,30 @@ public Property<Integer> getWorkers() {
808808
*/
809809
public static final Property<String> CONVERT_ENV_VIRTV2V_TMPDIR = new Property<>("convert.instance.env.virtv2v.tmpdir", null, String.class);
810810

811+
/**
812+
* Path to the VDDK library directory on the KVM conversion host, used when converting VMs from VMware to KVM via VDDK.
813+
* This directory is passed to virt-v2v as <code>-io vddk-libdir=&lt;path&gt;</code>.
814+
* Data type: String.<br>
815+
* Default value: <code>null</code>
816+
*/
817+
public static final Property<String> VDDK_LIB_DIR = new Property<>("vddk.lib.dir", null, String.class);
818+
819+
/**
820+
* Ordered list of VDDK transports for virt-v2v, passed as <code>-io vddk-transports=&lt;value&gt;</code>.
821+
* Example: <code>nbd:nbdssl</code>.
822+
* Data type: String.<br>
823+
* Default value: <code>null</code>
824+
*/
825+
public static final Property<String> VDDK_TRANSPORTS = new Property<>("vddk.transports", null, String.class);
826+
827+
/**
828+
* vCenter TLS certificate thumbprint used by virt-v2v VDDK mode, passed as <code>-io vddk-thumbprint=&lt;value&gt;</code>.
829+
* If unset, the KVM host computes it at runtime from the vCenter endpoint.
830+
* Data type: String.<br>
831+
* Default value: <code>null</code>
832+
*/
833+
public static final Property<String> VDDK_THUMBPRINT = new Property<>("vddk.thumbprint", null, String.class);
834+
811835
/**
812836
* BGP controll CIDR
813837
* Data type: String.<br>

api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ public class RemoteInstanceTO implements Serializable {
3636
private String vcenterPassword;
3737
private String vcenterHost;
3838
private String datacenterName;
39+
private String clusterName;
40+
private String hostName;
3941

4042
public RemoteInstanceTO() {
4143
}
4244

43-
public RemoteInstanceTO(String instanceName) {
45+
public RemoteInstanceTO(String instanceName, String clusterName, String hostName) {
4446
this.hypervisorType = Hypervisor.HypervisorType.VMware;
4547
this.instanceName = instanceName;
48+
this.clusterName = clusterName;
49+
this.hostName = hostName;
4650
}
4751

4852
public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
@@ -55,6 +59,12 @@ public RemoteInstanceTO(String instanceName, String instancePath, String vcenter
5559
this.datacenterName = datacenterName;
5660
}
5761

62+
public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName, String clusterName, String hostName) {
63+
this(instanceName, instancePath, vcenterHost, vcenterUsername, vcenterPassword, datacenterName);
64+
this.clusterName = clusterName;
65+
this.hostName = hostName;
66+
}
67+
5868
public Hypervisor.HypervisorType getHypervisorType() {
5969
return this.hypervisorType;
6070
}
@@ -82,4 +92,12 @@ public String getVcenterHost() {
8292
public String getDatacenterName() {
8393
return datacenterName;
8494
}
95+
96+
public String getClusterName() {
97+
return clusterName;
98+
}
99+
100+
public String getHostName() {
101+
return hostName;
102+
}
85103
}

api/src/main/java/com/cloud/host/Host.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public static String[] toStrings(Host.Type... types) {
5757
String HOST_UEFI_ENABLE = "host.uefi.enable";
5858
String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
5959
String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
60+
String HOST_VDDK_SUPPORT = "host.vddk.support";
61+
String HOST_VDDK_LIB_DIR = "vddk.lib.dir";
62+
String HOST_VDDK_VERSION = "host.vddk.version";
6063
String HOST_OVFTOOL_VERSION = "host.ovftool.version";
6164
String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
6265
String HOST_SSH_PORT = "host.ssh.port";

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ public class ApiConstants {
622622
public static final String USER_CONFIGURABLE = "userconfigurable";
623623
public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
624624
public static final String USER_SECRET_KEY = "usersecretkey";
625+
public static final String USE_VDDK = "usevddk";
625626
public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
626627
public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver";
627628
public static final String UPDATE_IN_SEQUENCE = "updateinsequence";

api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
179179
description = "(only for importing VMs from VMware to KVM) optional - the ID of the guest OS for the imported VM.")
180180
private Long guestOsId;
181181

182+
@Parameter(name = ApiConstants.USE_VDDK,
183+
type = CommandType.BOOLEAN,
184+
since = "4.22.1",
185+
description = "(only for importing VMs from VMware to KVM) optional - if true, uses VDDK on the KVM conversion host for converting the VM. " +
186+
"This parameter is mutually exclusive with " + ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES + ".")
187+
private Boolean useVddk;
188+
189+
182190
/////////////////////////////////////////////////////
183191
/////////////////// Accessors ///////////////////////
184192
/////////////////////////////////////////////////////
@@ -255,6 +263,10 @@ public Long getStoragePoolId() {
255263
return storagePoolId;
256264
}
257265

266+
public boolean getUseVddk() {
267+
return BooleanUtils.toBooleanDefaultIfNull(useVddk, true);
268+
}
269+
258270
public String getTmpPath() {
259271
return tmpPath;
260272
}

core/src/main/java/com/cloud/agent/api/CheckConvertInstanceCommand.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
public class CheckConvertInstanceCommand extends Command {
2020
boolean checkWindowsGuestConversionSupport = false;
21+
boolean useVddk = false;
22+
String vddkLibDir;
2123

2224
public CheckConvertInstanceCommand() {
2325
}
@@ -26,6 +28,11 @@ public CheckConvertInstanceCommand(boolean checkWindowsGuestConversionSupport) {
2628
this.checkWindowsGuestConversionSupport = checkWindowsGuestConversionSupport;
2729
}
2830

31+
public CheckConvertInstanceCommand(boolean checkWindowsGuestConversionSupport, boolean useVddk) {
32+
this.checkWindowsGuestConversionSupport = checkWindowsGuestConversionSupport;
33+
this.useVddk = useVddk;
34+
}
35+
2936
@Override
3037
public boolean executeInSequence() {
3138
return false;
@@ -34,4 +41,20 @@ public boolean executeInSequence() {
3441
public boolean getCheckWindowsGuestConversionSupport() {
3542
return checkWindowsGuestConversionSupport;
3643
}
44+
45+
public boolean isUseVddk() {
46+
return useVddk;
47+
}
48+
49+
public void setUseVddk(boolean useVddk) {
50+
this.useVddk = useVddk;
51+
}
52+
53+
public String getVddkLibDir() {
54+
return vddkLibDir;
55+
}
56+
57+
public void setVddkLibDir(String vddkLibDir) {
58+
this.vddkLibDir = vddkLibDir;
59+
}
3760
}

core/src/main/java/com/cloud/agent/api/ConvertInstanceCommand.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public class ConvertInstanceCommand extends Command {
3131
private boolean exportOvfToConversionLocation;
3232
private int threadsCountToExportOvf = 0;
3333
private String extraParams;
34+
private boolean useVddk;
35+
private String vddkLibDir;
36+
private String vddkTransports;
37+
private String vddkThumbprint;
3438

3539
public ConvertInstanceCommand() {
3640
}
@@ -90,6 +94,38 @@ public void setExtraParams(String extraParams) {
9094
this.extraParams = extraParams;
9195
}
9296

97+
public boolean isUseVddk() {
98+
return useVddk;
99+
}
100+
101+
public void setUseVddk(boolean useVddk) {
102+
this.useVddk = useVddk;
103+
}
104+
105+
public String getVddkLibDir() {
106+
return vddkLibDir;
107+
}
108+
109+
public void setVddkLibDir(String vddkLibDir) {
110+
this.vddkLibDir = vddkLibDir;
111+
}
112+
113+
public String getVddkTransports() {
114+
return vddkTransports;
115+
}
116+
117+
public void setVddkTransports(String vddkTransports) {
118+
this.vddkTransports = vddkTransports;
119+
}
120+
121+
public String getVddkThumbprint() {
122+
return vddkThumbprint;
123+
}
124+
125+
public void setVddkThumbprint(String vddkThumbprint) {
126+
this.vddkThumbprint = vddkThumbprint;
127+
}
128+
93129
@Override
94130
public boolean executeInSequence() {
95131
return false;

engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,8 +805,11 @@ protected AgentAttache notifyMonitorsOfConnection(final AgentAttache attache, fi
805805
String uefiEnabled = detailsMap.get(Host.HOST_UEFI_ENABLE);
806806
String virtv2vVersion = detailsMap.get(Host.HOST_VIRTV2V_VERSION);
807807
String ovftoolVersion = detailsMap.get(Host.HOST_OVFTOOL_VERSION);
808+
String vddkSupport = detailsMap.get(Host.HOST_VDDK_SUPPORT);
809+
String vddkLibDir = detailsMap.get(Host.HOST_VDDK_LIB_DIR);
810+
String vddkVersion = detailsMap.get(Host.HOST_VDDK_VERSION);
808811
logger.debug("Got HOST_UEFI_ENABLE [{}] for host [{}]:", uefiEnabled, host);
809-
if (ObjectUtils.anyNotNull(uefiEnabled, virtv2vVersion, ovftoolVersion)) {
812+
if (ObjectUtils.anyNotNull(uefiEnabled, virtv2vVersion, ovftoolVersion, vddkSupport, vddkLibDir, vddkVersion)) {
810813
_hostDao.loadDetails(host);
811814
boolean updateNeeded = false;
812815
if (StringUtils.isNotBlank(uefiEnabled) && !uefiEnabled.equals(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
@@ -821,6 +824,26 @@ protected AgentAttache notifyMonitorsOfConnection(final AgentAttache attache, fi
821824
host.getDetails().put(Host.HOST_OVFTOOL_VERSION, ovftoolVersion);
822825
updateNeeded = true;
823826
}
827+
if (StringUtils.isNotBlank(vddkSupport) && !vddkSupport.equals(host.getDetails().get(Host.HOST_VDDK_SUPPORT))) {
828+
host.getDetails().put(Host.HOST_VDDK_SUPPORT, vddkSupport);
829+
updateNeeded = true;
830+
}
831+
if (!StringUtils.defaultString(vddkLibDir).equals(StringUtils.defaultString(host.getDetails().get(Host.HOST_VDDK_LIB_DIR)))) {
832+
if (StringUtils.isBlank(vddkLibDir)) {
833+
host.getDetails().remove(Host.HOST_VDDK_LIB_DIR);
834+
} else {
835+
host.getDetails().put(Host.HOST_VDDK_LIB_DIR, vddkLibDir);
836+
}
837+
updateNeeded = true;
838+
}
839+
if (!StringUtils.defaultString(vddkVersion).equals(StringUtils.defaultString(host.getDetails().get(Host.HOST_VDDK_VERSION)))) {
840+
if (StringUtils.isBlank(vddkVersion)) {
841+
host.getDetails().remove(Host.HOST_VDDK_VERSION);
842+
} else {
843+
host.getDetails().put(Host.HOST_VDDK_VERSION, vddkVersion);
844+
}
845+
updateNeeded = true;
846+
}
824847
if (updateNeeded) {
825848
_hostDao.saveDetails(host);
826849
}

0 commit comments

Comments
 (0)