-/*jslint confusion: true*/
Ext.define('PVE.window.Migrate', {
extend: 'Ext.window.Window',
vmtype: undefined,
nodename: undefined,
vmid: undefined,
+ maxHeight: 450,
viewModel: {
data: {
preconditions: [],
'with-local-disks': 0,
mode: undefined,
- allowedNodes: undefined
+ allowedNodes: undefined,
+ overwriteLocalResourceCheck: false,
+ hasLocalResources: false
}
},
} else {
return true;
}
+ },
+ setLocalResourceCheckboxHidden: function(get) {
+ if (get('running') || !get('migration.hasLocalResources') ||
+ Proxmox.UserName !== 'root@pam') {
+ return true;
+ } else {
+ return false;
+ }
}
}
},
view.setTitle(
- Ext.String.format('{0} {1}{2}', gettext('Migrate'), vm.get(view.vmtype).commonName, view.vmid)
+ 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
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',
},
- checkMigratePreconditions: function() {
+ 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) {
}
if (vm.get('vmtype') === 'qemu') {
- me.checkQemuPreconditions();
+ me.checkQemuPreconditions(resetMigrationPossible);
} else {
- me.checkLxcPreconditions();
+ me.checkLxcPreconditions(resetMigrationPossible);
}
me.lookup('pveNodeSelector').disallowedNodes = [vm.get('nodename')];
},
- checkQemuPreconditions: function() {
+ checkQemuPreconditions: function(resetMigrationPossible) {
var me = this,
vm = me.getViewModel(),
migrateStats;
// Get migration object from viewmodel to prevent
// to many bind callbacks
var migration = vm.get('migration');
+ if (resetMigrationPossible) migration.possible = true;
migration.preconditions = [];
if (migrateStats.allowed_nodes) {
migration.allowedNodes = migrateStats.allowed_nodes;
+ var target = me.lookup('pveNodeSelector').value;
+ if (target.length && !migrateStats.allowed_nodes.includes(target)) {
+ let disallowed = migrateStats.not_allowed_nodes[target];
+ let missing_storages = disallowed.unavailable_storages.join(', ');
- if (!migrateStats.allowed_nodes.includes(me.lookup('pveNodeSelector').value)) {
migration.possible = false;
migration.preconditions.push({
- text: 'Local storage not available on selected Node, start VM to use live storage migration or select other target node',
+ text: 'Storage (' + missing_storages + ') 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.possible = false;
- migration.preconditions.push({
- text: 'Can\'t migrate VM with local resources: '+ migrateStats.local_resources.join(', '),
- severity: 'error'
- });
+ 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'
+ });
+ }
}
if (migrateStats.local_disks.length) {
migrateStats.local_disks.forEach(function (disk) {
if (disk.cdrom && disk.cdrom === 1) {
- migration.possible = false;
- migration.preconditions.push({
- text:'Can\'t migrate VM with local CD/DVD',
- severity: 'error'
- });
-
- } else if (!disk.referenced_in_config) {
- migration.possible = false;
- migration.preconditions.push({
- text: 'Found not referenced/unused disk via storage: '+ disk.volid,
- severity: 'error'
- });
+ 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 {
+ return;
+ }
+ } else {
+ migration.possible = false;
+ migration.preconditions.push({
+ text: "Can't migrate VM with local CD/DVD",
+ severity: 'error'
+ });
+ }
} else {
migration['with-local-disks'] = 1;
migration.preconditions.push({
- text:'Migration with local disk might take long: '+ disk.volid,
+ text:'Migration with local disk might take long: ' + disk.volid
+ +' (' + PVE.Utils.render_size(disk.size) + ')',
severity: 'warning'
});
}
}
});
},
- checkLxcPreconditions: function() {
+ checkLxcPreconditions: function(resetMigrationPossible) {
var me = this,
vm = me.getViewModel();
if (vm.get('running')) {
bind: {
hidden: '{setStorageselectorHidden}'
}
- }]
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ name: 'overwriteLocalResourceCheck',
+ fieldLabel: gettext('Force'),
+ autoEl: {
+ tag: 'div',
+ 'data-qtip': 'Overwrite local resources unavailable check'
+ },
+ bind: {
+ hidden: '{setLocalResourceCheckboxHidden}',
+ value: '{migration.overwriteLocalResourceCheck}'
+ },
+ listeners: {
+ change: {fn: 'checkMigratePreconditions', extraArg: true}
+ }
+ }]
}
]
},