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
This commit is contained in:
Nicolas Vazquez 2025-10-16 10:26:41 -03:00 committed by GitHub
parent 8b9f5fd8f9
commit e7a55a766c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 256 additions and 113 deletions

View File

@ -535,7 +535,6 @@ public class ApiConstants {
public static final String SHOW_CAPACITIES = "showcapacities";
public static final String SHOW_REMOVED = "showremoved";
public static final String SHOW_RESOURCE_ICON = "showicon";
public static final String SHOW_COMPLETED = "showcompleted";
public static final String SHOW_INACTIVE = "showinactive";
public static final String SHOW_UNIQUE = "showunique";
public static final String SIGNATURE = "signature";
@ -585,6 +584,7 @@ public class ApiConstants {
public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
public static final String TARGET_IQN = "targetiqn";
public static final String TASKS_FILTER = "tasksfilter";
public static final String TEMPLATE_FILTER = "templatefilter";
public static final String TEMPLATE_ID = "templateid";
public static final String TEMPLATE_IDS = "templateids";

View File

@ -75,11 +75,8 @@ public class ListImportVMTasksCmd extends BaseListCmd {
description = "Conversion host of the importing task")
private Long convertHostId;
@Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "Whether to list all import tasks.")
private boolean listAll = false;
@Parameter(name = ApiConstants.SHOW_COMPLETED, type = CommandType.BOOLEAN, description = "Whether to list completed tasks.")
private boolean showCompleted = false;
@Parameter(name = ApiConstants.TASKS_FILTER, type = CommandType.STRING, description = "Filter tasks by state, valid options are: All, Running, Completed, Failed")
private String tasksFilter;
public Long getZoneId() {
return zoneId;
@ -97,12 +94,8 @@ public class ListImportVMTasksCmd extends BaseListCmd {
return convertHostId;
}
public boolean isListAll() {
return listAll;
}
public boolean isShowCompleted() {
return showCompleted;
public String getTasksFilter() {
return tasksFilter;
}
@Override

View File

@ -55,6 +55,10 @@ public class ImportVMTaskResponse extends BaseResponse {
@Param(description = "the display name of the importing VM")
private String displayName;
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the importing VM task")
private String state;
@SerializedName(ApiConstants.VCENTER)
@Param(description = "the vcenter name of the importing VM task")
private String vcenter;
@ -242,4 +246,12 @@ public class ImportVMTaskResponse extends BaseResponse {
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}

View File

@ -23,6 +23,19 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface ImportVmTask extends Identity, InternalIdentity {
enum Step {
Prepare, CloningInstance, ConvertingInstance, Importing, Cleaning, Completed
Prepare, CloningInstance, ConvertingInstance, Importing, Completed
}
enum TaskState {
Running, Completed, Failed;
public static TaskState getValue(String state) {
for (TaskState s : TaskState.values()) {
if (s.name().equalsIgnoreCase(state)) {
return s;
}
}
throw new IllegalArgumentException("Invalid task state: " + state);
}
}
}

View File

@ -34,5 +34,5 @@ public interface ImportVmTasksManager {
void updateImportVMTaskStep(ImportVmTask importVMTaskVO, DataCenter zone, Account owner, Host convertHost,
Host importHost, Long vmId, ImportVmTask.Step step);
boolean removeImportVMTask(long taskId);
void updateImportVMTaskErrorState(ImportVmTask importVMTaskVO, ImportVmTask.TaskState state, String errorMsg);
}

View File

@ -93,6 +93,9 @@ public class ImportVMTaskVO implements ImportVmTask {
@Column(name = "step")
private Step step;
@Column(name = "state")
private TaskState state;
@Column(name = "description")
private String description;
@ -217,6 +220,14 @@ public class ImportVMTaskVO implements ImportVmTask {
this.step = step;
}
public TaskState getState() {
return state;
}
public void setState(TaskState state) {
this.state = state;
}
public String getDescription() {
return description;
}

View File

@ -18,12 +18,14 @@
//
package com.cloud.vm.dao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.ImportVMTaskVO;
import org.apache.cloudstack.vm.ImportVmTask;
import java.util.List;
public interface ImportVMTaskDao extends GenericDao<ImportVMTaskVO, Long> {
List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted);
Pair<List<ImportVMTaskVO>, Integer> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId,
ImportVmTask.TaskState state, Long startIndex, Long pageSizeVal);
}

View File

@ -16,10 +16,13 @@
// under the License.
package com.cloud.vm.dao;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.vm.ImportVMTaskVO;
import org.apache.cloudstack.vm.ImportVmTask;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@ -41,12 +44,14 @@ public class ImportVMTaskDaoImpl extends GenericDaoBase<ImportVMTaskVO, Long> im
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("vcenter", AllFieldsSearch.entity().getVcenter(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("convertHostId", AllFieldsSearch.entity().getConvertHostId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.done();
}
@Override
public List<ImportVMTaskVO> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId, boolean showCompleted) {
public Pair<List<ImportVMTaskVO>, Integer> listImportVMTasks(Long zoneId, Long accountId, String vcenter, Long convertHostId,
ImportVmTask.TaskState state, Long startIndex, Long pageSizeVal) {
SearchCriteria<ImportVMTaskVO> sc = AllFieldsSearch.create();
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
@ -60,6 +65,10 @@ public class ImportVMTaskDaoImpl extends GenericDaoBase<ImportVMTaskVO, Long> im
if (convertHostId != null) {
sc.setParameters("convertHostId", convertHostId);
}
return showCompleted ? listIncludingRemovedBy(sc) : listBy(sc);
if (state != null) {
sc.setParameters("state", state);
}
Filter filter = new Filter(ImportVMTaskVO.class, "created", false, startIndex, pageSizeVal);
return searchAndCount(sc, filter);
}
}

View File

@ -65,7 +65,8 @@ CREATE TABLE IF NOT EXISTS `cloud`.`import_vm_task`(
`source_vm_name` varchar(255) COMMENT 'Source VM name on vCenter',
`convert_host_id` bigint unsigned COMMENT 'Convert Host ID',
`import_host_id` bigint unsigned COMMENT 'Import Host ID',
`step` varchar(20) NOT NULL COMMENT 'Importing VM Task Step',
`step` varchar(20) COMMENT 'Importing VM Task Step',
`state` varchar(20) COMMENT 'Importing VM Task State',
`description` varchar(255) COMMENT 'Importing VM Task Description',
`duration` bigint unsigned COMMENT 'Duration in milliseconds for the completed tasks',
`created` datetime NOT NULL COMMENT 'date created',

View File

@ -25,13 +25,17 @@ import com.cloud.host.dao.HostDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.vm.ImportVMTaskVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.dao.ImportVMTaskDao;
import com.cloud.vm.dao.UserVmDao;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd;
import org.apache.cloudstack.api.response.ImportVMTaskResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -72,25 +76,33 @@ public class ImportVmTasksManagerImpl implements ImportVmTasksManager {
Long accountId = cmd.getAccountId();
String vcenter = cmd.getVcenter();
Long convertHostId = cmd.getConvertHostId();
boolean listAll = cmd.isListAll();
boolean showCompleted = cmd.isShowCompleted();
Long startIndex = cmd.getStartIndex();
Long pageSizeVal = cmd.getPageSizeVal();
List<ImportVMTaskVO> tasks;
if (listAll) {
tasks = importVMTaskDao.listAll();
} else {
tasks = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId, showCompleted);
}
ImportVmTask.TaskState state = getStateFromFilter(cmd.getTasksFilter());
Pair<List<ImportVMTaskVO>, Integer> result = importVMTaskDao.listImportVMTasks(zoneId, accountId, vcenter, convertHostId, state, startIndex, pageSizeVal);
List<ImportVMTaskVO> tasks = result.first();
List<ImportVMTaskResponse> responses = new ArrayList<>();
for (ImportVMTaskVO task : tasks) {
responses.add(createImportVMTaskResponse(task));
}
ListResponse<ImportVMTaskResponse> listResponses = new ListResponse<>();
listResponses.setResponses(responses, responses.size());
listResponses.setResponses(responses, result.second());
return listResponses;
}
private ImportVmTask.TaskState getStateFromFilter(String tasksFilter) {
if (StringUtils.isBlank(tasksFilter) || tasksFilter.equalsIgnoreCase("all")) {
return null;
}
try {
return ImportVmTask.TaskState.getValue(tasksFilter);
} catch (IllegalArgumentException e) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Invalid value for task state: %s", tasksFilter));
}
}
@Override
public ImportVmTask createImportVMTaskRecord(DataCenter zone, Account owner, long userId, String displayName, String vcenter, String datacenterName, String sourceVMName, Host convertHost, Host importHost) {
logger.debug("Creating import VM task entry for VM: {} for account {} on zone {} " +
@ -98,6 +110,7 @@ public class ImportVmTasksManagerImpl implements ImportVmTasksManager {
sourceVMName, owner.getAccountName(), zone.getName(), displayName, vcenter, datacenterName);
ImportVMTaskVO importVMTaskVO = new ImportVMTaskVO(zone.getId(), owner.getAccountId(), userId, displayName,
vcenter, datacenterName, sourceVMName, convertHost.getId(), importHost.getId());
importVMTaskVO.setState(ImportVmTask.TaskState.Running);
return importVMTaskDao.persist(importVMTaskVO);
}
@ -111,7 +124,6 @@ public class ImportVmTasksManagerImpl implements ImportVmTasksManager {
if (Completed == step) {
stringBuilder.append("Completed at ").append(DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate));
} else {
stringBuilder.append(String.format("[%s] ", DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), updatedDate)));
if (CloningInstance == step) {
stringBuilder.append(String.format("Cloning source instance: %s on vCenter: %s / datacenter: %s", sourceVMName, vcenter, datacenter));
} else if (ConvertingInstance == step) {
@ -142,13 +154,19 @@ public class ImportVmTasksManagerImpl implements ImportVmTasksManager {
Duration duration = Duration.between(importVMTaskVO.getCreated().toInstant(), updatedDate.toInstant());
importVMTaskVO.setDuration(duration.toMillis());
importVMTaskVO.setVmId(vmId);
importVMTaskVO.setState(ImportVmTask.TaskState.Completed);
}
importVMTaskDao.update(importVMTaskVO.getId(), importVMTaskVO);
}
@Override
public boolean removeImportVMTask(long taskId) {
return importVMTaskDao.remove(taskId);
public void updateImportVMTaskErrorState(ImportVmTask importVMTask, ImportVmTask.TaskState state, String errorMsg) {
ImportVMTaskVO importVMTaskVO = (ImportVMTaskVO) importVMTask;
Date updatedDate = DateUtil.now();
importVMTaskVO.setUpdated(updatedDate);
importVMTaskVO.setState(state);
importVMTaskVO.setDescription(errorMsg);
importVMTaskDao.update(importVMTaskVO.getId(), importVMTaskVO);
}
private ImportVMTaskResponse createImportVMTaskResponse(ImportVMTaskVO task) {
@ -169,19 +187,21 @@ public class ImportVmTasksManagerImpl implements ImportVmTasksManager {
response.setDisplayName(task.getDisplayName());
response.setStep(getStepDisplayField(task.getStep()));
response.setDescription(task.getDescription());
response.setState(task.getState().name());
Date updated = task.getUpdated();
Date currentDate = new Date();
if (updated != null && Completed != task.getStep()) {
Duration stepDuration = Duration.between(updated.toInstant(), currentDate.toInstant());
response.setStepDuration(getDurationDisplay(stepDuration.toMillis()));
}
if (Completed == task.getStep()) {
response.setStepDuration(getDurationDisplay(task.getDuration()));
} else {
Duration totalDuration = Duration.between(task.getCreated().toInstant(), currentDate.toInstant());
response.setDuration(getDurationDisplay(totalDuration.toMillis()));
if (updated != null) {
if (ImportVmTask.TaskState.Running == task.getState()) {
Duration stepDuration = Duration.between(updated.toInstant(), currentDate.toInstant());
response.setStepDuration(getDurationDisplay(stepDuration.toMillis()));
} else {
Duration totalDuration = Duration.between(task.getCreated().toInstant(), updated.toInstant());
response.setDuration(getDurationDisplay(totalDuration.toMillis()));
}
}
HostVO host = hostDao.findById(task.getConvertHostId());
if (host != null) {
response.setConvertInstanceHostId(host.getUuid());

View File

@ -1776,10 +1776,10 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
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",
sourceVMName, displayName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics()));
importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, userVm.getId(), Completed);
importVmTasksManager.removeImportVMTask(importVMTask.getId());
return userVm;
} catch (CloudRuntimeException e) {
logger.error(String.format("Error importing VM: %s", e.getMessage()), e);
importVmTasksManager.updateImportVMTaskErrorState(importVMTask, ImportVmTask.TaskState.Failed, e.getMessage());
ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT,
cmd.getEventDescription(), null, null, 0);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());

View File

@ -782,7 +782,6 @@ public class UnmanagedVMsManagerImplTest {
when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer);
}
when(importVMTaskVO.getId()).thenReturn(1L);
when(importVmTasksManager.createImportVMTaskRecord(any(DataCenter.class), any(Account.class), anyLong(), anyString(),
anyString(), anyString(), anyString(), any(Host.class), any(Host.class))).thenReturn(importVMTaskVO);
when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true);

View File

@ -635,6 +635,7 @@
"label.continue": "Continue",
"label.continue.install": "Continue with installation",
"label.controlnodes": "Control nodes",
"label.conversionhost": "Conversion Host",
"label.copied.clipboard": "Copied to clipboard",
"label.copy": "Copy",
"label.copy.clipboard": "Copy to clipboard",
@ -700,6 +701,8 @@
"label.csienabled": "CSI Enabled",
"label.currency": "Currency",
"label.current": "Current",
"label.currentstep": "Current step",
"label.currentstep.duration": "Current step duration",
"label.current.storage": "Current storage",
"label.currentpassword": "Current password",
"label.custom": "Custom",
@ -1246,6 +1249,7 @@
"label.import.instance": "Import Instance",
"label.import.offering": "Import Offering",
"label.import.role": "Import Role",
"label.import.vm.tasks": "Import VM Tasks",
"label.import.volume": "Import Volume",
"label.inactive": "Inactive",
"label.inbuilt": "Inbuilt",
@ -2314,6 +2318,7 @@
"label.sourcenattype": "Supported source NAT type",
"label.sourceport": "Source port",
"label.sourcetype": "Source type",
"label.sourcevmname": "Source VM Name",
"label.specifyasnumber": "Specify AS Number",
"label.specifyipranges": "Specify IP ranges",
"label.specifyvlan": "Specify VLAN",
@ -2881,6 +2886,7 @@
"label.leaseexpiryaction": "Lease expiry action",
"label.remainingdays": "Lease",
"label.leased": "Leased",
"label.totalduration": "Total duration",
"label.usestoragereplication": "Use primary storage replication",
"message.acquire.ip.failed": "Failed to acquire IP.",
"message.action.acquire.ip": "Please confirm that you want to acquire new IP.",
@ -3524,6 +3530,7 @@
"message.host.dedication.released": "Host dedication released.",
"message.host.external.datadisk": "Usage of data disks for the selected template is not applicable",
"message.import.running.instance.warning": "The selected VM is powered-on on the VMware Datacenter. The recommended state to convert a VMware VM into KVM is powered-off after a graceful shutdown of the guest OS.",
"message.import.vm.tasks": "Import from VMware to KVM tasks",
"message.import.volume": "Please specify the domain, account or project name. <br>If not set, the volume will be imported for the caller.",
"message.info.cloudian.console": "Cloudian Management Console should open in another window.",
"message.installwizard.cloudstack.helptext.website": " * Project website:\t ",

View File

@ -16,56 +16,83 @@
// under the License.
<template>
<a-card class="instances-card">
<template #title>
Import VM Tasks
<a-tooltip :title="'Running Import VM Tasks'">
<info-circle-outlined />
</a-tooltip>
<a-button
style="margin-left: 12px; margin-top: 4px"
:loading="loading"
size="small"
shape="round"
@click="fetchData()">
<template #icon><reload-outlined /></template>
</a-button>
<a-select
:placeholder="$t('label.filterby')"
:value="importVmTasksFilterValue"
style="min-width: 100px; margin-left: 10px; margin-bottom: 5px"
size=small
@change="onFilterChange"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
>
<template #suffixIcon><filter-outlined class="ant-select-suffix" /></template>
<a-select-option
v-for="filter in filters"
:key="filter"
:label="$t('label.' + filter)"
>
{{ $t('label.' + filter) }}
</a-select-option>
</a-select>
</template>
<a-table
:data-source="tasks"
:columns="columns">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'convertinstancehostid'">
<router-link :to="{ path: '/host/' + record.convertinstancehostid }">{{ record.convertinstancehostname }}</router-link>
</template>
<template v-else-if="column.key === 'displayname'">
<router-link v-if="record.virtualmachineid" :to="{ path: '/vm/' + record.virtualmachineid }">{{ record.displayname }}</router-link>
<span v-else>{{ record.displayname }}</span>
</template>
<a-row :gutter="12">
<a-col :md="24" :lg="24">
<a-card class="instances-card">
<template #title>
{{ $t('label.import.vm.tasks') }}
<a-tooltip :title="$t('message.import.vm.tasks')">
<info-circle-outlined />
</a-tooltip>
<a-button
style="margin-left: 12px; margin-top: 4px"
:loading="loading"
size="small"
shape="round"
@click="this.$emit('fetch-import-vm-tasks')" >
<template #icon><reload-outlined /></template>
</a-button>
<span style="float: right; width: 50%">
<a-select
:placeholder="$t('label.filterby')"
:value="filter"
style="min-width: 100px; margin-left: 10px; margin-bottom: 5px"
size=small
@change="onFilterChange"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
>
<template #suffixIcon><filter-outlined class="ant-select-suffix" /></template>
<a-select-option
v-for="filter in filters"
:key="filter"
:label="$t('label.' + filter)"
>
{{ $t('label.' + filter) }}
</a-select-option>
</a-select>
</span>
</template>
</a-table>
</a-card>
<a-table
:data-source="tasks"
class="instances-card-table"
size="middle"
:pagination="false"
:columns="columns">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'convertinstancehostid'">
<router-link :to="{ path: '/host/' + record.convertinstancehostid }">{{ record.convertinstancehostname }}</router-link>
</template>
<template v-else-if="column.key === 'displayname'">
<router-link v-if="record.virtualmachineid" :to="{ path: '/vm/' + record.virtualmachineid }">{{ record.displayname }}</router-link>
<span v-else>{{ record.displayname }}</span>
</template>
<template v-else-if="column.key === 'created'">
<span>{{ $toLocaleDate(record.created) }}</span>
</template>
</template>
</a-table>
<div class="instances-card-footer">
<a-pagination
class="row-element"
size="small"
:current="page"
:pageSize="pageSize"
:total="total"
:showTotal="total => `${$t('label.showing')} ${Math.min(total, 1+((page-1)*pageSize))}-${Math.min(page*pageSize, total)} ${$t('label.of')} ${total} ${$t('label.items')}`"
@change="onPaginationChange"
showQuickJumper>
<template #buildOptionText="props">
<span>{{ props.value }} / {{ $t('label.page') }}</span>
</template>
</a-pagination>
</div>
</a-card>
</a-col>
</a-row>
</template>
<script>
@ -81,69 +108,97 @@ export default {
loading: {
type: Boolean,
required: false
},
filter: {
type: String,
required: false
},
total: {
type: Number,
required: true
},
page: {
type: Number,
required: true
},
pageSize: {
type: Number,
required: true
}
},
data () {
const columns = [
{
key: 'created',
title: this.$t('label.created'),
dataIndex: 'created'
},
{
key: 'displayname',
title: 'VM Display Name',
title: this.$t('label.displayname'),
dataIndex: 'displayname'
},
{
key: 'convertinstancehostid',
title: 'Conversion Host',
title: this.$t('label.conversionhost'),
dataIndex: 'convertinstancehostid'
},
{
key: 'step',
title: 'Current Step',
title: this.$t('label.currentstep'),
dataIndex: 'step'
},
{
key: 'stepduration',
title: 'Current Step Duration',
title: this.$t('label.currentstep.duration'),
dataIndex: 'stepduration'
},
{
key: 'description',
title: 'Description',
title: this.$t('label.description'),
dataIndex: 'description'
},
{
key: 'duration',
title: 'Total Duration',
title: this.$t('label.totalduration'),
dataIndex: 'duration'
},
{
key: 'sourcevmname',
title: 'Source VM Name',
title: this.$t('label.sourcevmname'),
dataIndex: 'sourcevmname'
},
{
key: 'vcenter',
title: 'vCenter',
title: this.$t('label.vcenter'),
dataIndex: 'vcenter'
},
{
key: 'datacentername',
title: 'Datacenter Name',
title: this.$t('label.vcenter.datacenter'),
dataIndex: 'datacentername'
},
{
key: 'state',
title: this.$t('label.state'),
dataIndex: 'state'
}
]
return {
columns,
filters: ['running', 'completed'],
filters: ['all', 'running', 'completed', 'failed'],
filterValue: 'running'
}
},
methods: {
fetchData () {
this.$emit('fetch-import-vm-tasks', this.filterValue)
this.$emit('fetch-import-vm-tasks')
},
onFilterChange (e) {
this.filterValue = e
this.fetchData()
this.$emit('change-filter', e)
},
onPaginationChange (page, size) {
this.$emit('change-pagination', page, size)
}
}
}

