pve-manager/www/manager6/qemu/Config.js
Dominik Csapak d5a7996b13 fix reselection on vm/ct migrate in gui
there were a number of problems in how we reselected vms when they
migrated and selected:

we relied on the data in the configpanel to be static, but since
pveselnode is a reference, it actually changes when the resourcestore
changes
also, handling the reselection as a response to the statusstore failure
is very inconsistent, because we know exactly when a vm moves node in
the tree

this patch removes the whole configpanel vm migration code,
and lets the tree handle it
for this, we have to check if we have to reselect the entry,
deselect it manually and after the treeupdate reselect it

also in the right click selection check we have to check if it is
already selected, else the next selection will get canceled

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
2017-06-23 13:01:12 +02:00

348 lines
8.3 KiB
JavaScript

Ext.define('PVE.qemu.Config', {
extend: 'PVE.panel.Config',
alias: 'widget.PVE.qemu.Config',
onlineHelp: 'chapter_virtual_machines',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename) {
throw "no node name specified";
}
var vmid = me.pveSelNode.data.vmid;
if (!vmid) {
throw "no VM ID specified";
}
var template = me.pveSelNode.data.template;
var caps = Ext.state.Manager.get('GuiCap');
var base_url = '/nodes/' + nodename + "/qemu/" + vmid;
me.statusStore = Ext.create('PVE.data.ObjectStore', {
url: '/api2/json' + base_url + '/status/current',
interval: 1000
});
var vm_command = function(cmd, params) {
PVE.Utils.API2Request({
params: params,
url: base_url + '/status/' + cmd,
waitMsgTarget: me,
method: 'POST',
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
};
var resumeBtn = Ext.create('Ext.Button', {
text: gettext('Resume'),
disabled: !caps.vms['VM.PowerMgmt'],
hidden: true,
handler: function() {
vm_command('resume');
},
iconCls: 'fa fa-play'
});
var startBtn = Ext.create('Ext.Button', {
text: gettext('Start'),
disabled: !caps.vms['VM.PowerMgmt'],
handler: function() {
vm_command('start');
},
iconCls: 'fa fa-play'
});
var migrateBtn = Ext.create('Ext.Button', {
text: gettext('Migrate'),
disabled: !caps.vms['VM.Migrate'],
handler: function() {
var win = Ext.create('PVE.window.Migrate', {
vmtype: 'qemu',
nodename: nodename,
vmid: vmid
});
win.show();
},
iconCls: 'fa fa-send-o'
});
var cloneBtn = Ext.create('PVE.button.Split', {
text: gettext('Clone'),
iconCls: 'fa fa-fw fa-clone',
hidden: caps.vms['VM.Clone'] ? false : true,
handler: function() {
PVE.window.Clone.wrap(nodename, vmid, template);
},
menu: {
items: [{
text: gettext('Convert to template'),
disabled: template,
iconCls: 'fa fa-fw fa-file-o',
hidden: caps.vms['VM.Allocate'] ? false : true,
confirmMsg: PVE.Utils.format_task_description('qmtemplate', vmid),
handler: function() {
PVE.Utils.API2Request({
url: base_url + '/template',
waitMsgTarget: me,
method: 'POST',
failure: function(response, opts) {
Ext.Msg.alert('Error', response.htmlStatus);
}
});
}
}]
}
});
var shutdownBtn = Ext.create('PVE.button.Split', {
text: gettext('Shutdown'),
disabled: !caps.vms['VM.PowerMgmt'],
confirmMsg: PVE.Utils.format_task_description('qmshutdown', vmid),
handler: function() {
vm_command('shutdown');
},
menu: {
items: [{
text: gettext('Stop'),
disabled: !caps.vms['VM.PowerMgmt'],
dangerous: true,
confirmMsg: PVE.Utils.format_task_description('qmstop', vmid),
handler: function() {
vm_command("stop", { timeout: 30 });
},
iconCls: 'fa fa-stop'
},{
text: gettext('Reset'),
disabled: !caps.vms['VM.PowerMgmt'],
confirmMsg: PVE.Utils.format_task_description('qmreset', vmid),
handler: function() {
vm_command("reset");
},
iconCls: 'fa fa-bolt'
}]
},
iconCls: 'fa fa-power-off'
});
var removeBtn = Ext.create('PVE.button.Button', {
text: gettext('Remove'),
disabled: !caps.vms['VM.Allocate'],
handler: function() {
Ext.create('PVE.window.SafeDestroy', {
url: base_url,
item: { type: 'VM', id: vmid }
}).show();
},
iconCls: 'fa fa-trash-o'
});
var vmname = me.pveSelNode.data.name;
var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
disabled: !caps.vms['VM.Console'],
consoleType: 'kvm',
consoleName: vmname,
nodename: nodename,
vmid: vmid,
iconCls: 'fa fa-terminal'
});
var descr = vmid + " (" + (vmname ? "'" + vmname + "' " : "'VM " + vmid + "'") + ")";
Ext.apply(me, {
title: Ext.String.format(gettext("Virtual Machine {0} on node {1}"), descr, "'" + nodename + "'"),
hstateid: 'kvmtab',
tbar: [ resumeBtn, startBtn, shutdownBtn,
removeBtn, migrateBtn, cloneBtn, consoleBtn],
defaults: { statusStore: me.statusStore },
items: [
{
title: gettext('Summary'),
xtype: 'pveQemuSummary',
iconCls: 'fa fa-book',
itemId: 'summary'
}
]
});
if (caps.vms['VM.Console'] && !template) {
me.items.push({
title: gettext('Console'),
itemId: 'console',
iconCls: 'fa fa-terminal',
xtype: 'pveNoVncConsole',
vmid: vmid,
consoleType: 'kvm',
nodename: nodename
});
}
me.items.push(
{
title: gettext('Hardware'),
itemId: 'hardware',
iconCls: 'fa fa-desktop',
xtype: 'PVE.qemu.HardwareView'
},
{
title: gettext('Options'),
iconCls: 'fa fa-gear',
itemId: 'options',
xtype: 'PVE.qemu.Options'
},
{
title: gettext('Task History'),
itemId: 'tasks',
xtype: 'pveNodeTasks',
iconCls: 'fa fa-list',
vmidFilter: vmid
}
);
if (caps.vms['VM.Monitor'] && !template) {
me.items.push({
title: gettext('Monitor'),
iconCls: 'fa fa-eye',
itemId: 'monitor',
xtype: 'pveQemuMonitor'
});
}
if (caps.vms['VM.Backup']) {
me.items.push({
title: gettext('Backup'),
iconCls: 'fa fa-floppy-o',
xtype: 'pveBackupView',
itemId: 'backup'
},
{
title: gettext('Replication'),
iconCls: 'fa fa-retweet',
xtype: 'pveReplicaView',
itemId: 'replication'
});
}
if (caps.vms['VM.Snapshot'] && !template) {
me.items.push({
title: gettext('Snapshots'),
iconCls: 'fa fa-history',
xtype: 'pveQemuSnapshotTree',
itemId: 'snapshot'
});
}
if (caps.vms['VM.Console']) {
me.items.push(
{
xtype: 'pveFirewallRules',
title: gettext('Firewall'),
iconCls: 'fa fa-shield',
allow_iface: true,
base_url: base_url + '/firewall/rules',
list_refs_url: base_url + '/firewall/refs',
itemId: 'firewall'
},
{
xtype: 'pveFirewallOptions',
groups: ['firewall'],
iconCls: 'fa fa-gear',
onlineHelp: 'pve_firewall_vm_container_configuration',
title: gettext('Options'),
base_url: base_url + '/firewall/options',
fwtype: 'vm',
itemId: 'firewall-options'
},
{
xtype: 'pveFirewallAliases',
title: gettext('Alias'),
groups: ['firewall'],
iconCls: 'fa fa-external-link',
base_url: base_url + '/firewall/aliases',
itemId: 'firewall-aliases'
},
{
xtype: 'pveIPSet',
title: gettext('IPSet'),
groups: ['firewall'],
iconCls: 'fa fa-list-ol',
base_url: base_url + '/firewall/ipset',
list_refs_url: base_url + '/firewall/refs',
itemId: 'firewall-ipset'
},
{
title: gettext('Log'),
groups: ['firewall'],
iconCls: 'fa fa-list',
onlineHelp: 'chapter_pve_firewall',
itemId: 'firewall-fwlog',
xtype: 'pveLogView',
url: '/api2/extjs' + base_url + '/firewall/log'
}
);
}
if (caps.vms['Permissions.Modify']) {
me.items.push({
xtype: 'pveACLView',
title: gettext('Permissions'),
iconCls: 'fa fa-unlock',
itemId: 'permissions',
path: '/vms/' + vmid
});
}
me.callParent();
me.mon(me.statusStore, 'load', function(s, records, success) {
var status;
var qmpstatus;
var spice = false;
if (!success) {
status = qmpstatus = 'unknown';
} else {
var rec = s.data.get('status');
status = rec ? rec.data.value : 'unknown';
rec = s.data.get('qmpstatus');
qmpstatus = rec ? rec.data.value : 'unknown';
rec = s.data.get('template');
template = rec.data.value || false;
spice = s.data.get('spice') ? true : false;
}
if (qmpstatus === 'prelaunch' || qmpstatus === 'paused' || qmpstatus === 'suspended') {
startBtn.setVisible(false);
resumeBtn.setVisible(true);
} else {
startBtn.setVisible(true);
resumeBtn.setVisible(false);
}
consoleBtn.setEnableSpice(spice);
startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
removeBtn.setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
consoleBtn.setDisabled(template);
});
me.on('afterrender', function() {
me.statusStore.startUpdate();
});
me.on('destroy', function() {
me.statusStore.stopUpdate();
});
}
});