+ if (!view.vmtype) {
+ throw "missing custom view config: vmtype";
+ }
+ vm.set('vmtype', view.vmtype);
+
+ view.setTitle(
+ Ext.String.format('{0} {1} {2}', gettext('Migrate'), vm.get(view.vmtype).commonName, view.vmid),
+ );
+ me.lookup('proxmoxHelpButton').setHelpConfig({
+ onlineHelp: vm.get(view.vmtype).onlineHelp,
+ });
+ me.lookup('formPanel').isValid();
+ },
+
+ onTargetChange: function(nodeSelector) {
+ // Always display the storages of the currently seleceted migration target
+ this.lookup('pveDiskStorageSelector').setNodename(nodeSelector.value);
+ this.checkMigratePreconditions();
+ },
+
+ startMigration: function() {
+ var me = this,
+ view = me.getView(),
+ vm = me.getViewModel();
+
+ var values = me.lookup('formPanel').getValues();
+ var params = {
+ target: values.target,
+ };
+
+ if (vm.get('migration.mode')) {
+ params[vm.get('migration.mode')] = 1;
+ }
+ if (vm.get('migration.with-local-disks')) {
+ params['with-local-disks'] = 1;
+ }
+ //offline migration to a different storage currently might fail at a late stage
+ //(i.e. after some disks have been moved), so don't expose it yet in the GUI
+ if (vm.get('migration.with-local-disks') && vm.get('running') && values.targetstorage) {
+ params.targetstorage = values.targetstorage;
+ }
+
+ if (vm.get('migration.overwriteLocalResourceCheck')) {
+ params.force = 1;
+ }
+
+ Proxmox.Utils.API2Request({
+ params: params,
+ url: '/nodes/' + vm.get('nodename') + '/' + vm.get('vmtype') + '/' + vm.get('vmid') + '/migrate',
+ waitMsgTarget: view,
+ method: 'POST',
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ success: function(response, options) {
+ var upid = response.result.data;
+ var extraTitle = Ext.String.format(' ({0} ---> {1})', vm.get('nodename'), params.target);
+
+ Ext.create('Proxmox.window.TaskViewer', {
+ upid: upid,
+ extraTitle: extraTitle,
+ }).show();
+
+ view.close();
+ },
+ });
+ },
+
+ checkMigratePreconditions: function(resetMigrationPossible) {
+ var me = this,
+ vm = me.getViewModel();
+
+ var vmrec = PVE.data.ResourceStore.findRecord('vmid', vm.get('vmid'),
+ 0, false, false, true);
+ if (vmrec && vmrec.data && vmrec.data.running) {
+ vm.set('running', true);
+ }
+
+ if (vm.get('vmtype') === 'qemu') {
+ 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
+ me.lookup('pveNodeSelector').allowedNodes = vm.get('migration.allowedNodes');
+
+ me.lookup('formPanel').isValid();
+ },
+
+ checkQemuPreconditions: async function(resetMigrationPossible) {
+ let me = this,
+ vm = me.getViewModel(),
+ migrateStats;
+
+ if (vm.get('running')) {
+ vm.set('migration.mode', 'online');
+ }
+
+ 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;
+ }
+
+ if (migrateStats.running) {
+ vm.set('running', true);
+ }
+ // Get migration object from viewmodel to prevent to many bind callbacks
+ let migration = vm.get('migration');
+ if (resetMigrationPossible) {
+ migration.possible = true;
+ }
+ migration.preconditions = [];
+
+ if (migrateStats.allowed_nodes) {
+ 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(', ');
+
+ 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 (migrateStats.local_resources.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(', ')),
+ 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(', ')),
+ severity: 'warning',