Skip to content

Commit e7a55a7

Browse files
authored
Fixes for Import VM Tasks listing (#11841)
* Fix import VM tasks pagination * Fix UI for pagination and proper listing * Fixes and improvements * Polish UI * Restore config.json * Fix state on parameter description
1 parent 8b9f5fd commit e7a55a7

File tree

15 files changed

+256
-113
lines changed

15 files changed

+256
-113
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,6 @@ public class ApiConstants {
535535
public static final String SHOW_CAPACITIES = "showcapacities";
536536
public static final String SHOW_REMOVED = "showremoved";
537537
public static final String SHOW_RESOURCE_ICON = "showicon";
538-
public static final String SHOW_COMPLETED = "showcompleted";
539538
public static final String SHOW_INACTIVE = "showinactive";
540539
public static final String SHOW_UNIQUE = "showunique";
541540
public static final String SIGNATURE = "signature";
@@ -585,6 +584,7 @@ public class ApiConstants {
585584
public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine";
586585
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
587586
public static final String TARGET_IQN = "targetiqn";
587+
public static final String TASKS_FILTER = "tasksfilter";
588588
public static final String TEMPLATE_FILTER = "templatefilter";
589589
public static final String TEMPLATE_ID = "templateid";
590590
public static final String TEMPLATE_IDS = "templateids";

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

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,8 @@ 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;
78+
@Parameter(name = ApiConstants.TASKS_FILTER, type = CommandType.STRING, description = "Filter tasks by state, valid options are: All, Running, Completed, Failed")
79+
private String tasksFilter;
8380

8481
public Long getZoneId() {
8582
return zoneId;
@@ -97,12 +94,8 @@ public Long getConvertHostId() {
9794
return convertHostId;
9895
}
9996

100-
public boolean isListAll() {
101-
return listAll;
102-
}
103-
104-
public boolean isShowCompleted() {
105-
return showCompleted;
97+
public String getTasksFilter() {
98+
return tasksFilter;
10699
}
107100

108101
@Override

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public class ImportVMTaskResponse extends BaseResponse {
5555
@Param(description = "the display name of the importing VM")
5656
private String displayName;
5757

58+
@SerializedName(ApiConstants.STATE)
59+
@Param(description = "the state of the importing VM task")
60+
private String state;
61+
5862
@SerializedName(ApiConstants.VCENTER)
5963
@Param(description = "the vcenter name of the importing VM task")
6064
private String vcenter;
@@ -242,4 +246,12 @@ public Date getLastUpdated() {
242246
public void setLastUpdated(Date lastUpdated) {
243247
this.lastUpdated = lastUpdated;
244248
}
249+
250+
public String getState() {
251+
return state;
252+
}
253+
254+
public void setState(String state) {
255+
this.state = state;
256+
}
245257
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@
2323

2424
public interface ImportVmTask extends Identity, InternalIdentity {
2525
enum Step {
26-
Prepare, CloningInstance, ConvertingInstance, Importing, Cleaning, Completed
26+
Prepare, CloningInstance, ConvertingInstance, Importing, Completed
27+
}
28+
29+
enum TaskState {
30+
Running, Completed, Failed;
31+
32+
public static TaskState getValue(String state) {
33+
for (TaskState s : TaskState.values()) {
34+
if (s.name().equalsIgnoreCase(state)) {
35+
return s;
36+
}
37+
}
38+
throw new IllegalArgumentException("Invalid task state: " + state);
39+
}
2740
}
2841
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ ImportVmTask createImportVMTaskRecord(DataCenter zone, Account owner, long userI
3434
void updateImportVMTaskStep(ImportVmTask importVMTaskVO, DataCenter zone, Account owner, Host convertHost,
3535
Host importHost, Long vmId, ImportVmTask.Step step);
3636

37-
boolean removeImportVMTask(long taskId);
37+
void updateImportVMTaskErrorState(ImportVmTask importVMTaskVO, ImportVmTask.TaskState state, String errorMsg);
3838
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ public ImportVMTaskVO() {
9393
@Column(name = "step")
9494
private Step step;
9595

96+
@Column(name = "state")
97+
private TaskState state;
98+
9699
@Column(name = "description")
97100
private String description;
98101

@@ -217,6 +220,14 @@ public void setStep(Step step) {
217220
this.step = step;
218221
}
219222

223+
public TaskState getState() {
224+
return state;
225+
}
226+
227+
public void setState(TaskState state) {
228+
this.state = state;
229+
}
230+
220231
public String getDescription() {
221232
return description;
222233
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
//
1919
package com.cloud.vm.dao;
2020

21+
import com.cloud.utils.Pair;
2122
import com.cloud.utils.db.GenericDao;
2223
import com.cloud.vm.ImportVMTaskVO;
23-
24+
import org.apache.cloudstack.vm.ImportVmTask;
2425
import java.util.List;
2526

2627
public interface ImportVMTaskDao extends GenericDao<ImportVMTaskVO, Long> {
2728

28-
List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted);
29+
Pair<List<ImportVMTaskVO>, Integer> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId,
30+
ImportVmTask.TaskState state, Long startIndex, Long pageSizeVal);
2931
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
// under the License.
1717
package com.cloud.vm.dao;
1818

19+
import com.cloud.utils.Pair;
20+
import com.cloud.utils.db.Filter;
1921
import com.cloud.utils.db.GenericDaoBase;
2022
import com.cloud.utils.db.SearchBuilder;
2123
import com.cloud.utils.db.SearchCriteria;
2224
import com.cloud.vm.ImportVMTaskVO;
25+
import org.apache.cloudstack.vm.ImportVmTask;
2326
import org.apache.commons.lang3.StringUtils;
2427
import org.springframework.stereotype.Component;
2528

@@ -41,12 +44,14 @@ void init() {
4144
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
4245
AllFieldsSearch.and("vcenter", AllFieldsSearch.entity().getVcenter(), SearchCriteria.Op.EQ);
4346
AllFieldsSearch.and("convertHostId", AllFieldsSearch.entity().getConvertHostId(), SearchCriteria.Op.EQ);
47+
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
4448
AllFieldsSearch.done();
4549
}
4650

4751

4852
@Override
49-
public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted) {
53+
public Pair<List<ImportVMTaskVO>, Integer> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId,
54+
ImportVmTask.TaskState state, Long startIndex, Long pageSizeVal) {
5055
SearchCriteria<ImportVMTaskVO> sc = AllFieldsSearch.create();
5156
if (zoneId != null) {
5257
sc.setParameters("zoneId", zoneId);
@@ -60,6 +65,10 @@ public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, Strin
6065
if (convertHostId != null) {
6166
sc.setParameters("convertHostId", convertHostId);
6267
}
63-
return showCompleted ? listIncludingRemovedBy(sc) : listBy(sc);
68+
if (state != null) {
69+
sc.setParameters("state", state);
70+
}
71+
Filter filter = new Filter(ImportVMTaskVO.class, "created", false, startIndex, pageSizeVal);
72+
return searchAndCount(sc, filter);
6473
}
6574
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ CREATE TABLE IF NOT EXISTS `cloud`.`import_vm_task`(
6565
`source_vm_name` varchar(255) COMMENT 'Source VM name on vCenter',
6666
`convert_host_id` bigint unsigned COMMENT 'Convert Host ID',
6767
`import_host_id` bigint unsigned COMMENT 'Import Host ID',
68-
`step` varchar(20) NOT NULL COMMENT 'Importing VM Task Step',
68+
`step` varchar(20) COMMENT 'Importing VM Task Step',
69+
`state` varchar(20) COMMENT 'Importing VM Task State',
6970
`description` varchar(255) COMMENT 'Importing VM Task Description',
7071
`duration` bigint unsigned COMMENT 'Duration in milliseconds for the completed tasks',
7172
`created` datetime NOT NULL COMMENT 'date created',

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

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@
2525
import com.cloud.user.Account;
2626
import com.cloud.user.AccountService;
2727
import com.cloud.utils.DateUtil;
28+
import com.cloud.utils.Pair;
2829
import com.cloud.vm.ImportVMTaskVO;
2930
import com.cloud.vm.UserVmVO;
3031
import com.cloud.vm.dao.ImportVMTaskDao;
3132
import com.cloud.vm.dao.UserVmDao;
33+
import org.apache.cloudstack.api.ApiErrorCode;
34+
import org.apache.cloudstack.api.ServerApiException;
3235
import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd;
3336
import org.apache.cloudstack.api.response.ImportVMTaskResponse;
3437
import org.apache.cloudstack.api.response.ListResponse;
38+
import org.apache.commons.lang3.StringUtils;
3539
import org.apache.logging.log4j.LogManager;
3640
import org.apache.logging.log4j.Logger;
3741

@@ -72,32 +76,41 @@ public ListResponse<ImportVMTaskResponse> listImportVMTasks(ListImportVMTasksCmd
7276
Long accountId = cmd.getAccountId();
7377
String vcenter = cmd.getVcenter();
7478
Long convertHostId = cmd.getConvertHostId();
75-
boolean listAll = cmd.isListAll();
76-
boolean showCompleted = cmd.isShowCompleted();
79+
Long startIndex = cmd.getStartIndex();
80+
Long pageSizeVal = cmd.getPageSizeVal();
7781

78-
List<ImportVMTaskVO> tasks;
79-
if (listAll) {
80-
tasks = importVMTaskDao.listAll();
81-
} else {
82-
tasks = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId, showCompleted);
83-
}
82+
ImportVmTask.TaskState state = getStateFromFilter(cmd.getTasksFilter());
83+
Pair<List<ImportVMTaskVO>, Integer> result = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId, state, startIndex, pageSizeVal);
84+
List<ImportVMTaskVO> tasks = result.first();
8485

8586
List<ImportVMTaskResponse> responses = new ArrayList<>();
8687
for (ImportVMTaskVO task : tasks) {
8788
responses.add(createImportVMTaskResponse(task));
8889
}
8990
ListResponse<ImportVMTaskResponse> listResponses = new ListResponse<>();
90-
listResponses.setResponses(responses, responses.size());
91+
listResponses.setResponses(responses, result.second());
9192
return listResponses;
9293
}
9394

95+
private ImportVmTask.TaskState getStateFromFilter(String tasksFilter) {
96+
if (StringUtils.isBlank(tasksFilter) || tasksFilter.equalsIgnoreCase("all")) {
97+
return null;
98+
}
99+
try {
100+
return ImportVmTask.TaskState.getValue(tasksFilter);
101+
} catch (IllegalArgumentException e) {
102+
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Invalid value for task state: %s", tasksFilter));
103+
}
104+
}
105+
94106
@Override
95107
public ImportVmTask createImportVMTaskRecord(DataCenter zone, Account owner, long userId, String displayName, String vcenter, String datacenterName, String sourceVMName, Host convertHost, Host importHost) {
96108
logger.debug("Creating import VM task entry for VM: {} for account {} on zone {} " +
97109
"from the vCenter: {} / datacenter: {} / source VM: {}",
98110
sourceVMName, owner.getAccountName(), zone.getName(), displayName, vcenter, datacenterName);
99111
ImportVMTaskVO importVMTaskVO = new ImportVMTaskVO(zone.getId(), owner.getAccountId(), userId, displayName,
100112
vcenter, datacenterName, sourceVMName, convertHost.getId(), importHost.getId());
113+
importVMTaskVO.setState(ImportVmTask.TaskState.Running);
101114
return importVMTaskDao.persist(importVMTaskVO);
102115
}
103116

@@ -111,7 +124,6 @@ private String getStepDescription(ImportVMTaskVO importVMTaskVO, Host convertHos
111124
if (Completed == step) {
112125
stringBuilder.append("Completed at ").append(DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate));
113126
} else {
114-
stringBuilder.append(String.format("[%s] ", DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate)));
115127
if (CloningInstance == step) {
116128
stringBuilder.append(String.format("Cloning source instance: %s on vCenter: %s / datacenter: %s", sourceVMName, vcenter, datacenter));
117129
} else if (ConvertingInstance == step) {
@@ -142,13 +154,19 @@ public void updateImportVMTaskStep(ImportVmTask importVMTask, DataCenter zone, A
142154
Duration duration = Duration.between(importVMTaskVO.getCreated().toInstant(), updatedDate.toInstant());
143155
importVMTaskVO.setDuration(duration.toMillis());
144156
importVMTaskVO.setVmId(vmId);
157+
importVMTaskVO.setState(ImportVmTask.TaskState.Completed);
145158
}
146159
importVMTaskDao.update(importVMTaskVO.getId(), importVMTaskVO);
147160
}
148161

149162
@Override
150-
public boolean removeImportVMTask(long taskId) {
151-
return importVMTaskDao.remove(taskId);
163+
public void updateImportVMTaskErrorState(ImportVmTask importVMTask, ImportVmTask.TaskState state, String errorMsg) {
164+
ImportVMTaskVO importVMTaskVO = (ImportVMTaskVO) importVMTask;
165+
Date updatedDate = DateUtil.now();
166+
importVMTaskVO.setUpdated(updatedDate);
167+
importVMTaskVO.setState(state);
168+
importVMTaskVO.setDescription(errorMsg);
169+
importVMTaskDao.update(importVMTaskVO.getId(), importVMTaskVO);
152170
}
153171

154172
private ImportVMTaskResponse createImportVMTaskResponse(ImportVMTaskVO task) {
@@ -169,19 +187,21 @@ private ImportVMTaskResponse createImportVMTaskResponse(ImportVMTaskVO task) {
169187
response.setDisplayName(task.getDisplayName());
170188
response.setStep(getStepDisplayField(task.getStep()));
171189
response.setDescription(task.getDescription());
190+
response.setState(task.getState().name());
172191

173192
Date updated = task.getUpdated();
174193
Date currentDate = new Date();
175-
if (updated != null && Completed != task.getStep()) {
176-
Duration stepDuration = Duration.between(updated.toInstant(), currentDate.toInstant());
177-
response.setStepDuration(getDurationDisplay(stepDuration.toMillis()));
178-
}
179-
if (Completed == task.getStep()) {
180-
response.setStepDuration(getDurationDisplay(task.getDuration()));
181-
} else {
182-
Duration totalDuration = Duration.between(task.getCreated().toInstant(), currentDate.toInstant());
183-
response.setDuration(getDurationDisplay(totalDuration.toMillis()));
194+
195+
if (updated != null) {
196+
if (ImportVmTask.TaskState.Running == task.getState()) {
197+
Duration stepDuration = Duration.between(updated.toInstant(), currentDate.toInstant());
198+
response.setStepDuration(getDurationDisplay(stepDuration.toMillis()));
199+
} else {
200+
Duration totalDuration = Duration.between(task.getCreated().toInstant(), updated.toInstant());
201+
response.setDuration(getDurationDisplay(totalDuration.toMillis()));
202+
}
184203
}
204+
185205
HostVO host = hostDao.findById(task.getConvertHostId());
186206
if (host != null) {
187207
response.setConvertInstanceHostId(host.getUuid());

0 commit comments

Comments
 (0)