From f97a6e194c3d54716f2f5c3acbd62e903917d507 Mon Sep 17 00:00:00 2001 From: upstream Date: Fri, 2 Oct 2026 16:40:54 +0200 Subject: [PATCH] Upstream proxmox-git/pve-manager state of the touched files before 513c9bc03e --- www/manager6/form/DiskStorageSelector.js | 190 +++++++++++++++++++++++ www/manager6/lxc/MPResize.js | 96 ++++++++++++ www/manager6/qemu/HDResize.js | 99 ++++++++++++ 3 files changed, 385 insertions(+) create mode 100644 www/manager6/form/DiskStorageSelector.js create mode 100644 www/manager6/lxc/MPResize.js create mode 100644 www/manager6/qemu/HDResize.js diff --git a/www/manager6/form/DiskStorageSelector.js b/www/manager6/form/DiskStorageSelector.js new file mode 100644 index 0000000..696f903 --- /dev/null +++ b/www/manager6/form/DiskStorageSelector.js @@ -0,0 +1,190 @@ +Ext.define('PVE.form.DiskStorageSelector', { + extend: 'Ext.container.Container', + alias: 'widget.pveDiskStorageSelector', + + layout: 'fit', + defaults: { + margin: '0 0 5 0', + }, + + // the fieldLabel for the storageselector + storageLabel: gettext('Storage'), + + // the content to show (e.g., images or rootdir) + storageContent: undefined, + + // if true, selects the first available storage + autoSelect: false, + + allowBlank: false, + emptyText: '', + + // hides the selection field + // this is always hidden on creation, + // and only shown when the storage needs a selection and + // hideSelection is not true + hideSelection: undefined, + + // hides the size field (e.g, for the efi disk dialog) + hideSize: false, + + // hides the format field + hideFormat: false, + + // sets the initial size value + // string because else we get a type confusion + defaultSize: '32', + + changeStorage: function (f, value) { + var me = this; + var formatsel = me.getComponent('diskformat'); + var hdfilesel = me.getComponent('hdimage'); + var hdsizesel = me.getComponent('disksize'); + + // initial store load, and reset/deletion of the storage + if (!value) { + hdfilesel.setDisabled(true); + hdfilesel.setVisible(false); + + formatsel.setDisabled(true); + return; + } + + var rec = f.store.getById(value); + // if the storage is not defined, or valid, + // we cannot know what to enable/disable + if (!rec) { + return; + } + + let validFormats = {}; + let defaultFormat = 'raw'; + let selectFormat = defaultFormat; + if (rec.data.formats) { + for (const format of rec.data.formats.supported) { + validFormats[format] = true; + } + defaultFormat = rec.data.formats.default; + } else if (rec.data.format) { + // legacy api, just for compatibility + // 0 is the formats, 1 the default in the backend + validFormats = rec.data.format[0]; + defaultFormat = rec.data.format[1]; + } + + if (Object.keys(validFormats).length > 0) { + delete validFormats.subvol; // we never need subvol in the gui + if (validFormats.qcow2) { + selectFormat = 'qcow2'; + } else if (validFormats.raw) { + selectFormat = 'raw'; + } else { + selectFormat = defaultFormat; + } + } + + var select = !!rec.data.select_existing && !me.hideSelection; + + let numberOfValidFormats = Ext.Object.getValues(validFormats).filter( + (valid) => !!valid, + ).length; + formatsel.setDisabled(me.hideFormat || numberOfValidFormats <= 1); + formatsel.setValue(selectFormat); + + hdfilesel.setDisabled(!select); + hdfilesel.setVisible(select); + if (select) { + hdfilesel.setStorage(value); + } + + hdsizesel.setDisabled(select || me.hideSize); + hdsizesel.setVisible(!select && !me.hideSize); + }, + + setNodename: function (nodename) { + var me = this; + var hdstorage = me.getComponent('hdstorage'); + var hdfilesel = me.getComponent('hdimage'); + + hdstorage.setNodename(nodename); + hdfilesel.setNodename(nodename); + }, + + setDisabled: function (value) { + var me = this; + var hdstorage = me.getComponent('hdstorage'); + + // reset on disable + if (value) { + hdstorage.setValue(); + } + hdstorage.setDisabled(value); + + // disabling does not always fire this event and we do not need + // the value of the validity + hdstorage.fireEvent('validitychange'); + }, + + initComponent: function () { + var me = this; + + me.items = [ + { + xtype: 'pveStorageSelector', + itemId: 'hdstorage', + name: 'hdstorage', + fieldLabel: me.storageLabel, + nodename: me.nodename, + storageContent: me.storageContent, + disabled: me.disabled, + autoSelect: me.autoSelect, + allowBlank: me.allowBlank, + emptyText: me.emptyText, + listeners: { + change: { + fn: me.changeStorage, + scope: me, + }, + }, + }, + { + xtype: 'pveFileSelector', + name: 'hdimage', + itemId: 'hdimage', + fieldLabel: gettext('Disk image'), + nodename: me.nodename, + disabled: true, + hidden: true, + }, + { + xtype: 'numberfield', + itemId: 'disksize', + name: 'disksize', + fieldLabel: `${gettext('Disk size')} (${gettext('GiB')})`, + hidden: me.hideSize, + disabled: me.hideSize, + minValue: 0.001, + maxValue: 128 * 1024, + decimalPrecision: 3, + value: me.defaultSize, + allowBlank: false, + }, + { + xtype: 'pveDiskFormatSelector', + itemId: 'diskformat', + name: 'diskformat', + fieldLabel: gettext('Format'), + nodename: me.nodename, + disabled: true, + hidden: me.hideFormat || me.storageContent === 'rootdir', + value: 'qcow2', + allowBlank: false, + }, + ]; + + // use it to disable the children but not ourself + me.disabled = false; + + me.callParent(); + }, +}); diff --git a/www/manager6/lxc/MPResize.js b/www/manager6/lxc/MPResize.js new file mode 100644 index 0000000..658123a --- /dev/null +++ b/www/manager6/lxc/MPResize.js @@ -0,0 +1,96 @@ +Ext.define('PVE.window.MPResize', { + extend: 'Ext.window.Window', + + resizable: false, + + resize_disk: function (disk, size) { + var me = this; + var params = { disk: disk, size: '+' + size + 'G' }; + + Proxmox.Utils.API2Request({ + params: params, + url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/resize', + waitMsgTarget: me, + method: 'PUT', + failure: function (response, opts) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + }, + success: function (response, opts) { + var upid = response.result.data; + var win = Ext.create('Proxmox.window.TaskViewer', { upid: upid }); + win.show(); + me.close(); + }, + }); + }, + + initComponent: function () { + var me = this; + + if (!me.nodename) { + throw 'no node name specified'; + } + + if (!me.vmid) { + throw 'no VM ID specified'; + } + + var items = [ + { + xtype: 'displayfield', + name: 'disk', + value: me.disk, + fieldLabel: gettext('Disk'), + vtype: 'StorageId', + allowBlank: false, + }, + ]; + + me.hdsizesel = Ext.createWidget('numberfield', { + name: 'size', + minValue: 0, + maxValue: 128 * 1024, + decimalPrecision: 3, + value: '0', + fieldLabel: `${gettext('Size Increment')} (${gettext('GiB')})`, + allowBlank: false, + }); + + items.push(me.hdsizesel); + + me.formPanel = Ext.create('Ext.form.Panel', { + bodyPadding: 10, + border: false, + fieldDefaults: { + labelWidth: 120, + anchor: '100%', + }, + items: items, + }); + + var form = me.formPanel.getForm(); + + var submitBtn; + + me.title = gettext('Resize disk'); + submitBtn = Ext.create('Ext.Button', { + text: gettext('Resize disk'), + handler: function () { + if (form.isValid()) { + let values = form.getValues(); + me.resize_disk(me.disk, values.size); + } + }, + }); + + Ext.apply(me, { + modal: true, + border: false, + layout: 'fit', + buttons: [submitBtn], + items: [me.formPanel], + }); + + me.callParent(); + }, +}); diff --git a/www/manager6/qemu/HDResize.js b/www/manager6/qemu/HDResize.js new file mode 100644 index 0000000..574bfb5 --- /dev/null +++ b/www/manager6/qemu/HDResize.js @@ -0,0 +1,99 @@ +Ext.define('PVE.window.HDResize', { + extend: 'Ext.window.Window', + + resizable: false, + + resize_disk: function (disk, size) { + var me = this; + var params = { disk: disk, size: '+' + size + 'G' }; + + Proxmox.Utils.API2Request({ + params: params, + url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/resize', + waitMsgTarget: me, + method: 'PUT', + failure: function (response, opts) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + }, + success: function (response, options) { + Ext.create('Proxmox.window.TaskProgress', { + autoShow: true, + upid: response.result.data, + }); + me.close(); + }, + }); + }, + + initComponent: function () { + var me = this; + + if (!me.nodename) { + throw 'no node name specified'; + } + + if (!me.vmid) { + throw 'no VM ID specified'; + } + + var items = [ + { + xtype: 'displayfield', + name: 'disk', + value: me.disk, + fieldLabel: gettext('Disk'), + vtype: 'StorageId', + allowBlank: false, + }, + ]; + + me.hdsizesel = Ext.createWidget('numberfield', { + name: 'size', + minValue: 0, + maxValue: 128 * 1024, + decimalPrecision: 3, + value: '0', + fieldLabel: `${gettext('Size Increment')} (${gettext('GiB')})`, + allowBlank: false, + }); + + items.push(me.hdsizesel); + + me.formPanel = Ext.create('Ext.form.Panel', { + bodyPadding: 10, + border: false, + fieldDefaults: { + labelWidth: 140, + anchor: '100%', + }, + items: items, + }); + + var form = me.formPanel.getForm(); + + var submitBtn; + + me.title = gettext('Resize disk'); + submitBtn = Ext.create('Ext.Button', { + text: gettext('Resize disk'), + handler: function () { + if (form.isValid()) { + let values = form.getValues(); + me.resize_disk(me.disk, values.size); + } + }, + }); + + Ext.apply(me, { + modal: true, + width: 250, + height: 150, + border: false, + layout: 'fit', + buttons: [submitBtn], + items: [me.formPanel], + }); + + me.callParent(); + }, +});