public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH manager] fix #5871: ui: resize disk: show current and new size
@ 2026-10-16 10:07 Michal Fox
  0 siblings, 0 replies; only message in thread
From: Michal Fox @ 2026-10-16 10:07 UTC (permalink / raw)
  To: pve-devel

The resize dialogs of VMs and containers only ask for the size
increment, so users have to look up the current size of the disk in
the config to know which size the disk will have afterwards.

Load the config of the guest in the dialogs and show the current size
of the disk, and the size it will have with the entered increment,
which gets updated while typing. As the dialogs load the size
themselves, callers do not need to change.

The size of the config is in the 'disk-size' format, where the units
are binary, while Proxmox.Utils.parse_size_unit() takes 'G' as GB, so
add a small parser for it, like parse_size() of PVE::JSONSchema.

Signed-off-by: Michal Fox <me@dualfroz.com>
---
Tested in the browser with both dialogs and mocked API calls, for
disks with the sizes '32G', '528K', '16896', '1.5T' and '10GiB', a
passed through disk without size, and a container's rootfs and mount
point: the current size is shown ('Unknown' without size), the new size
follows the increment and is empty for an invalid one, and the resize
request is the same as before, for example '+2.5G'. The fixed height of
the VM dialog is dropped, as it cut off the new rows.

This does not touch the callers, so it should not conflict with the
series splitting out the disks into their own grid, which opens the
dialog the same way.

