Skip to content

Commit 2e044f7

Browse files
nvazquezshwstpprCopilotsureshanaparti
authored andcommitted
VMware to KVM Migrations improvements (apache#11594)
* Add source VM name on virt-v2v migration log entries * Improve the feedback by displaying the running importing tasks * Add source VM name prefix on more conversion logs * Improve listing and also list completed tasks * Pass extra parameters to virt-v2v if administrator allows via global setting * Add Force converting directly to storage pool option * Refactor based on review comments * Add properties for env vars for the instance conversion * Add separate component for Import VM Tasks * applying copilot suggestions from code review Co-authored-by: Copilot <[email protected]> * Fix importing unmanaged instances due to incorrect internal name * Add VM prefix on each log operation for conversion * Log the original VM name instead of the cloned VM in case of cloning * Allow searching storage pool by UUID after conversion to support SharedMountPoint * Fix search pools logic * Improve UI and add checks for force convert to pool parameter * Support Local storage when forceconverttopool is set to true * Add config key to for allowed extra params and add validation * Fix params lists * Fix compile error * Remove extra stubbings * Fix extra params execution --------- Co-authored-by: Abhishek Kumar <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Suresh Kumar Anaparti <[email protected]>
1 parent 6a759fe commit 2e044f7

File tree

29 files changed

+1946
-281
lines changed

29 files changed

+1946
-281
lines changed

agent/conf/agent.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,9 @@ iscsi.session.cleanup.enabled=false
451451

452452
# If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise.
453453
# create.full.clone=false
454+
455+
# Instance conversion TMPDIR env var
456+
#convert.instance.env.tmpdir=
457+
458+
# Instance conversion VIRT_V2V_TMPDIR env var
459+
#convert.instance.env.virtv2v.tmpdir=

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,20 @@ public Property<Integer> getWorkers() {
798798
*/
799799
public static final Property<Boolean> VIRTV2V_VERBOSE_ENABLED = new Property<>("virtv2v.verbose.enabled", false);
800800

801+
/**
802+
* Set env TMPDIR var for virt-v2v Instance Conversion from VMware to KVM
803+
* Data type: String.<br>
804+
* Default value: <code>null</code>
805+
*/
806+
public static final Property<String> CONVERT_ENV_TMPDIR = new Property<>("convert.instance.env.tmpdir", null, String.class);
807+
808+
/**
809+
* Set env VIRT_V2V_TMPDIR var for virt-v2v Instance Conversion from VMware to KVM
810+
* Data type: String.<br>
811+
* Default value: <code>null</code>
812+
*/
813+
public static final Property<String> CONVERT_ENV_VIRTV2V_TMPDIR = new Property<>("convert.instance.env.virtv2v.tmpdir", null, String.class);
814+
801815
/**
802816
* BGP controll CIDR
803817
* Data type: String.<br>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ public class ApiConstants {
230230
public static final String EVENT_TYPE = "eventtype";
231231
public static final String EXPIRES = "expires";
232232
public static final String EXTRA_CONFIG = "extraconfig";
233+
public static final String EXTRA_PARAMS = "extraparams";
233234
public static final String EXTRA_DHCP_OPTION = "extradhcpoption";
234235
public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname";
235236
public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode";
@@ -248,6 +249,8 @@ public class ApiConstants {
248249
public static final String FIRSTNAME = "firstname";
249250
public static final String FORCED = "forced";
250251
public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
252+
public static final String FORCE_CONVERT_TO_POOL = "forceconverttopool";
253+
251254
public static final String FORCE_DELETE_HOST = "forcedeletehost";
252255
public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles";
253256
public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype";
@@ -537,6 +540,7 @@ public class ApiConstants {
537540
public static final String SHOW_CAPACITIES = "showcapacities";
538541
public static final String SHOW_REMOVED = "showremoved";
539542
public static final String SHOW_RESOURCE_ICON = "showicon";
543+
public static final String SHOW_COMPLETED = "showcompleted";
540544
public static final String SHOW_INACTIVE = "showinactive";
541545
public static final String SHOW_UNIQUE = "showunique";
542546
public static final String SIGNATURE = "signature";

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ public class ImportVmCmd extends ImportUnmanagedInstanceCmd {
159159
description = "(only for importing VMs from VMware to KVM) optional - if true, forces MS to export OVF from VMware to temporary storage, else uses KVM Host if ovftool is available, falls back to MS if not.")
160160
private Boolean forceMsToImportVmFiles;
161161

162+
@Parameter(name = ApiConstants.EXTRA_PARAMS,
163+
type = CommandType.STRING,
164+
since = "4.22",
165+
description = "(only for importing VMs from VMware to KVM) optional - extra parameters to be passed on the virt-v2v command, if allowed by the administrator")
166+
private String extraParams;
167+
168+
@Parameter(name = ApiConstants.FORCE_CONVERT_TO_POOL,
169+
type = CommandType.BOOLEAN,
170+
since = "4.22",
171+
description = "(only for importing VMs from VMware to KVM) optional - if true, forces virt-v2v conversions to write directly on the provided storage pool (avoid using temporary conversion pool).")
172+
private Boolean forceConvertToPool;
173+
162174
/////////////////////////////////////////////////////
163175
/////////////////// Accessors ///////////////////////
164176
/////////////////////////////////////////////////////
@@ -248,6 +260,14 @@ public String getEventType() {
248260
return EventTypes.EVENT_VM_IMPORT;
249261
}
250262

263+
public String getExtraParams() {
264+
return extraParams;
265+
}
266+
267+
public boolean getForceConvertToPool() {
268+
return BooleanUtils.toBooleanDefaultIfNull(forceConvertToPool, false);
269+
}
270+
251271
@Override
252272
public String getEventDescription() {
253273
String vmName = getName();
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.vm;
18+
19+
import com.cloud.exception.ConcurrentOperationException;
20+
import com.cloud.exception.InsufficientCapacityException;
21+
import com.cloud.exception.NetworkRuleConflictException;
22+
import com.cloud.exception.ResourceAllocationException;
23+
import com.cloud.exception.ResourceUnavailableException;
24+
import com.cloud.user.Account;
25+
import org.apache.cloudstack.acl.RoleType;
26+
import org.apache.cloudstack.api.APICommand;
27+
import org.apache.cloudstack.api.ApiConstants;
28+
import org.apache.cloudstack.api.BaseListCmd;
29+
import org.apache.cloudstack.api.Parameter;
30+
import org.apache.cloudstack.api.ResponseObject;
31+
import org.apache.cloudstack.api.ServerApiException;
32+
import org.apache.cloudstack.api.response.AccountResponse;
33+
import org.apache.cloudstack.api.response.HostResponse;
34+
import org.apache.cloudstack.api.response.ImportVMTaskResponse;
35+
import org.apache.cloudstack.api.response.ListResponse;
36+
import org.apache.cloudstack.api.response.ZoneResponse;
37+
import org.apache.cloudstack.context.CallContext;
38+
import org.apache.cloudstack.vm.ImportVmTasksManager;
39+
40+
import javax.inject.Inject;
41+
42+
@APICommand(name = "listImportVmTasks",
43+
description = "List running import virtual machine tasks from a unmanaged hosts into CloudStack",
44+
responseObject = ImportVMTaskResponse.class,
45+
responseView = ResponseObject.ResponseView.Full,
46+
requestHasSensitiveInfo = false,
47+
authorized = {RoleType.Admin},
48+
since = "4.22")
49+
public class ListImportVMTasksCmd extends BaseListCmd {
50+
51+
@Inject
52+
public ImportVmTasksManager importVmTasksManager;
53+
54+
@Parameter(name = ApiConstants.ZONE_ID,
55+
type = CommandType.UUID,
56+
entityType = ZoneResponse.class,
57+
required = true,
58+
description = "the zone ID")
59+
private Long zoneId;
60+
61+
@Parameter(name = ApiConstants.ACCOUNT_ID,
62+
type = CommandType.UUID,
63+
entityType = AccountResponse.class,
64+
description = "the ID of the Account")
65+
private Long accountId;
66+
67+
@Parameter(name = ApiConstants.VCENTER,
68+
type = CommandType.STRING,
69+
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
70+
private String vcenter;
71+
72+
@Parameter(name = ApiConstants.CONVERT_INSTANCE_HOST_ID,
73+
type = CommandType.UUID,
74+
entityType = HostResponse.class,
75+
description = "Conversion host of the importing task")
76+
private Long convertHostId;
77+
78+
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "Whether to list all import tasks.")
79+
private boolean listAll = false;
80+
81+
@Parameter(name = ApiConstants.SHOW_COMPLETED, type = CommandType.BOOLEAN, description = "Whether to list completed tasks.")
82+
private boolean showCompleted = false;
83+
84+
public Long getZoneId() {
85+
return zoneId;
86+
}
87+
88+
public Long getAccountId() {
89+
return accountId;
90+
}
91+
92+
public String getVcenter() {
93+
return vcenter;
94+
}
95+
96+
public Long getConvertHostId() {
97+
return convertHostId;
98+
}
99+
100+
public boolean isListAll() {
101+
return listAll;
102+
}
103+
104+
public boolean isShowCompleted() {
105+
return showCompleted;
106+
}
107+
108+
@Override
109+
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
110+
ListResponse<ImportVMTaskResponse> response = importVmTasksManager.listImportVMTasks(this);
111+
response.setResponseName(getCommandName());
112+
setResponseObject(response);
113+
}
114+
115+
@Override
116+
public long getEntityOwnerId() {
117+
Account account = CallContext.current().getCallingAccount();
118+
if (account != null) {
119+
return account.getId();
120+
}
121+
return Account.ACCOUNT_ID_SYSTEM;
122+
}
123+
}

0 commit comments

Comments
 (0)