Skip to content

Commit 139e3b2

Browse files
nvazquezDaanHooglandsureshanaparti
authored andcommitted
[Vmware] Improve listing of Vmware Datacenter VMs for migration to KVM (apache#10770)
Co-authored-by: dahn <daan.hoogland@gmail.com> Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
1 parent 58b31d6 commit 139e3b2

10 files changed

Lines changed: 290 additions & 44 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ public class UnmanagedInstanceResponse extends BaseResponse {
7979
@Param(description = "the operating system of the virtual machine")
8080
private String operatingSystem;
8181

82+
@SerializedName(ApiConstants.BOOT_MODE)
83+
@Param(description = "indicates the boot mode")
84+
private String bootMode;
85+
86+
@SerializedName(ApiConstants.BOOT_TYPE)
87+
@Param(description = "indicates the boot type")
88+
private String bootType;
89+
8290
@SerializedName(ApiConstants.DISK)
8391
@Param(description = "the list of disks associated with the virtual machine", responseObject = UnmanagedInstanceDiskResponse.class)
8492
private Set<UnmanagedInstanceDiskResponse> disks;
@@ -211,4 +219,20 @@ public void setNics(Set<NicResponse> nics) {
211219
public void addNic(NicResponse nic) {
212220
this.nics.add(nic);
213221
}
222+
223+
public String getBootMode() {
224+
return bootMode;
225+
}
226+
227+
public void setBootMode(String bootMode) {
228+
this.bootMode = bootMode;
229+
}
230+
231+
public String getBootType() {
232+
return bootType;
233+
}
234+
235+
public void setBootType(String bootType) {
236+
this.bootType = bootType;
237+
}
214238
}

api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public enum PowerState {
6161

6262
private String vncPassword;
6363

64+
private String bootType;
65+
private String bootMode;
66+
6467
public String getName() {
6568
return name;
6669
}
@@ -195,6 +198,22 @@ public String toString() {
195198
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(
196199
this, "name", "internalCSName", "hostName", "clusterName"));
197200
}
201+
202+
public String getBootType() {
203+
return bootType;
204+
}
205+
206+
public void setBootType(String bootType) {
207+
this.bootType = bootType;
208+
}
209+
210+
public String getBootMode() {
211+
return bootMode;
212+
}
213+
214+
public void setBootMode(String bootMode) {
215+
this.bootMode = bootMode;
216+
}
198217

199218
public static class Disk {
200219
private String diskId;

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import javax.naming.ConfigurationException;
4444
import javax.persistence.EntityExistsException;
4545

46+
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
4647
import com.cloud.hypervisor.vmware.util.VmwareClient;
4748
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
4849
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
@@ -1585,14 +1586,26 @@ public List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsph
15851586
return compatiblePools;
15861587
}
15871588

1588-
@Override
1589-
public List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
1589+
private static class VcenterData {
1590+
public final String vcenter;
1591+
public final String datacenterName;
1592+
public final String username;
1593+
public final String password;
1594+
1595+
public VcenterData(String vcenter, String datacenterName, String username, String password) {
1596+
this.vcenter = vcenter;
1597+
this.datacenterName = datacenterName;
1598+
this.username = username;
1599+
this.password = password;
1600+
}
1601+
}
1602+
1603+
private VcenterData getVcenterData(ListVmwareDcVmsCmd cmd) {
15901604
String vcenter = cmd.getVcenter();
15911605
String datacenterName = cmd.getDatacenterName();
15921606
String username = cmd.getUsername();
15931607
String password = cmd.getPassword();
15941608
Long existingVcenterId = cmd.getExistingVcenterId();
1595-
String keyword = cmd.getKeyword();
15961609

15971610
if ((existingVcenterId == null && StringUtils.isBlank(vcenter)) ||
15981611
(existingVcenterId != null && StringUtils.isNotBlank(vcenter))) {
@@ -1613,34 +1626,67 @@ public List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
16131626
username = vmwareDc.getUser();
16141627
password = vmwareDc.getPassword();
16151628
}
1629+
VcenterData vmwaredc = new VcenterData(vcenter, datacenterName, username, password);
1630+
return vmwaredc;
1631+
}
1632+
1633+
private static VmwareContext getVmwareContext(String vcenter, String username, String password) throws Exception {
1634+
s_logger.debug(String.format("Connecting to the VMware vCenter %s", vcenter));
1635+
String serviceUrl = String.format("https://%s/sdk/vimService", vcenter);
1636+
VmwareClient vimClient = new VmwareClient(vcenter);
1637+
vimClient.connect(serviceUrl, username, password);
1638+
return new VmwareContext(vimClient, vcenter);
1639+
}
1640+
1641+
@Override
1642+
public List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
1643+
VcenterData vmwareDC = getVcenterData(cmd);
1644+
String vcenter = vmwareDC.vcenter;
1645+
String username = vmwareDC.username;
1646+
String password = vmwareDC.password;
1647+
String datacenterName = vmwareDC.datacenterName;
1648+
String keyword = cmd.getKeyword();
1649+
String esxiHostName = cmd.getHostName();
1650+
String virtualMachineName = cmd.getInstanceName();
16161651

16171652
try {
1618-
s_logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs",
1619-
datacenterName, vcenter));
1620-
String serviceUrl = String.format("https://%s/sdk/vimService", vcenter);
1621-
VmwareClient vimClient = new VmwareClient(vcenter);
1622-
vimClient.connect(serviceUrl, username, password);
1623-
VmwareContext context = new VmwareContext(vimClient, vcenter);
1624-
1625-
DatacenterMO dcMo = new DatacenterMO(context, datacenterName);
1626-
ManagedObjectReference dcMor = dcMo.getMor();
1627-
if (dcMor == null) {
1628-
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s",
1629-
datacenterName, vcenter);
1630-
s_logger.error(msg);
1631-
throw new InvalidParameterValueException(msg);
1653+
VmwareContext context = getVmwareContext(vcenter, username, password);
1654+
DatacenterMO dcMo = getDatacenterMO(context, vcenter, datacenterName);
1655+
1656+
List<UnmanagedInstanceTO> instances;
1657+
if (StringUtils.isNotBlank(esxiHostName) && StringUtils.isNotBlank(virtualMachineName)) {
1658+
ManagedObjectReference hostMor = dcMo.findHost(esxiHostName);
1659+
if (hostMor == null) {
1660+
String errorMsg = String.format("Cannot find a host with name %s on vcenter %s", esxiHostName, vcenter);
1661+
s_logger.error(errorMsg);
1662+
throw new CloudRuntimeException(errorMsg);
1663+
}
1664+
HostMO hostMO = new HostMO(context, hostMor);
1665+
VirtualMachineMO vmMo = hostMO.findVmOnHyperHost(virtualMachineName);
1666+
instances = Collections.singletonList(VmwareHelper.getUnmanagedInstance(hostMO, vmMo));
1667+
} else {
1668+
instances = dcMo.getAllVmsOnDatacenter(keyword);
16321669
}
1633-
List<UnmanagedInstanceTO> instances = dcMo.getAllVmsOnDatacenter();
1634-
return StringUtils.isBlank(keyword) ? instances :
1635-
instances.stream().filter(x -> x.getName().toLowerCase().contains(keyword.toLowerCase())).collect(Collectors.toList());
1670+
return instances;
16361671
} catch (Exception e) {
1637-
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
1672+
String errorMsg = String.format("Error retrieving VMs from the VMware VC %s datacenter %s: %s",
16381673
vcenter, datacenterName, e.getMessage());
16391674
s_logger.error(errorMsg, e);
16401675
throw new CloudRuntimeException(errorMsg);
16411676
}
16421677
}
16431678

