public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import
@ 2026-09-29 13:58 Michal Fox
  2026-09-29 13:58 ` [PATCH manager 1/2] fix #8015: ui: upload: let the user choose the .img image format Michal Fox
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michal Fox @ 2026-09-29 13:58 UTC (permalink / raw)
  To: pve-devel

.img files uploaded or downloaded as import content always got '.raw'
appended, so qcow2 images with that extension, like the Ubuntu cloud
images, were imported as raw disks and did not boot (#8015). as Fiona
suggested in the bug, the user now selects the format explicitly: a
format selector shows up for .img files and its extension is appended
instead. the upload/download stays disabled until a format is chosen.

tested with the built pvemanagerlib.js in a browser for both windows:
a .img file shows the selector and gets .qcow2 or .raw appended
depending on the choice, other extensions do not show it.

Michal Fox (2):
  fix #8015: ui: upload: let the user choose the .img image format
  fix #8015: ui: download url: let the user choose the .img image format

 www/manager6/window/DownloadUrlToStorage.js | 32 +++++++++++++--
 www/manager6/window/UploadToStorage.js      | 45 +++++++++++++++------
 2 files changed, 62 insertions(+), 15 deletions(-)

-- 
2.43.0




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH manager 1/2] fix #8015: ui: upload: let the user choose the .img image format
  2026-09-29 13:58 [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Michal Fox
@ 2026-09-29 13:58 ` Michal Fox
  2026-09-29 13:58 ` [PATCH manager 2/2] fix #8015: ui: download url: " Michal Fox
  2026-09-30 10:27 ` applied: [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Dominik Csapak
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Fox @ 2026-09-29 13:58 UTC (permalink / raw)
  To: pve-devel

When uploading a '.img' file as import content, '.raw' is appended to
the file name, so the image is always treated as a raw image. But the
'.img' extension is also commonly used for other formats, for example
the Ubuntu cloud images are qcow2 images. Such an image is then
imported as raw disk, which results in a disk with the size of the
qcow2 file and a guest that does not boot.

The format cannot be derived from the '.img' extension, so show a
format selector for such files and only append the extension of the
selected format to the file name. The upload stays disabled until a
format is selected, so the choice is always an explicit one.

Signed-off-by: Michal Fox <me@dualfroz.com>
---
 www/manager6/window/UploadToStorage.js | 45 +++++++++++++++++++-------
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/www/manager6/window/UploadToStorage.js b/www/manager6/window/UploadToStorage.js
index cc53596d..54af1603 100644
--- a/www/manager6/window/UploadToStorage.js
+++ b/www/manager6/window/UploadToStorage.js
@@ -14,11 +14,10 @@ Ext.define('PVE.window.UploadToStorage', {
         vztmpl: ['.tar.gz', '.tar.xz', '.tar.zst'],
     },
 
-    // accepted for file selection, will be renamed to real extension
-    extensionAliases: {
-        import: {
-            '.img': '.raw',
-        },
+    // accepted for file selection, but the extension does not tell the image format, so the user
+    // has to select it and it gets appended as real extension
+    formatAliases: {
+        import: ['.img'],
     },
 
     cbindData: function (initialConfig) {
@@ -27,7 +26,7 @@ Ext.define('PVE.window.UploadToStorage', {
 
         me.url = `/nodes/${me.nodename}/storage/${me.storage}/upload`;
 
-        let fileSelectorExt = ext.concat(Object.keys(me.extensionAliases[me.content] ?? {}));
+        let fileSelectorExt = ext.concat(me.formatAliases[me.content] ?? []);
 
         return {
             extensions: fileSelectorExt.join(', '),
@@ -40,6 +39,7 @@ Ext.define('PVE.window.UploadToStorage', {
             size: '-',
             mimetype: '-',
             filename: '',
+            needsFormat: false,
         },
     },
 
@@ -154,12 +154,12 @@ Ext.define('PVE.window.UploadToStorage', {
             const me = this;
             const vm = me.getViewModel();
             const view = me.getView();
-            let name = input.value.replace(/^.*(\/|\\)/, '');
-            for (const [alias, real] of Object.entries(view.extensionAliases[view.content] ?? {})) {
-                if (name.endsWith(alias)) {
-                    name += real;
-                }
-            }
+            const name = input.value.replace(/^.*(\/|\\)/, '');
+            const aliases = view.formatAliases[view.content] ?? [];
+            const needsFormat = aliases.some((alias) => name.endsWith(alias));
+            me.selectedName = name;
+            vm.set('needsFormat', needsFormat);
+            me.lookup('imageFormat').setValue(null);
             const fileInput = input.fileInputEl.dom;
             vm.set('filename', name);
             vm.set(
@@ -178,6 +178,12 @@ Ext.define('PVE.window.UploadToStorage', {
                 checksum.setDisabled(false);
             }
         },
+
+        formatChange: function (field, format) {
+            if (format) {
+                this.getViewModel().set('filename', `${this.selectedName}.${format}`);
+            }
+        },
     },
 
     items: [
@@ -220,6 +226,21 @@ Ext.define('PVE.window.UploadToStorage', {
                     },
                     regexText: gettext('Wrong file extension'),
                 },
+                {
+                    xtype: 'pveDiskFormatSelector',
+                    reference: 'imageFormat',
+                    fieldLabel: gettext('Format'),
+                    allowBlank: false,
+                    hidden: true,
+                    disabled: true,
+                    bind: {
+                        hidden: '{!needsFormat}',
+                        disabled: '{!needsFormat}',
+                    },
+                    listeners: {
+                        change: 'formatChange',
+                    },
+                },
                 {
                     xtype: 'displayfield',
                     name: 'size',
-- 
2.43.0




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH manager 2/2] fix #8015: ui: download url: let the user choose the .img image format
  2026-09-29 13:58 [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Michal Fox
  2026-09-29 13:58 ` [PATCH manager 1/2] fix #8015: ui: upload: let the user choose the .img image format Michal Fox
@ 2026-09-29 13:58 ` Michal Fox
  2026-09-30 10:27 ` applied: [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Dominik Csapak
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Fox @ 2026-09-29 13:58 UTC (permalink / raw)
  To: pve-devel

Like for the upload, '.raw' was appended to the name of '.img' images
downloaded as import content, which breaks importing images in other
formats, such as the qcow2 based Ubuntu cloud images.

After querying the URL of such an image, show a format selector and
append the extension of the selected format to the file name instead.

Signed-off-by: Michal Fox <me@dualfroz.com>
---
 www/manager6/window/DownloadUrlToStorage.js | 32 +++++++++++++++++++--
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/www/manager6/window/DownloadUrlToStorage.js b/www/manager6/window/DownloadUrlToStorage.js
index f1c4392c..be31fb59 100644
--- a/www/manager6/window/DownloadUrlToStorage.js
+++ b/www/manager6/window/DownloadUrlToStorage.js
@@ -30,6 +30,7 @@ Ext.define('PVE.window.DownloadUrlToStorage', {
             size: '-',
             mimetype: '-',
             enableQuery: true,
+            needsFormat: false,
         },
     },
 
@@ -82,6 +83,7 @@ Ext.define('PVE.window.DownloadUrlToStorage', {
 
                     let filename = data.filename || '';
                     let compression = '__default__';
+                    let needsFormat = false;
                     if (view.content === 'iso') {
                         const matches = filename.match(/^(.+)\.(gz|lzo|zst|bz2)$/i);
                         if (matches) {
@@ -89,10 +91,12 @@ Ext.define('PVE.window.DownloadUrlToStorage', {
                             compression = matches[2].toLowerCase();
                         }
                     } else if (view.content === 'import') {
-                        if (filename.endsWith('.img')) {
-                            filename += '.raw';
-                        }
+                        // the extension does not tell the image format, the user has to select it
+                        needsFormat = filename.endsWith('.img');
                     }
+                    me.queriedName = filename;
+                    me.getViewModel().set('needsFormat', needsFormat);
+                    me.lookup('imageFormat').setValue(null);
 
                     view.setValues({
                         filename,
@@ -106,6 +110,12 @@ Ext.define('PVE.window.DownloadUrlToStorage', {
             });
         },
 
+        formatChange: function (field, format) {
+            if (format) {
+                this.getView().setValues({ filename: `${this.queriedName}.${format}` });
+            }
+        },
+
         hashChange: function (field) {
             let checksum = Ext.getCmp('downloadUrlChecksum');
             if (field.getValue() === '__default__') {
@@ -169,6 +179,22 @@ Ext.define('PVE.window.DownloadUrlToStorage', {
                         return this.processRawValue(this.getRawValue())?.trim();
                     },
                 },
+                {
+                    xtype: 'pveDiskFormatSelector',
+                    reference: 'imageFormat',
+                    fieldLabel: gettext('Format'),
+                    submitValue: false,
+                    allowBlank: false,
+                    hidden: true,
+                    disabled: true,
+                    bind: {
+                        hidden: '{!needsFormat}',
+                        disabled: '{!needsFormat}',
+                    },
+                    listeners: {
+                        change: 'formatChange',
+                    },
+                },
             ],
             column1: [
                 {
-- 
2.43.0




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* applied: [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import
  2026-09-29 13:58 [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Michal Fox
  2026-09-29 13:58 ` [PATCH manager 1/2] fix #8015: ui: upload: let the user choose the .img image format Michal Fox
  2026-09-29 13:58 ` [PATCH manager 2/2] fix #8015: ui: download url: " Michal Fox
@ 2026-09-30 10:27 ` Dominik Csapak
  2 siblings, 0 replies; 4+ messages in thread
From: Dominik Csapak @ 2026-09-30 10:27 UTC (permalink / raw)
  To: pve-devel, Michal Fox

On Tue, 29 Sep 2026 15:58:38 +0200, Michal Fox wrote:
> .img files uploaded or downloaded as import content always got '.raw'
> appended, so qcow2 images with that extension, like the Ubuntu cloud
> images, were imported as raw disks and did not boot (#8015). as Fiona
> suggested in the bug, the user now selects the format explicitly: a
> format selector shows up for .img files and its extension is appended
> instead. the upload/download stays disabled until a format is chosen.
> 
> [...]

Applied, thanks!

[1/2] fix #8015: ui: upload: let the user choose the .img image format
      commit: 2380c3df6742aee91e9519a4a5c0aff4f3c6a350
[2/2] fix #8015: ui: download url: let the user choose the .img image format
      commit: ebf648ddce2ec255ff5d0ee85f456f4a64d8e020




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-30 10:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29 13:58 [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Michal Fox
2026-09-29 13:58 ` [PATCH manager 1/2] fix #8015: ui: upload: let the user choose the .img image format Michal Fox
2026-09-29 13:58 ` [PATCH manager 2/2] fix #8015: ui: download url: " Michal Fox
2026-09-30 10:27 ` applied: [PATCH manager 0/2] fix #8015: ui: let the user choose the .img image format for import Dominik Csapak

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