View File

@ -497,11 +497,17 @@
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane :key=2 tab="Import VM Tasks" v-if="isMigrateFromVmware">
<a-tab-pane :key=2 :tab="$t('label.import.vm.tasks')" v-if="isMigrateFromVmware">
<ImportVmTasks
:tasks="importVmTasks"
:loading="loadingImportVmTasks"
:filter="importVmTasksFilter"
:total="itemCount.tasks || 0"
:page="page.tasks"
:pageSize="pageSize.tasks"
@fetch-import-vm-tasks="fetchImportVmTasks"
@change-pagination="onChangeImportTasksPagination"
@change-filter="onChangeImportTasksFilter"
/>
</a-tab-pane>
</a-tabs>
@ -704,11 +710,13 @@ export default {
},
page: {
unmanaged: 1,
managed: 1
managed: 1,
tasks: 1
},
pageSize: {
unmanaged: 10,
managed: 10
managed: 10,
tasks: 10
},
searchFilters: {
unmanaged: [],
@ -765,12 +773,14 @@ export default {
selectedVmwareVcenter: undefined,
activeTabKey: 1,
loadingImportVmTasks: false,
importVmTasks: []
importVmTasks: [],
importVmTasksFilter: 'running'
}
},
created () {
this.page.unmanaged = parseInt(this.$route.query.unmanagedpage || 1)
this.page.managed = parseInt(this.$route.query.managedpage || 1)
this.page.tasks = parseInt(this.$route.query.tasks || 1)
this.initForm()
this.fetchData()
},
@ -1102,6 +1112,7 @@ export default {
this.page.managed = 1
this.managedInstances = []
this.managedInstancesSelectedRowKeys = []
this.page.tasks = 1
this.activeTabKey = 1
},
onSelectHypervisor (value) {
@ -1178,15 +1189,25 @@ export default {
this.fetchImportVmTasks()
}
},
fetchImportVmTasks (filter) {
onChangeImportTasksPagination (page, pagesize) {
this.page.tasks = page
this.pageSize.tasks = pagesize
this.fetchImportVmTasks()
},
onChangeImportTasksFilter (filter) {
this.importVmTasksFilter = filter
this.fetchImportVmTasks()
},
fetchImportVmTasks () {
this.loadingImportVmTasks = true
const params = {
zoneid: this.zoneId
}
if (filter && filter === 'completed') {
params.showcompleted = true
zoneid: this.zoneId,
page: this.page.tasks,
pagesize: this.pageSize.tasks,
tasksfilter: this.importVmTasksFilter
}
getAPI('listImportVmTasks', params).then(response => {
this.itemCount.tasks = response.listimportvmtasksresponse.count
this.importVmTasks = response.listimportvmtasksresponse.importvmtask || []
}).catch(error => {
this.$notifyError(error)