1679+
private static DatacenterMO getDatacenterMO(VmwareContext context, String vcenter, String datacenterName) throws Exception {
1680+
DatacenterMO dcMo = new DatacenterMO(context, datacenterName);
1681+
ManagedObjectReference dcMor = dcMo.getMor();
1682+
if (dcMor == null) {
1683+
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s", datacenterName, vcenter);
1684+
s_logger.error(msg);
1685+
throw new InvalidParameterValueException(msg);
1686+
}
1687+
return dcMo;
1688+
}
1689+
16441690
@Override
16451691
public boolean hasNexusVSM(Long clusterId) {
16461692
ClusterVSMMapVO vsmMapVo = null;

plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/api/command/admin/zone/ListVmwareDcVmsCmd.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ public class ListVmwareDcVmsCmd extends BaseListCmd {
7070
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
7171
private String password;
7272

73+
@Parameter(name = ApiConstants.HOST_NAME, type = CommandType.STRING, description = "Name of the host on vCenter. Must be set along with the instancename parameter")
74+
private String hostName;
75+
76+
@Parameter(name = ApiConstants.INSTANCE_NAME, type = CommandType.STRING, description = "Name of the VM on vCenter. Must be set along with the hostname parameter")
77+
private String instanceName;
78+
7379
public String getVcenter() {
7480
return vcenter;
7581
}
@@ -86,10 +92,18 @@ public String getDatacenterName() {
8692
return datacenterName;
8793
}
8894

95+
public String getHostName() {
96+
return hostName;
97+
}
98+
8999
public Long getExistingVcenterId() {
90100
return existingVcenterId;
91101
}
92102

103+
public String getInstanceName() {
104+
return instanceName;
105+
}
106+
93107
@Override
94108
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
95109
checkParameters();
@@ -125,6 +139,11 @@ private void checkParameters() {
125139
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
126140
"Please set all the information for a vCenter IP/Name, datacenter, username and password");
127141
}
142+
if ((StringUtils.isNotBlank(instanceName) && StringUtils.isBlank(hostName)) ||
143+
(StringUtils.isBlank(instanceName) && StringUtils.isNotBlank(hostName))) {
144+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
145+
"Please set the hostname parameter along with the instancename parameter");
146+
}
128147
}
129148

