Skip to content

Commit f9e9466

Browse files
committed
Improve listing and also list completed tasks
1 parent 83fd30d commit f9e9466

File tree

11 files changed

+211
-35
lines changed

11 files changed

+211
-35
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ public class ApiConstants {
526526
public static final String SHOW_CAPACITIES = "showcapacities";
527527
public static final String SHOW_REMOVED = "showremoved";
528528
public static final String SHOW_RESOURCE_ICON = "showicon";
529+
public static final String SHOW_COMPLETED = "showcompleted";
529530
public static final String SHOW_INACTIVE = "showinactive";
530531
public static final String SHOW_UNIQUE = "showunique";
531532
public static final String SIGNATURE = "signature";

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ public class ListImportVMTasksCmd extends BaseListCmd {
7575
description = "Conversion host of the importing task")
7676
private Long convertHostId;
7777

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+
7884
public Long getZoneId() {
7985
return zoneId;
8086
}
@@ -91,6 +97,14 @@ public Long getConvertHostId() {
9197
return convertHostId;
9298
}
9399

100+
public boolean isListAll() {
101+
return listAll;
102+
}
103+
104+
public boolean isShowCompleted() {
105+
return showCompleted;
106+
}
107+
94108
@Override
95109
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
96110
ListResponse<ImportVMTaskResponse> response = vmImportService.listImportVMTasks(this);

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ public class ImportVMTaskResponse extends BaseResponse {
4747
@Param(description = "the ID of account")
4848
private String accountId;
4949

50+
@SerializedName(ApiConstants.VIRTUAL_MACHINE_ID)
51+
@Param(description = "the ID of the imported VM (after task is completed)")
52+
private String virtualMachineId;
53+
5054
@SerializedName(ApiConstants.DISPLAY_NAME)
5155
@Param(description = "the display name of the importing VM")
5256
private String displayName;
@@ -67,9 +71,13 @@ public class ImportVMTaskResponse extends BaseResponse {
6771
@Param(description = "the current step on the importing VM task")
6872
private String step;
6973

74+
@SerializedName("stepduration")
75+
@Param(description = "the duration of the current step")
76+
private String stepDuration;
77+
7078
@SerializedName(ApiConstants.DURATION)
71-
@Param(description = "the current step duration in seconds")
72-
private Long duration;
79+
@Param(description = "the total task duration")
80+
private String duration;
7381

7482
@SerializedName(ApiConstants.DESCRIPTION)
7583
@Param(description = "the current step description on the importing VM task")
@@ -131,6 +139,14 @@ public void setAccountId(String accountId) {
131139
this.accountId = accountId;
132140
}
133141

142+
public String getVirtualMachineId() {
143+
return virtualMachineId;
144+
}
145+
146+
public void setVirtualMachineId(String virtualMachineId) {
147+
this.virtualMachineId = virtualMachineId;
148+
}
149+
134150
public String getDisplayName() {
135151
return displayName;
136152
}
@@ -171,11 +187,19 @@ public void setStep(String step) {
171187
this.step = step;
172188
}
173189

174-
public Long getDuration() {
190+
public String getStepDuration() {
191+
return stepDuration;
192+
}
193+
194+
public void setStepDuration(String stepDuration) {
195+
this.stepDuration = stepDuration;
196+
}
197+
198+
public String getDuration() {
175199
return duration;
176200
}
177201

178-
public void setDuration(Long duration) {
202+
public void setDuration(String duration) {
179203
this.duration = duration;
180204
}
181205

engine/schema/src/main/java/com/cloud/vm/ImportVMTaskVO.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public ImportVMTaskVO() {
7575
@Column(name = "user_id")
7676
private long userId;
7777

78+
@Column(name = "vm_id")
79+
private Long vmId;
7880
@Column(name = "display_name")
7981
private String displayName;
8082

@@ -94,11 +96,14 @@ public ImportVMTaskVO() {
9496
private long importHostId;
9597

9698
@Column(name = "step")
97-
Step step;
99+
private Step step;
98100

99101
@Column(name = "description")
100102
private String description;
101103

104+
@Column(name = "duration")
105+
private Long duration;
106+
102107
@Column(name = "created")
103108
@Temporal(value = TemporalType.TIMESTAMP)
104109
private Date created;
@@ -153,6 +158,14 @@ public void setUserId(long userId) {
153158
this.userId = userId;
154159
}
155160

161+
public Long getVmId() {
162+
return vmId;
163+
}
164+
165+
public void setVmId(Long vmId) {
166+
this.vmId = vmId;
167+
}
168+
156169
public String getDisplayName() {
157170
return displayName;
158171
}
@@ -217,6 +230,14 @@ public void setDescription(String description) {
217230
this.description = description;
218231
}
219232

233+
public Long getDuration() {
234+
return duration;
235+
}
236+
237+
public void setDuration(Long duration) {
238+
this.duration = duration;
239+
}
240+
220241
public Date getCreated() {
221242
return created;
222243
}

engine/schema/src/main/java/com/cloud/vm/dao/ImportVMTaskDao.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@
2525

2626
public interface ImportVMTaskDao extends GenericDao<ImportVMTaskVO, Long> {
2727

28-
List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId);
28+
List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted);
2929
}

engine/schema/src/main/java/com/cloud/vm/dao/ImportVMTaskDaoImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void init() {
4646

4747

4848
@Override
49-
public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId) {
49+
public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted) {
5050
SearchCriteria<ImportVMTaskVO> sc = AllFieldsSearch.create();
5151
if (zoneId != null) {
5252
sc.setParameters("zoneId", zoneId);
@@ -60,6 +60,6 @@ public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, Strin
6060
if (convertHostId != null) {
6161
sc.setParameters("convertHostId", convertHostId);
6262
}
63-
return listBy(sc);
63+
return showCompleted ? listIncludingRemovedBy(sc) : listBy(sc);
6464
}
6565
}

engine/schema/src/main/resources/META-INF/db/schema-42100to42200.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ CREATE TABLE IF NOT EXISTS `cloud`.`import_vm_task`(
2929
`zone_id` bigint unsigned NOT NULL COMMENT 'Zone ID',
3030
`account_id` bigint unsigned NOT NULL COMMENT 'Account ID',
3131
`user_id` bigint unsigned NOT NULL COMMENT 'User ID',
32+
`vm_id` bigint unsigned COMMENT 'VM ID',
3233
`display_name` varchar(255) COMMENT 'Display VM Name',
3334
`vcenter` varchar(255) COMMENT 'VCenter',
3435
`datacenter` varchar(255) COMMENT 'VCenter Datacenter name',
@@ -37,13 +38,15 @@ CREATE TABLE IF NOT EXISTS `cloud`.`import_vm_task`(
3738
`import_host_id` bigint unsigned COMMENT 'Import Host ID',
3839
`step` varchar(20) NOT NULL COMMENT 'Importing VM Task Step',
3940
`description` varchar(255) COMMENT 'Importing VM Task Description',
41+
`duration` bigint unsigned COMMENT 'Duration in milliseconds for the completed tasks',
4042
`created` datetime NOT NULL COMMENT 'date created',
4143
`updated` datetime COMMENT 'date updated if not null',
4244
`removed` datetime COMMENT 'date removed if not null',
4345
PRIMARY KEY (`id`),
4446
CONSTRAINT `fk_import_vm_task__zone_id` FOREIGN KEY `fk_import_vm_task__zone_id` (`zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE,
4547
CONSTRAINT `fk_import_vm_task__account_id` FOREIGN KEY `fk_import_vm_task__account_id` (`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE,
4648
CONSTRAINT `fk_import_vm_task__user_id` FOREIGN KEY `fk_import_vm_task__user_id` (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE,
49+
CONSTRAINT `fk_import_vm_task__vm_id` FOREIGN KEY `fk_import_vm_task__vm_id` (`user_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE,
4750
CONSTRAINT `fk_import_vm_task__convert_host_id` FOREIGN KEY `fk_import_vm_task__convert_host_id` (`convert_host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
4851
CONSTRAINT `fk_import_vm_task__import_host_id` FOREIGN KEY `fk_import_vm_task__import_host_id` (`import_host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
4952
INDEX `i_import_vm_task__zone_id`(`zone_id`)

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
120120
timeout, verboseModeEnabled);
121121
if (!result) {
122122
String err = String.format(
123-
"The virt-v2v conversion for the OVF %s failed. Please check the agent logs " +
123+
"(%s) The virt-v2v conversion for the OVF %s failed. Please check the agent logs " +
124124
"for the virt-v2v output. Please try on a different kvm host which " +
125125
"has a different virt-v2v version.",
126-
ovfTemplateDirOnConversionLocation);
126+
sourceInstanceName, ovfTemplateDirOnConversionLocation);
127127
logger.error(err);
128128
return new Answer(cmd, false, err);
129129
}

server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,13 @@
195195
import java.util.Random;
196196
import java.util.Set;
197197
import java.util.TimeZone;
198-
import java.util.concurrent.TimeUnit;
199198
import java.util.stream.Collectors;
200199

201200
import static com.cloud.vm.ImportVMTaskVO.Step.CloningInstance;
202201
import static com.cloud.vm.ImportVMTaskVO.Step.Completed;
203202
import static com.cloud.vm.ImportVMTaskVO.Step.ConvertingInstance;
204203
import static com.cloud.vm.ImportVMTaskVO.Step.Importing;
204+
import static com.cloud.vm.ImportVMTaskVO.Step.Prepare;
205205
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
206206
import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS;
207207

@@ -1639,13 +1639,19 @@ private String getStepDescription(ImportVMTaskVO importVMTaskVO, HostVO convertH
16391639
String datacenter = importVMTaskVO.getDatacenter();
16401640

16411641
StringBuilder stringBuilder = new StringBuilder();
1642-
stringBuilder.append(String.format("[%s] ", DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate)));
1643-
if (CloningInstance == step) {
1644-
stringBuilder.append(String.format("Cloning source instance: %s on vCenter: %s / datacenter: %s", sourceVMName, vcenter, datacenter));
1645-
} else if (ConvertingInstance == step) {
1646-
stringBuilder.append(String.format("Converting the cloned VMware instance to a KVM instance on the host: %s", convertHost.getName()));
1647-
} else if (Importing == step) {
1648-
stringBuilder.append(String.format("Importing the converted KVM instance on the host: %s", importHost.getName()));
1642+
if (Completed == step) {
1643+
stringBuilder.append("Completed at ").append(DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate));
1644+
} else {
1645+
stringBuilder.append(String.format("[%s] ", DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate)));
1646+
if (CloningInstance == step) {
1647+
stringBuilder.append(String.format("Cloning source instance: %s on vCenter: %s / datacenter: %s", sourceVMName, vcenter, datacenter));
1648+
} else if (ConvertingInstance == step) {
1649+
stringBuilder.append(String.format("Converting the cloned VMware instance to a KVM instance on the host: %s", convertHost.getName()));
1650+
} else if (Importing == step) {
1651+
stringBuilder.append(String.format("Importing the converted KVM instance on the host: %s", importHost.getName()));
1652+
} else if (Prepare == step) {
1653+
stringBuilder.append("Preparing to convert Vmware instance");
1654+
}
16491655
}
16501656
return stringBuilder.toString();
16511657
}
@@ -1660,6 +1666,10 @@ protected void updateImportVMTaskStep(ImportVMTaskVO importVMTaskVO, DataCenter
16601666
importVMTaskVO.setStep(step);
16611667
importVMTaskVO.setDescription(description);
16621668
importVMTaskVO.setUpdated(updatedDate);
1669+
if (Completed == step) {
1670+
Duration duration = Duration.between(importVMTaskVO.getCreated().toInstant(), updatedDate.toInstant());
1671+
importVMTaskVO.setDuration(duration.toMillis());
1672+
}
16631673
importVMTaskDao.update(importVMTaskVO.getId(), importVMTaskVO);
16641674
}
16651675

@@ -1762,6 +1772,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
17621772
long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000;
17631773
logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s",
17641774
sourceVMName, instanceName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics()));
1775+
importVMTaskVO.setVmId(userVm.getId());
17651776
updateImportVMTaskStep(importVMTaskVO, zone, owner, convertHost, importHost, Completed);
17661777
importVMTaskDao.remove(importVMTaskVO.getId());
17671778
return userVm;
@@ -2925,7 +2936,16 @@ public ListResponse<ImportVMTaskResponse> listImportVMTasks(ListImportVMTasksCmd
29252936
Long accountId = cmd.getAccountId();
29262937
String vcenter = cmd.getVcenter();
29272938
Long convertHostId = cmd.getConvertHostId();
2928-
List<ImportVMTaskVO> tasks = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId);
2939+
boolean listAll = cmd.isListAll();
2940+
boolean showCompleted = cmd.isShowCompleted();
2941+
2942+
List<ImportVMTaskVO> tasks;
2943+
if (listAll) {
2944+
tasks = importVMTaskDao.listAll();
2945+
} else {
2946+
tasks = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId, showCompleted);
2947+
}
2948+
29292949
List<ImportVMTaskResponse> responses = new ArrayList<>();
29302950
for (ImportVMTaskVO task : tasks) {
29312951
responses.add(createImportVMTaskResponse(task));
@@ -2950,26 +2970,63 @@ private ImportVMTaskResponse createImportVMTaskResponse(ImportVMTaskVO task) {
29502970
response.setVcenter(task.getVcenter());
29512971
response.setDatacenterName(task.getDatacenter());
29522972
response.setSourceVMName(task.getSourceVMName());
2953-
response.setStep(task.getStep().name());
2973+
response.setDisplayName(task.getDisplayName());
2974+
response.setStep(getStepDisplayField(task.getStep()));
2975+
response.setDescription(task.getDescription());
2976+
29542977
Date updated = task.getUpdated();
2955-
if (updated != null) {
2956-
Date currentDate = new Date();
2957-
Duration duration = Duration.between(updated.toInstant(), currentDate.toInstant());
2958-
long durationSeconds = TimeUnit.SECONDS.convert(duration.toMillis(), TimeUnit.MILLISECONDS);
2959-
response.setDuration(durationSeconds);
2978+
Date currentDate = new Date();
2979+
if (updated != null && Completed != task.getStep()) {
2980+
Duration stepDuration = Duration.between(updated.toInstant(), currentDate.toInstant());
2981+
response.setStepDuration(getDurationDisplay(stepDuration.toMillis()));
2982+
}
2983+
if (Completed == task.getStep()) {
2984+
response.setStepDuration(getDurationDisplay(task.getDuration()));
2985+
} else {
2986+
Duration totalDuration = Duration.between(task.getCreated().toInstant(), currentDate.toInstant());
2987+
response.setDuration(getDurationDisplay(totalDuration.toMillis()));
29602988
}
2961-
response.setDescription(task.getDescription());
29622989
HostVO host = hostDao.findById(task.getConvertHostId());
29632990
if (host != null) {
29642991
response.setConvertInstanceHostId(host.getUuid());
29652992
response.setConvertInstanceHostName(host.getName());
29662993
}
2994+
if (task.getVmId() != null) {
2995+
UserVmVO userVm = userVmDao.findById(task.getVmId());
2996+
response.setVirtualMachineId(userVm.getUuid());
2997+
}
29672998
response.setCreated(task.getCreated());
29682999
response.setLastUpdated(task.getUpdated());
29693000
response.setObjectName("importvmtask");
29703001
return response;
29713002
}
29723003

3004+
protected String getStepDisplayField(ImportVMTaskVO.Step step) {
3005+
int totalSteps = ImportVMTaskVO.Step.values().length;
3006+
return String.format("[%s/%s] %s", step.ordinal() + 1, totalSteps, step.name());
3007+
}
3008+
3009+
protected static String getDurationDisplay(Long durationMs) {
3010+
if (durationMs == null) {
3011+
return null;
3012+
}
3013+
long hours = durationMs / (1000 * 60 * 60);
3014+
long minutes = (durationMs / (1000 * 60)) % 60;
3015+
long seconds = (durationMs / 1000) % 60;
3016+
3017+
StringBuilder result = new StringBuilder();
3018+
if (hours > 0) {
3019+
result.append(String.format("%s hs ", hours));
3020+
}
3021+
if (minutes > 0) {
3022+
result.append(String.format("%s min ", minutes));
3023+
}
3024+
if (seconds > 0) {
3025+
result.append(String.format("%s secs", seconds));
3026+
}
3027+
return result.toString();
3028+
}
3029+
29733030
private HashMap<String, UnmanagedInstanceTO> getRemoteVmsOnKVMHost(long zoneId, String remoteHostUrl, String username, String password) {
29743031
//ToDo: add option to list one Vm by name
29753032
List<HostVO> hosts = resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(Hypervisor.HypervisorType.KVM, zoneId);

server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.UUID;
3939

4040
import com.cloud.offering.DiskOffering;
41+
import com.cloud.vm.ImportVMTaskVO;
4142
import org.apache.cloudstack.api.ResponseGenerator;
4243
import org.apache.cloudstack.api.ResponseObject;
4344
import org.apache.cloudstack.api.ServerApiException;
@@ -1150,4 +1151,17 @@ public void testCheckUnmanagedDiskLimits() {
11501151
Assert.fail("Exception encountered: " + e.getMessage());
11511152
}
11521153
}
1154+
1155+
@Test
1156+
public void testStepsField() {
1157+
ImportVMTaskVO.Step step = ImportVMTaskVO.Step.ConvertingInstance;
1158+
System.out.println(step.ordinal());
1159+
System.out.println(ImportVMTaskVO.Step.values().length);
1160+
}
1161+
1162+
@Test
1163+
public void testDurationDisplay() {
1164+
long duration = 125 * 1000;
1165+
System.out.println(UnmanagedVMsManagerImpl.getDurationDisplay(duration));
1166+
}
11531167
}

0 commit comments

Comments
 (0)