diff --git a/pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue b/pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue
index 75d7ab5c..fed7b2fa 100644
--- a/pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue
+++ b/pkg/harvester/components/vm-migration/ConfigureMappingsStep.vue
@@ -126,6 +126,10 @@ const applyStorageMapTargets = (mapSpec, { markOverridden = false, captureInheri
if (match?.destination?.storageClass) {
entry.target = match.destination.storageClass;
+ if (captureInherited) {
+ entry.inheritedFromProvider = true;
+ }
+
if (match.destination.volumeMode) {
entry.volumeMode = match.destination.volumeMode;
@@ -252,18 +256,19 @@ const buildStorageEntries = () => {
if (ds && ds.id) {
if (!datastoreMap[ds.id]) {
datastoreMap[ds.id] = {
- name: ds.name || t('harvester.addons.vmMigration.generic.unknown'),
- id: ds.id,
- type: ds.type || '',
- capacity: 0,
- target: '',
- volumeMode: DEFAULT_VOLUME_MODE,
- accessModes: [...DEFAULT_ACCESS_MODES],
- inheritedVolumeMode: DEFAULT_VOLUME_MODE,
- inheritedAccessModes: [...DEFAULT_ACCESS_MODES],
- overridden: false,
- usedBy: [],
- _key: `stor-${ ds.id }`,
+ name: ds.name || t('harvester.addons.vmMigration.generic.unknown'),
+ id: ds.id,
+ type: ds.type || '',
+ capacity: 0,
+ target: '',
+ volumeMode: DEFAULT_VOLUME_MODE,
+ accessModes: [...DEFAULT_ACCESS_MODES],
+ inheritedVolumeMode: DEFAULT_VOLUME_MODE,
+ inheritedAccessModes: [...DEFAULT_ACCESS_MODES],
+ inheritedFromProvider: false,
+ overridden: false,
+ usedBy: [],
+ _key: `stor-${ ds.id }`,
};
}
@@ -293,18 +298,19 @@ const buildNetworkEntriesFromProvider = (networksData) => {
const buildStorageEntriesFromProvider = (datastoresData) => {
storageEntries.value = (Array.isArray(datastoresData) ? datastoresData : []).map((ds) => ({
- name: ds.name || ds.id,
- id: ds.id || '',
- type: ds.type || '',
- capacity: ds.capacity || 0,
- target: '',
- volumeMode: DEFAULT_VOLUME_MODE,
- accessModes: [...DEFAULT_ACCESS_MODES],
- inheritedVolumeMode: DEFAULT_VOLUME_MODE,
- inheritedAccessModes: [...DEFAULT_ACCESS_MODES],
- overridden: false,
- usedBy: [],
- _key: `stor-${ ds.id || ds.name }`,
+ name: ds.name || ds.id,
+ id: ds.id || '',
+ type: ds.type || '',
+ capacity: ds.capacity || 0,
+ target: '',
+ volumeMode: DEFAULT_VOLUME_MODE,
+ accessModes: [...DEFAULT_ACCESS_MODES],
+ inheritedVolumeMode: DEFAULT_VOLUME_MODE,
+ inheritedAccessModes: [...DEFAULT_ACCESS_MODES],
+ inheritedFromProvider: false,
+ overridden: false,
+ usedBy: [],
+ _key: `stor-${ ds.id || ds.name }`,
}));
};
diff --git a/pkg/harvester/components/vm-migration/MappingColumn.vue b/pkg/harvester/components/vm-migration/MappingColumn.vue
index f234121d..e7d83749 100644
--- a/pkg/harvester/components/vm-migration/MappingColumn.vue
+++ b/pkg/harvester/components/vm-migration/MappingColumn.vue
@@ -108,7 +108,7 @@ const formatModes = (entry) => {
{{ formatModes(entry) }}
{{ t('harvester.addons.vmMigration.storageDefaults.inherited', { provider: inheritedProviderName }) }}
diff --git a/pkg/harvester/components/vm-migration/SelectVmsStep.vue b/pkg/harvester/components/vm-migration/SelectVmsStep.vue
index cd55be06..33be7e1d 100644
--- a/pkg/harvester/components/vm-migration/SelectVmsStep.vue
+++ b/pkg/harvester/components/vm-migration/SelectVmsStep.vue
@@ -25,8 +25,9 @@ const { discoveredVMs, selectedVMIds, tableRows } = toRefs(props.stepData);
const selectedVMs = ref([]);
const loading = ref(true);
-const networkMap = ref({});
-const datastoreMap = ref({});
+// Restored from stepData so friendly names survive step navigation / remount.
+const networkMap = ref(props.stepData.networkMap || {});
+const datastoreMap = ref(props.stepData.datastoreMap || {});
const sortableTableRef = ref(null);
const allVMsSelected = ref(false);
const errors = ref([]);
@@ -240,12 +241,22 @@ const clearSelection = () => {
if (table) {
table.clearSelection();
+
+ if (typeof table.setPage === 'function') {
+ table.setPage(1);
+ }
}
});
};
-// Re-sorts the table so currently-selected VMs appear on the first pages.
-const showSelectedFirst = () => {
+const selectAllVMs = () => {
+ allVMsSelected.value = true;
+ selectedVMIds.value = new Set(discoveredVMs.value.map((vm) => vm.id));
+ selectedVMs.value = discoveredVMs.value.slice();
+};
+
+// Moves currently-selected VMs to the first page(s) and re-checks them.
+const sortSelectedToFront = () => {
if (selectedVMIds.value.size === 0) {
return;
}
@@ -258,19 +269,33 @@ const showSelectedFirst = () => {
h.name === 'vmName' ? { ...h, sort: ['selectedSort', 'vmName'] } : h
));
+ skipNextSelectionEvent = true;
+
nextTick(() => {
const table = sortableTableRef.value;
- if (table) {
- table.page = 1;
- }
- });
-};
+ if (!table) {
+ skipNextSelectionEvent = false;
-const selectAllVMs = () => {
- allVMsSelected.value = true;
- selectedVMIds.value = new Set(discoveredVMs.value.map((vm) => vm.id));
- selectedVMs.value = discoveredVMs.value.slice();
+ return;
+ }
+
+ if (typeof table.changeSort === 'function') {
+ table.changeSort('vmName', false);
+ } else if (typeof table.setPage === 'function') {
+ table.setPage(1);
+ }
+
+ nextTick(() => {
+ const rowsToReselect = (table.pagedRows || []).filter((row) => selectedVMIds.value.has(row._original?.id));
+
+ if (rowsToReselect.length > 0) {
+ table.update(rowsToReselect, []);
+ }
+
+ skipNextSelectionEvent = false;
+ });
+ });
};
watch(
@@ -342,6 +367,9 @@ const fetchVMs = async() => {
return map;
}, {});
+ props.stepData.networkMap = networkMap.value;
+ props.stepData.datastoreMap = datastoreMap.value;
+
lastFetchedAt.value = Date.now();
tableRows.value = buildTableRows();
};
@@ -398,6 +426,10 @@ const init = async() => {
tableRows.value = buildTableRows();
loading.value = false;
+ // Returning to the step with an existing selection: bring selected VMs forward and re-check them.
+ await nextTick();
+ sortSelectedToFront();
+
return;
}
@@ -465,7 +497,6 @@ init();
:row-actions="false"
:groupable="false"
:paging="true"
- :rows-per-page="20"
key-field="_key"
@selection="onSelect"
>
@@ -475,13 +506,9 @@ init();
{{ t('harvester.addons.vmMigration.selectVms.availableVms') }}
-
+
{{ selectedCount }} {{ t('harvester.addons.vmMigration.selectVms.selected') }}
-
+
|
{
.storage-defaults-card {
margin: 0;
+ padding: 20px;
}
.description {