]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/window/Migrate.js
ui: guest import: move live import checkbox into panel
[pve-manager.git] / www / manager6 / window / Migrate.js
index 6f4759de9d5895a2628e62fd568a2d1870de1105..5473821b9416b70accefa9e4adba0883979f62be 100644 (file)
@@ -98,7 +98,6 @@ Ext.define('PVE.window.Migrate', {
            me.lookup('proxmoxHelpButton').setHelpConfig({
                onlineHelp: vm.get(view.vmtype).onlineHelp,
            });
-           me.checkMigratePreconditions();
            me.lookup('formPanel').isValid();
        },
 
@@ -156,7 +155,7 @@ Ext.define('PVE.window.Migrate', {
            });
        },
 
-       checkMigratePreconditions: function(resetMigrationPossible) {
+       checkMigratePreconditions: async function(resetMigrationPossible) {
            var me = this,
                vm = me.getViewModel();
 
@@ -166,12 +165,13 @@ Ext.define('PVE.window.Migrate', {
                vm.set('running', true);
            }
 
+           me.lookup('pveNodeSelector').disallowedNodes = [vm.get('nodename')];
+
            if (vm.get('vmtype') === 'qemu') {
-               me.checkQemuPreconditions(resetMigrationPossible);
+               await me.checkQemuPreconditions(resetMigrationPossible);
            } else {
                me.checkLxcPreconditions(resetMigrationPossible);
            }
-           me.lookup('pveNodeSelector').disallowedNodes = [vm.get('nodename')];
 
            // Only allow nodes where the local storage is available in case of offline migration
            // where storage migration is not possible
@@ -190,11 +190,16 @@ Ext.define('PVE.window.Migrate', {
            }
 
            try {
+               if (me.fetchingNodeMigrateInfo && me.fetchingNodeMigrateInfo === vm.get('nodename')) {
+                   return;
+               }
+               me.fetchingNodeMigrateInfo = vm.get('nodename');
                let { result } = await Proxmox.Async.api2({
                    url: `/nodes/${vm.get('nodename')}/${vm.get('vmtype')}/${vm.get('vmid')}/migrate`,
                    method: 'GET',
                });
                migrateStats = result.data;
+               me.fetchingNodeMigrateInfo = false;
            } catch (error) {
                Ext.Msg.alert(gettext('Error'), error.htmlStatus);
                return;
@@ -214,49 +219,73 @@ Ext.define('PVE.window.Migrate', {
                migration.allowedNodes = migrateStats.allowed_nodes;
                let target = me.lookup('pveNodeSelector').value;
                if (target.length && !migrateStats.allowed_nodes.includes(target)) {
-                   let disallowed = migrateStats.not_allowed_nodes[target];
-                   let missingStorages = disallowed.unavailable_storages.join(', ');
+                   let disallowed = migrateStats.not_allowed_nodes[target] ?? {};
+                   if (disallowed.unavailable_storages !== undefined) {
+                       let missingStorages = disallowed.unavailable_storages.join(', ');
 
-                   migration.possible = false;
-                   migration.preconditions.push({
-                       text: 'Storage (' + missingStorages + ') not available on selected target. ' +
-                         'Start VM to use live storage migration or select other target node',
-                       severity: 'error',
-                   });
+                       migration.possible = false;
+                       migration.preconditions.push({
+                           text: 'Storage (' + missingStorages + ') not available on selected target. ' +
+                             'Start VM to use live storage migration or select other target node',
+                           severity: 'error',
+                       });
+                   }
+
+                   if (disallowed['unavailable-resources'] !== undefined) {
+                       let unavailableResources = disallowed['unavailable-resources'].join(', ');
+
+                       migration.possible = false;
+                       migration.preconditions.push({
+                           text: 'Mapped Resources (' + unavailableResources + ') not available on selected target. ',
+                           severity: 'error',
+                       });
+                   }
                }
            }
 
-           if (migrateStats.local_resources.length) {
+           let blockingResources = [];
+           let mappedResources = migrateStats['mapped-resources'] ?? [];
+
+           for (const res of migrateStats.local_resources) {
+               if (mappedResources.indexOf(res) === -1) {
+                   blockingResources.push(res);
+               }
+           }
+
+           if (blockingResources.length) {
                migration.hasLocalResources = true;
                if (!migration.overwriteLocalResourceCheck || vm.get('running')) {
                    migration.possible = false;
                    migration.preconditions.push({
                        text: Ext.String.format('Can\'t migrate VM with local resources: {0}',
-                       migrateStats.local_resources.join(', ')),
+                       blockingResources.join(', ')),
                        severity: 'error',
                    });
                } else {
                    migration.preconditions.push({
                        text: Ext.String.format('Migrate VM with local resources: {0}. ' +
                        'This might fail if resources aren\'t available on the target node.',
-                       migrateStats.local_resources.join(', ')),
+                       blockingResources.join(', ')),
                        severity: 'warning',
                    });
                }
            }
 
+           if (mappedResources && mappedResources.length) {
+               if (vm.get('running')) {
+                   migration.possible = false;
+                   migration.preconditions.push({
+                       text: Ext.String.format('Can\'t migrate running VM with mapped resources: {0}',
+                       mappedResources.join(', ')),
+                       severity: 'error',
+                   });
+               }
+           }
+
            if (migrateStats.local_disks.length) {
                migrateStats.local_disks.forEach(function(disk) {
                    if (disk.cdrom && disk.cdrom === 1) {
-                       if (disk.volid.includes('vm-' + vm.get('vmid') + '-cloudinit')) {
-                           if (migrateStats.running) {
-                               migration.possible = false;
-                               migration.preconditions.push({
-                                    text: "Can't live migrate VM with local cloudinit disk, use shared storage instead",
-                                    severity: 'error',
-                               });
-                           }
-                       } else {
+                       if (!disk.volid.includes('vm-' + vm.get('vmid') + '-cloudinit')) {
                            migration.possible = false;
                            migration.preconditions.push({
                                text: "Can't migrate VM with local CD/DVD",