130149
@Override

server/src/main/java/com/cloud/api/ApiResponseHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5276,6 +5276,8 @@ public UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstan
52765276
response.setMemory(instance.getMemory());
52775277
response.setOperatingSystemId(instance.getOperatingSystemId());
52785278
response.setOperatingSystem(instance.getOperatingSystem());
5279+
response.setBootMode(instance.getBootMode());
5280+
response.setBootType(instance.getBootType());
52795281
response.setObjectName("unmanagedinstance");
52805282

52815283
if (instance.getDisks() != null) {

ui/src/views/tools/ManageInstances.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,31 @@ export default {
13201320
this.fetchInstances()
13211321
}
13221322
},
1323+
fetchVmwareInstanceForKVMMigration (vmname, hostname) {
1324+
const params = {}
1325+
if (this.isMigrateFromVmware && this.selectedVmwareVcenter) {
1326+
if (this.selectedVmwareVcenter.vcenter) {
1327+
params.datacentername = this.selectedVmwareVcenter.datacentername
1328+
params.vcenter = this.selectedVmwareVcenter.vcenter
1329+
params.username = this.selectedVmwareVcenter.username
1330+
params.password = this.selectedVmwareVcenter.password
1331+
} else {
1332+
params.existingvcenterid = this.selectedVmwareVcenter.existingvcenterid
1333+
}
1334+
params.instancename = vmname
1335+
params.hostname = hostname
1336+
}
1337+
api('listVmwareDcVms', params).then(json => {
1338+
const response = json.listvmwaredcvmsresponse
1339+
this.selectedUnmanagedInstance = response.unmanagedinstance[0]
1340+
this.selectedUnmanagedInstance.ostypename = this.selectedUnmanagedInstance.osdisplayname
1341+
this.selectedUnmanagedInstance.state = this.selectedUnmanagedInstance.powerstate
1342+
}).catch(error => {
1343+
this.$notifyError(error)
1344+
}).finally(() => {
1345+
this.loading = false
1346+
})
1347+
},
13231348
onManageInstanceAction () {
13241349
this.selectedUnmanagedInstance = {}
13251350
if (this.unmanagedInstances.length > 0 &&
@@ -1337,6 +1362,9 @@ export default {
13371362
}
13381363
})
13391364
this.showUnmanageForm = false
1365+
} else if (this.isMigrateFromVmware) {
1366+
this.fetchVmwareInstanceForKVMMigration(this.selectedUnmanagedInstance.name, this.selectedUnmanagedInstance.hostname)
1367+
this.showUnmanageForm = true
13401368
} else {
13411369
this.showUnmanageForm = true
13421370
}

ui/src/views/tools/SelectVmwareVcenter.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ export default {
227227
} else {
228228
params.existingvcenterid = this.selectedExistingVcenterId
229229
}
230+
params.page = 1
231+
params.pagesize = 10
230232
api('listVmwareDcVms', params).then(json => {
231233
const obj = {
232234
params: params,
@@ -265,6 +267,11 @@ export default {
265267
this.loading = false
266268
})
267269
},
270+
onSelectExternalVmwareDatacenter (value) {
271+
if (this.vcenterSelectedOption === 'new' && !(this.vcenter === '' || this.datacentername === '' || this.username === '' || this.password === '')) {
272+
this.listVmwareDatacenterVms()
273+
}
274+
},
268275
onSelectExistingVmwareDatacenter (value) {
269276
this.selectedExistingVcenterId = value
270277
},

0 commit comments

Comments
 (0)