The shown sizes are based on the size in the config, like in the
hardware view, while the API adds the increment to the actual size of
the volume. These only differ if the config is out of date.

 www/manager6/Utils.js         | 10 +++++++++
 www/manager6/lxc/MPResize.js  | 41 ++++++++++++++++++++++++++++++++++
 www/manager6/qemu/HDResize.js | 42 ++++++++++++++++++++++++++++++++++-
 3 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 8b99371d..a9260ec6 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1148,6 +1148,16 @@ Ext.define('PVE.Utils', {
             return `${per.toFixed(1)}% of ${maxcpu} ${cpu_label}`;
         },
 
+        // parses a size in the 'disk-size' format of the API, like '32G', into bytes
+        parse_disk_size: function (value) {
+            let match = /^(\d+(?:\.\d+)?)(?:([KMGT])(?:iB)?)?$/.exec(value);
+            if (!match) {
+                return undefined;
+            }
+            let exponent = ['', 'K', 'M', 'G', 'T'].indexOf(match[2] ?? '');
+            return parseFloat(match[1]) * 1024 ** exponent;
+        },
+
         render_bandwidth: function (value) {
             if (!Ext.isNumeric(value)) {
                 return '';
diff --git a/www/manager6/lxc/MPResize.js b/www/manager6/lxc/MPResize.js
index 658123a1..ec56adb1 100644
--- a/www/manager6/lxc/MPResize.js
+++ b/www/manager6/lxc/MPResize.js
@@ -24,6 +24,17 @@ Ext.define('PVE.window.MPResize', {
         });
     },
 
+    updateNewSize: function () {
+        let me = this;
+        let newSize = '';
+        if (me.currentSize !== undefined && me.hdsizesel.isValid()) {
+            newSize = Proxmox.Utils.format_size(
+                me.currentSize + me.hdsizesel.getValue() * 1024 ** 3,
+            );
+        }
+        me.down('#newSize').setValue(newSize);
+    },
+
     initComponent: function () {
         var me = this;
 
@@ -44,6 +55,11 @@ Ext.define('PVE.window.MPResize', {
                 vtype: 'StorageId',
                 allowBlank: false,
             },
+            {
+                xtype: 'displayfield',
+                itemId: 'currentSize',
+                fieldLabel: gettext('Current Size'),
+            },
         ];
 
         me.hdsizesel = Ext.createWidget('numberfield', {
@@ -54,9 +70,17 @@ Ext.define('PVE.window.MPResize', {
             value: '0',
             fieldLabel: `${gettext('Size Increment')} (${gettext('GiB')})`,
             allowBlank: false,
+            listeners: {
+                change: () => me.updateNewSize(),
+            },
         });
 
         items.push(me.hdsizesel);
+        items.push({
+            xtype: 'displayfield',
+            itemId: 'newSize',
+            fieldLabel: gettext('New Size'),
+        });
 
         me.formPanel = Ext.create('Ext.form.Panel', {
             bodyPadding: 10,
@@ -92,5 +116,22 @@ Ext.define('PVE.window.MPResize', {
         });
 
         me.callParent();
+
+        Proxmox.Utils.API2Request({
+            url: `/nodes/${me.nodename}/lxc/${me.vmid}/config`,
+            method: 'GET',
+            waitMsgTarget: me,
+            failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+            success: function (response) {
+                let size = PVE.Parser.parseLxcMountPoint(response.result.data[me.disk])?.size;
+                me.currentSize = size ? PVE.Utils.parse_disk_size(size) : undefined;
+                me.down('#currentSize').setValue(
+                    me.currentSize !== undefined
+                        ? Proxmox.Utils.format_size(me.currentSize)
+                        : Proxmox.Utils.unknownText,
+                );
+                me.updateNewSize();
+            },
+        });
     },
 });
diff --git a/www/manager6/qemu/HDResize.js b/www/manager6/qemu/HDResize.js
index 574bfb5a..4c2ac581 100644
--- a/www/manager6/qemu/HDResize.js
+++ b/www/manager6/qemu/HDResize.js
@@ -25,6 +25,17 @@ Ext.define('PVE.window.HDResize', {
         });
     },
 
+    updateNewSize: function () {
+        let me = this;
+        let newSize = '';
+        if (me.currentSize !== undefined && me.hdsizesel.isValid()) {
+            newSize = Proxmox.Utils.format_size(
+                me.currentSize + me.hdsizesel.getValue() * 1024 ** 3,
+            );
+        }
+        me.down('#newSize').setValue(newSize);
+    },
+
     initComponent: function () {
         var me = this;
 
@@ -45,6 +56,11 @@ Ext.define('PVE.window.HDResize', {
                 vtype: 'StorageId',
                 allowBlank: false,
             },
+            {
+                xtype: 'displayfield',
+                itemId: 'currentSize',
+                fieldLabel: gettext('Current Size'),
+            },
         ];
 
         me.hdsizesel = Ext.createWidget('numberfield', {
@@ -55,9 +71,17 @@ Ext.define('PVE.window.HDResize', {
             value: '0',
             fieldLabel: `${gettext('Size Increment')} (${gettext('GiB')})`,
             allowBlank: false,
+            listeners: {
+                change: () => me.updateNewSize(),
+            },
         });
 
         items.push(me.hdsizesel);
+        items.push({
+            xtype: 'displayfield',
+            itemId: 'newSize',
+            fieldLabel: gettext('New Size'),
+        });
 
         me.formPanel = Ext.create('Ext.form.Panel', {
             bodyPadding: 10,
@@ -87,7 +111,6 @@ Ext.define('PVE.window.HDResize', {
         Ext.apply(me, {
             modal: true,
             width: 250,
-            height: 150,
             border: false,
             layout: 'fit',
             buttons: [submitBtn],
@@ -95,5 +118,22 @@ Ext.define('PVE.window.HDResize', {
         });
 
         me.callParent();
+
+        Proxmox.Utils.API2Request({
+            url: `/nodes/${me.nodename}/qemu/${me.vmid}/config`,
+            method: 'GET',
+            waitMsgTarget: me,
+            failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+            success: function (response) {
+                let size = PVE.Parser.parseQemuDrive(me.disk, response.result.data[me.disk])?.size;
+                me.currentSize = size ? PVE.Utils.parse_disk_size(size) : undefined;
+                me.down('#currentSize').setValue(
+                    me.currentSize !== undefined
+                        ? Proxmox.Utils.format_size(me.currentSize)
+                        : Proxmox.Utils.unknownText,
+                );
+                me.updateNewSize();
+            },
+        });
     },
 });
-- 
2.43.0




^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-16 10:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 10:07 [PATCH manager] fix #5871: ui: resize disk: show current and new size Michal Fox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal