ui: vm hardware: module wide refactoring/cleanups/style changes/fixes

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2022-04-01 16:43:52 +02:00
parent 0bb1e60d1a
commit b49a0404be

View File

@ -46,13 +46,10 @@ Ext.define('PVE.qemu.HardwareView', {
initComponent: function() { initComponent: function() {
var me = this; var me = this;
const nodename = me.pveSelNode.data.node; const { node: nodename, vmid } = me.pveSelNode.data;
if (!nodename) { if (!nodename) {
throw "no node name specified"; throw "no node name specified";
} } else if (!vmid) {
const vmid = me.pveSelNode.data.vmid;
if (!vmid) {
throw "no VM ID specified"; throw "no VM ID specified";
} }
@ -60,6 +57,8 @@ Ext.define('PVE.qemu.HardwareView', {
const diskCap = caps.vms['VM.Config.Disk']; const diskCap = caps.vms['VM.Config.Disk'];
const cdromCap = caps.vms['VM.Config.CDROM']; const cdromCap = caps.vms['VM.Config.CDROM'];
let isCloudInitKey = v => v && v.toString().match(/vm-.*-cloudinit/);
let rows = { let rows = {
memory: { memory: {
header: gettext('Memory'), header: gettext('Memory'),
@ -108,25 +107,21 @@ Ext.define('PVE.qemu.HardwareView', {
var cpulimit = me.getObjectValue('cpulimit', undefined, pending); var cpulimit = me.getObjectValue('cpulimit', undefined, pending);
var cpuunits = me.getObjectValue('cpuunits', undefined, pending); var cpuunits = me.getObjectValue('cpuunits', undefined, pending);
var res = Ext.String.format('{0} ({1} sockets, {2} cores)', let res = Ext.String.format(
sockets*cores, sockets, cores); '{0} ({1} sockets, {2} cores)', sockets * cores, sockets, cores);
if (model) { if (model) {
res += ' [' + model + ']'; res += ' [' + model + ']';
} }
if (numa) { if (numa) {
res += ' [numa=' + numa +']'; res += ' [numa=' + numa +']';
} }
if (vcpus) { if (vcpus) {
res += ' [vcpus=' + vcpus +']'; res += ' [vcpus=' + vcpus +']';
} }
if (cpulimit) { if (cpulimit) {
res += ' [cpulimit=' + cpulimit +']'; res += ' [cpulimit=' + cpulimit +']';
} }
if (cpuunits) { if (cpuunits) {
res += ' [cpuunits=' + cpuunits +']'; res += ' [cpuunits=' + cpuunits +']';
} }
@ -334,25 +329,21 @@ Ext.define('PVE.qemu.HardwareView', {
} }
}; };
var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config'; let baseurl = `nodes/${nodename}/qemu/${vmid}/config`;
var sm = Ext.create('Ext.selection.RowModel', {}); let sm = Ext.create('Ext.selection.RowModel', {});
var run_editor = function() { let run_editor = function() {
var rec = sm.getSelection()[0]; let rec = sm.getSelection()[0];
if (!rec) { if (!rec || !rows[rec.data.key]?.editor) {
return; return;
} }
let rowdef = rows[rec.data.key];
let editor = rowdef.editor;
var rowdef = rows[rec.data.key];
if (!rowdef.editor) {
return;
}
var editor = rowdef.editor;
if (rowdef.isOnStorageBus) { if (rowdef.isOnStorageBus) {
var value = me.getObjectValue(rec.data.key, '', true); let value = me.getObjectValue(rec.data.key, '', true);
if (value.match(/vm-.*-cloudinit/)) { if (isCloudInitKey(value)) {
return; return;
} else if (value.match(/media=cdrom/)) { } else if (value.match(/media=cdrom/)) {
editor = 'PVE.qemu.CDEdit'; editor = 'PVE.qemu.CDEdit';
@ -361,84 +352,74 @@ Ext.define('PVE.qemu.HardwareView', {
} }
} }
var win; let commonOpts = {
autoShow: true,
pveSelNode: me.pveSelNode,
confid: rec.data.key,
url: `/api2/extjs/${baseurl}`,
listeners: {
destroy: () => me.reload(),
},
};
if (Ext.isString(editor)) { if (Ext.isString(editor)) {
win = Ext.create(editor, { Ext.create(editor, commonOpts);
pveSelNode: me.pveSelNode,
confid: rec.data.key,
url: '/api2/extjs/' + baseurl,
});
} else { } else {
var config = Ext.apply({ let win = Ext.createWidget(rowdef.editor.xtype, Ext.apply(commonOpts, rowdef.editor));
pveSelNode: me.pveSelNode,
confid: rec.data.key,
url: '/api2/extjs/' + baseurl,
}, rowdef.editor);
win = Ext.createWidget(rowdef.editor.xtype, config);
win.load(); win.load();
} }
win.show();
win.on('destroy', me.reload, me);
}; };
var run_resize = function() { let edit_btn = new Proxmox.button.Button({
var rec = sm.getSelection()[0];
if (!rec) {
return;
}
var win = Ext.create('PVE.window.HDResize', {
disk: rec.data.key,
nodename: nodename,
vmid: vmid,
});
win.show();
win.on('destroy', me.reload, me);
};
var run_move = function() {
var rec = sm.getSelection()[0];
if (!rec) {
return;
}
var win = Ext.create('PVE.window.HDMove', {
disk: rec.data.key,
nodename: nodename,
vmid: vmid,
});
win.show();
win.on('destroy', me.reload, me);
};
var edit_btn = new Proxmox.button.Button({
text: gettext('Edit'), text: gettext('Edit'),
selModel: sm, selModel: sm,
disabled: true, disabled: true,
handler: run_editor, handler: run_editor,
}); });
var resize_btn = new Proxmox.button.Button({ let resize_btn = new Proxmox.button.Button({
text: gettext('Resize disk'), text: gettext('Resize disk'),
selModel: sm, selModel: sm,
disabled: true, disabled: true,
handler: run_resize, handler: () => {
let rec = sm.getSelection()[0];
if (!rec) {
return;
}
Ext.create('PVE.window.HDResize', {
autoShow: true,
disk: rec.data.key,
nodename: nodename,
vmid: vmid,
listeners: {
destroy: () => me.reload(),
},
});
},
}); });
var move_btn = new Proxmox.button.Button({ let move_btn = new Proxmox.button.Button({
text: gettext('Move disk'), text: gettext('Move disk'),
selModel: sm, selModel: sm,
disabled: true, disabled: true,
handler: run_move, handler: () => {
var rec = sm.getSelection()[0];
if (!rec) {
return;
}
Ext.create('PVE.window.HDMove', {
autoShow: true,
disk: rec.data.key,
nodename: nodename,
vmid: vmid,
listeners: {
destroy: () => me.reload(),
},
});
},
}); });
var remove_btn = new Proxmox.button.Button({ let remove_btn = new Proxmox.button.Button({
text: gettext('Remove'), text: gettext('Remove'),
defaultText: gettext('Remove'), defaultText: gettext('Remove'),
altText: gettext('Detach'), altText: gettext('Detach'),
@ -459,28 +440,25 @@ Ext.define('PVE.qemu.HardwareView', {
} }
return msg; return msg;
}, },
handler: function(b, e, rec) { handler: function(btn, e, rec) {
Proxmox.Utils.API2Request({ Proxmox.Utils.API2Request({
url: '/api2/extjs/' + baseurl, url: '/api2/extjs/' + baseurl,
waitMsgTarget: me, waitMsgTarget: me,
method: b.RESTMethod, method: btn.RESTMethod,
params: { params: {
'delete': rec.data.key, 'delete': rec.data.key,
}, },
callback: () => me.reload(), callback: () => me.reload(),
failure: function(response, opts) { failure: response => Ext.Msg.alert('Error', response.htmlStatus),
Ext.Msg.alert('Error', response.htmlStatus);
},
success: function(response, options) { success: function(response, options) {
if (b.RESTMethod === 'POST') { if (btn.RESTMethod === 'POST') {
var upid = response.result.data; Ext.create('Proxmox.window.TaskProgress', {
var win = Ext.create('Proxmox.window.TaskProgress', { autoShow: true,
upid: upid, upid: response.result.data,
listeners: { listeners: {
destroy: () => me.reload(), destroy: () => me.reload(),
}, },
}); });
win.show();
} }
}, },
}); });
@ -502,56 +480,49 @@ Ext.define('PVE.qemu.HardwareView', {
}, },
}); });
var revert_btn = new PVE.button.PendingRevert({ let revert_btn = new PVE.button.PendingRevert({
apiurl: '/api2/extjs/' + baseurl, apiurl: '/api2/extjs/' + baseurl,
}); });
var efidisk_menuitem = Ext.create('Ext.menu.Item', { let efidisk_menuitem = Ext.create('Ext.menu.Item', {
text: gettext('EFI Disk'), text: gettext('EFI Disk'),
iconCls: 'fa fa-fw fa-hdd-o black', iconCls: 'fa fa-fw fa-hdd-o black',
disabled: !caps.vms['VM.Config.Disk'], disabled: !caps.vms['VM.Config.Disk'],
handler: function() { handler: function() {
let bios = me.rstore.getData().map.bios; let { data: bios } = me.rstore.getData().map.bios || {};
let usesEFI = bios && (bios.data.value === 'ovmf' || bios.data.pending === 'ovmf');
var win = Ext.create('PVE.qemu.EFIDiskEdit', { Ext.create('PVE.qemu.EFIDiskEdit', {
autoShow: true,
url: '/api2/extjs/' + baseurl, url: '/api2/extjs/' + baseurl,
pveSelNode: me.pveSelNode, pveSelNode: me.pveSelNode,
usesEFI: usesEFI, usesEFI: bios?.value === 'ovmf' || bios?.pending === 'ovmf',
listeners: {
destroy: () => me.reload(),
},
}); });
win.on('destroy', me.reload, me);
win.show();
}, },
}); });
let counts = {}; let counts = {};
let isAtLimit = (type) => counts[type] >= PVE.Utils.hardware_counts[type]; let isAtLimit = (type) => counts[type] >= PVE.Utils.hardware_counts[type];
var set_button_status = function() { let set_button_status = function() {
var selection_model = me.getSelectionModel(); let selection_model = me.getSelectionModel();
var rec = selection_model.getSelection()[0]; let rec = selection_model.getSelection()[0];
// en/disable hardwarebuttons counts = {}; // en/disable hardwarebuttons
counts = {}; let hasCloudInit = false;
var hasCloudInit = false; me.rstore.getData().items.forEach(function({ id, data }) {
me.rstore.getData().items.forEach(function(item) { if (!hasCloudInit && (isCloudInitKey(data.value) || isCloudInitKey(data.pending))) {
if (!hasCloudInit && (
/vm-.*-cloudinit/.test(item.data.value) ||
/vm-.*-cloudinit/.test(item.data.pending)
)) {
hasCloudInit = true; hasCloudInit = true;
return; return;
} }
let match = item.id.match(/^([^\d]+)\d+$/); let match = id.match(/^([^\d]+)\d+$/);
let type;
if (match && PVE.Utils.hardware_counts[match[1]] !== undefined) { if (match && PVE.Utils.hardware_counts[match[1]] !== undefined) {
type = match[1]; let type = match[1];
} else { counts[type] = (counts[type] || 0) + 1;
return;
} }
counts[type] = (counts[type] || 0) + 1;
}); });
// heuristic only for disabling some stuff, the backend has the final word. // heuristic only for disabling some stuff, the backend has the final word.
@ -578,14 +549,13 @@ Ext.define('PVE.qemu.HardwareView', {
revert_btn.disable(); revert_btn.disable();
return; return;
} }
const key = rec.data.key; const { key, value } = rec.data;
const value = rec.data.value;
const row = rows[key]; const row = rows[key];
const deleted = !!rec.data.delete; const deleted = !!rec.data.delete;
const pending = deleted || me.hasPendingChanges(key); const pending = deleted || me.hasPendingChanges(key);
const isCloudInit = value && value.toString().match(/vm-.*-cloudinit/); const isCloudInit = isCloudInitKey(value);
const isCDRom = value && !!value.toString().match(/media=cdrom/) && !isCloudInit; const isCDRom = value && !!value.toString().match(/media=cdrom/) && !isCloudInit;
const isUnusedDisk = key.match(/^unused\d+/); const isUnusedDisk = key.match(/^unused\d+/);
@ -595,21 +565,12 @@ Ext.define('PVE.qemu.HardwareView', {
const tpmMoveable = key === 'tpmstate0' && !me.pveSelNode.data.running; const tpmMoveable = key === 'tpmstate0' && !me.pveSelNode.data.running;
remove_btn.setDisabled( remove_btn.setDisabled(
deleted || deleted || row.never_delete || (isCDRom && !cdromCap) || (isDisk && !diskCap));
row.never_delete ||
(isCDRom && !cdromCap) ||
(isDisk && !diskCap),
);
remove_btn.setText(isUsedDisk && !isCloudInit ? remove_btn.altText : remove_btn.defaultText); remove_btn.setText(isUsedDisk && !isCloudInit ? remove_btn.altText : remove_btn.defaultText);
remove_btn.RESTMethod = isUnusedDisk ? 'POST':'PUT'; remove_btn.RESTMethod = isUnusedDisk ? 'POST':'PUT';
edit_btn.setDisabled( edit_btn.setDisabled(
deleted || deleted || !row.editor || isCloudInit || (isCDRom && !cdromCap) || (isDisk && !diskCap));
!row.editor ||
isCloudInit ||
(isCDRom && !cdromCap) ||
(isDisk && !diskCap),
);
resize_btn.setDisabled(pending || !isUsedDisk || !diskCap); resize_btn.setDisabled(pending || !isUsedDisk || !diskCap);