Skip to content

Commit ab20b12

Browse files
authored
KVM Ingestion - Import Instance (#7976)
This PR adds new functionality to import KVM instances from an external host or from disk images in local or shared storage. Doc PR: apache/cloudstack-documentation#356
1 parent 82f7abd commit ab20b12

File tree

40 files changed

+3466
-356
lines changed

40 files changed

+3466
-356
lines changed

api/src/main/java/com/cloud/vm/UserVmService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.vm;
1818

19+
import java.util.LinkedHashMap;
1920
import java.util.List;
2021
import java.util.Map;
2122

@@ -518,7 +519,8 @@ UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException
518519

519520
UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard,
520521
final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey,
521-
final String hostName, final HypervisorType hypervisorType, final Map<String, String> customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException;
522+
final String hostName, final HypervisorType hypervisorType, final Map<String, String> customParameters,
523+
final VirtualMachine.PowerState powerState, final LinkedHashMap<String, List<NicProfile>> networkNicMap) throws InsufficientCapacityException;
522524

523525
/**
524526
* Unmanage a guest VM from CloudStack

api/src/main/java/com/cloud/vm/VmDetailConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public interface VmDetailConstants {
3939
// KVM specific (internal)
4040
String KVM_VNC_PORT = "kvm.vnc.port";
4141
String KVM_VNC_ADDRESS = "kvm.vnc.address";
42+
String KVM_VNC_PASSWORD = "kvm.vnc.password";
4243

4344
// KVM specific, custom virtual GPU hardware
4445
String VIDEO_HARDWARE = "video.hardware";

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ public class ApiConstants {
212212
public static final String HOST_IDS = "hostids";
213213
public static final String HOST_IP = "hostip";
214214
public static final String HOST_NAME = "hostname";
215+
public static final String HOST = "host";
215216
public static final String HOST_CONTROL_STATE = "hostcontrolstate";
216217
public static final String HOSTS_MAP = "hostsmap";
217218
public static final String HYPERVISOR = "hypervisor";
@@ -1064,7 +1065,9 @@ public class ApiConstants {
10641065
public static final String SOURCE_NAT_IP = "sourcenatipaddress";
10651066
public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid";
10661067
public static final String HAS_RULES = "hasrules";
1068+
public static final String DISK_PATH = "diskpath";
10671069
public static final String IMPORT_SOURCE = "importsource";
1070+
public static final String TEMP_PATH = "temppath";
10681071
public static final String OBJECT_STORAGE = "objectstore";
10691072

10701073
public static final String HEURISTIC_RULE = "heuristicrule";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd {
8484
@Parameter(name = ApiConstants.NAME,
8585
type = CommandType.STRING,
8686
required = true,
87-
description = "the hypervisor name of the instance")
87+
description = "the name of the instance as it is known to the hypervisor")
8888
private String name;
8989

9090
@Parameter(name = ApiConstants.DISPLAY_NAME,

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

Lines changed: 106 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@
3131
import org.apache.cloudstack.api.ResponseObject;
3232
import org.apache.cloudstack.api.ServerApiException;
3333
import org.apache.cloudstack.api.response.HostResponse;
34+
import org.apache.cloudstack.api.response.NetworkResponse;
3435
import org.apache.cloudstack.api.response.StoragePoolResponse;
3536
import org.apache.cloudstack.api.response.UserVmResponse;
3637
import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
38+
import org.apache.cloudstack.api.response.ZoneResponse;
39+
import org.apache.cloudstack.vm.VmImportService;
3740
import org.apache.commons.lang3.ObjectUtils;
3841
import org.apache.commons.lang3.StringUtils;
3942
import org.apache.log4j.Logger;
4043

44+
import javax.inject.Inject;
45+
4146
@APICommand(name = "importVm",
4247
description = "Import virtual machine from a unmanaged host into CloudStack",
4348
responseObject = UserVmResponse.class,
@@ -47,21 +52,72 @@
4752
authorized = {RoleType.Admin},
4853
since = "4.19.0")
4954
public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
50-
5155
public static final Logger LOGGER = Logger.getLogger(ImportVmCmd.class);
5256

57+
@Inject
58+
public VmImportService vmImportService;
59+
60+
/////////////////////////////////////////////////////
61+
//////////////// API parameters /////////////////////
62+
/////////////////////////////////////////////////////
63+
64+
65+
@Parameter(name = ApiConstants.ZONE_ID,
66+
type = CommandType.UUID,
67+
entityType = ZoneResponse.class,
68+
required = true,
69+
description = "the zone ID")
70+
private Long zoneId;
71+
72+
@Parameter(name = ApiConstants.USERNAME,
73+
type = CommandType.STRING,
74+
description = "the username for the host")
75+
private String username;
76+
77+
@Parameter(name = ApiConstants.PASSWORD,
78+
type = CommandType.STRING,
79+
description = "the password for the host")
80+
private String password;
81+
82+
@Parameter(name = ApiConstants.HOST,
83+
type = CommandType.STRING,
84+
description = "the host name or IP address")
85+
private String host;
86+
5387
@Parameter(name = ApiConstants.HYPERVISOR,
5488
type = CommandType.STRING,
5589
required = true,
5690
description = "hypervisor type of the host")
5791
private String hypervisor;
5892

93+
@Parameter(name = ApiConstants.DISK_PATH,
94+
type = CommandType.STRING,
95+
description = "path of the disk image")
96+
private String diskPath;
97+
5998
@Parameter(name = ApiConstants.IMPORT_SOURCE,
6099
type = CommandType.STRING,
61100
required = true,
62101
description = "Source location for Import" )
63102
private String importSource;
64103

104+
@Parameter(name = ApiConstants.NETWORK_ID,
105+
type = CommandType.UUID,
106+
entityType = NetworkResponse.class,
107+
description = "the network ID")
108+
private Long networkId;
109+
110+
@Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "Host where local disk is located")
111+
private Long hostId;
112+
113+
@Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "Shared storage pool where disk is located")
114+
private Long storagePoolId;
115+
116+
@Parameter(name = ApiConstants.TEMP_PATH,
117+
type = CommandType.STRING,
118+
description = "Temp Path on external host for disk image copy" )
119+
private String tmpPath;
120+
65121
// Import from Vmware to KVM migration parameters
66122

67123
@Parameter(name = ApiConstants.EXISTING_VCENTER_ID,
@@ -73,7 +129,7 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
73129
@Parameter(name = ApiConstants.HOST_IP,
74130
type = BaseCmd.CommandType.STRING,
75131
description = "(only for importing migrated VMs from Vmware to KVM) VMware ESXi host IP/Name.")
76-
private String host;
132+
private String hostip;
77133

78134
@Parameter(name = ApiConstants.VCENTER,
79135
type = CommandType.STRING,
@@ -88,14 +144,6 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
88144
description = "(only for importing migrated VMs from Vmware to KVM) Name of VMware cluster.")
89145
private String clusterName;
90146

91-
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING,
92-
description = "(only for importing migrated VMs from Vmware to KVM) The Username required to connect to resource.")
93-
private String username;
94-
95-
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING,
96-
description = "(only for importing migrated VMs from Vmware to KVM) The password for the specified username.")
97-
private String password;
98-
99147
@Parameter(name = ApiConstants.CONVERT_INSTANCE_HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
100148
description = "(only for importing migrated VMs from Vmware to KVM) optional - the host to perform the virt-v2v migration from VMware to KVM.")
101149
private Long convertInstanceHostId;
@@ -104,30 +152,20 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
104152
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.")
105153
private Long convertStoragePoolId;
106154

107-
@Override
108-
public String getEventType() {
109-
return EventTypes.EVENT_VM_IMPORT;
110-
}
155+
/////////////////////////////////////////////////////
156+
/////////////////// Accessors ///////////////////////
157+
/////////////////////////////////////////////////////
111158

112-
@Override
113-
public String getEventDescription() {
114-
String vmName = getName();
115-
if (ObjectUtils.anyNotNull(vcenter, existingVcenterId)) {
116-
String msg = StringUtils.isNotBlank(vcenter) ?
117-
String.format("external vCenter: %s - datacenter: %s", vcenter, datacenterName) :
118-
String.format("existing vCenter Datacenter with ID: %s", existingVcenterId);
119-
return String.format("Importing unmanaged VM: %s from %s - VM: %s", getDisplayName(), msg, vmName);
120-
}
121-
return String.format("Importing unmanaged VM: %s", vmName);
159+
public Long getZoneId() {
160+
return zoneId;
122161
}
123162

124-
125163
public Long getExistingVcenterId() {
126164
return existingVcenterId;
127165
}
128166

129-
public String getHost() {
130-
return host;
167+
public String getHostIp() {
168+
return hostip;
131169
}
132170

133171
public String getVcenter() {
@@ -150,6 +188,10 @@ public String getPassword() {
150188
return password;
151189
}
152190

191+
public String getHost() {
192+
return host;
193+
}
194+
153195
public Long getConvertInstanceHostId() {
154196
return convertInstanceHostId;
155197
}
@@ -162,10 +204,47 @@ public String getHypervisor() {
162204
return hypervisor;
163205
}
164206

207+
public String getDiskPath() {
208+
return diskPath;
209+
}
210+
165211
public String getImportSource() {
166212
return importSource;
167213
}
168214

215+
public Long getHostId() {
216+
return hostId;
217+
}
218+
219+
public Long getStoragePoolId() {
220+
return storagePoolId;
221+
}
222+
223+
public String getTmpPath() {
224+
return tmpPath;
225+
}
226+
227+
public Long getNetworkId() {
228+
return networkId;
229+
}
230+
231+
@Override
232+
public String getEventType() {
233+
return EventTypes.EVENT_VM_IMPORT;
234+
}
235+
236+
@Override
237+
public String getEventDescription() {
238+
String vmName = getName();
239+
if (ObjectUtils.anyNotNull(vcenter, existingVcenterId)) {
240+
String msg = StringUtils.isNotBlank(vcenter) ?
241+
String.format("external vCenter: %s - datacenter: %s", vcenter, datacenterName) :
242+
String.format("existing vCenter Datacenter with ID: %s", existingVcenterId);
243+
return String.format("Importing unmanaged VM: %s from %s - VM: %s", getDisplayName(), msg, vmName);
244+
}
245+
return String.format("Importing unmanaged VM: %s", vmName);
246+
}
247+
169248
/////////////////////////////////////////////////////
170249
/////////////// API Implementation///////////////////
171250
/////////////////////////////////////////////////////
@@ -176,5 +255,4 @@ public void execute() throws ResourceUnavailableException, InsufficientCapacityE
176255
response.setResponseName(getCommandName());
177256
setResponseObject(response);
178257
}
179-
180258
}

0 commit comments

Comments
 (0)