* [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI
@ 2025-03-20 13:40 Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH storage v2 1/1] import: allow upload of qcow2 files into import storage Dominik Csapak
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Dominik Csapak @ 2025-03-20 13:40 UTC (permalink / raw)
To: pve-devel
most of the building blocks are already there:
* we can have qcow2 files in an import storage
* we can import qcow2 files via the api from such a storage
this series fills in the missing bits & pieces:
* allow uploading qcow2 files into an import storage via the webgui
* adding the possibility to select such a file when creating a vm/disk
We could maybe also allow this for raw/vmdk if we want to, but IMHO
we can start out with qcow2 and add the others as necssary.
(if wanted, I can of course also add the others in a next version or as
a follow up)
changes from v1:
* fixed an issue where the file selector would be hidden but invalid
pve-storage:
Dominik Csapak (1):
import: allow upload of qcow2 files into import storage
src/PVE/API2/Storage/Status.pm | 17 ++++++++++++++++-
src/PVE/Storage.pm | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
pve-manager:
Dominik Csapak (3):
ui: storage content: allow upload of qcow2 for import type
ui: form: file selector: allow optional filter
ui: qemu hd edit: allow importing a disk from the import storage
www/manager6/form/FileSelector.js | 10 ++++
www/manager6/qemu/HDEdit.js | 72 +++++++++++++++++++++++++-
www/manager6/window/UploadToStorage.js | 2 +-
3 files changed, 82 insertions(+), 2 deletions(-)
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH storage v2 1/1] import: allow upload of qcow2 files into import storage
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
@ 2025-03-20 13:40 ` Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 1/3] ui: storage content: allow upload of qcow2 for import type Dominik Csapak
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2025-03-20 13:40 UTC (permalink / raw)
To: pve-devel
so users can upload qcow2 files directly in the ui
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
no changes in v2:
src/PVE/API2/Storage/Status.pm | 17 ++++++++++++++++-
src/PVE/Storage.pm | 2 +-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/PVE/API2/Storage/Status.pm b/src/PVE/API2/Storage/Status.pm
index c854b53..b253392 100644
--- a/src/PVE/API2/Storage/Status.pm
+++ b/src/PVE/API2/Storage/Status.pm
@@ -456,6 +456,7 @@ __PACKAGE__->register_method ({
my $path;
my $isOva = 0;
+ my $isQcow2 = 0;
if ($content eq 'iso') {
if ($filename !~ m![^/]+$PVE::Storage::ISO_EXT_RE_0$!) {
@@ -472,7 +473,12 @@ __PACKAGE__->register_method ({
raise_param_exc({ filename => "invalid filename or wrong extension" });
}
- $isOva = 1;
+ if ($filename =~ m/\.ova$/) {
+ $isOva = 1;
+ } elsif ($filename =~ m/\.qcow2$/) {
+ $isQcow2 = 1;
+ }
+
$path = PVE::Storage::get_import_dir($cfg, $storage);
} else {
raise_param_exc({ content => "upload content type '$content' not allowed" });
@@ -543,6 +549,9 @@ __PACKAGE__->register_method ({
if ($isOva) {
assert_ova_contents($tmpfilename);
+ } elsif ($isQcow2) {
+ # checks untrusted image
+ PVE::Storage::file_size_info($tmpfilename, 10, 'qcow2', 1);
}
};
if (my $err = $@) {
@@ -667,6 +676,7 @@ __PACKAGE__->register_method({
my $path;
my $isOva = 0;
+ my $isQcow2 = 0;
if ($content eq 'iso') {
if ($filename !~ m![^/]+$PVE::Storage::ISO_EXT_RE_0$!) {
@@ -685,6 +695,8 @@ __PACKAGE__->register_method({
if ($filename =~ m/\.ova$/) {
$isOva = 1;
+ } elsif ($filename =~ m/\.qcow2$/) {
+ $isQcow2 = 1;
}
$path = PVE::Storage::get_import_dir($cfg, $storage);
@@ -717,6 +729,9 @@ __PACKAGE__->register_method({
if ($isOva) {
assert_ova_contents($tmp_path);
+ } elsif ($isQcow2) {
+ # checks untrusted image
+ PVE::Storage::file_size_info($tmp_path, 10, 'qcow2', 1);
}
};
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 3b4f041..deed73f 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -116,7 +116,7 @@ our $BACKUP_EXT_RE_2 = qr/\.(tgz|(?:tar|vma)(?:\.(${\PVE::Storage::Plugin::COMPR
our $IMPORT_EXT_RE_1 = qr/\.(ova|ovf|qcow2|raw|vmdk)/;
-our $UPLOAD_IMPORT_EXT_RE_1 = qr/\.(ova)/;
+our $UPLOAD_IMPORT_EXT_RE_1 = qr/\.(ova|qcow2)/;
our $SAFE_CHAR_CLASS_RE = qr/[a-zA-Z0-9\-\.\+\=\_]/;
our $SAFE_CHAR_WITH_WHITESPACE_CLASS_RE = qr/[ a-zA-Z0-9\-\.\+\=\_]/;
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH manager v2 1/3] ui: storage content: allow upload of qcow2 for import type
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH storage v2 1/1] import: allow upload of qcow2 files into import storage Dominik Csapak
@ 2025-03-20 13:40 ` Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 2/3] ui: form: file selector: allow optional filter Dominik Csapak
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2025-03-20 13:40 UTC (permalink / raw)
To: pve-devel
partially fixes #2424
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
no changes in v2
www/manager6/window/UploadToStorage.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/www/manager6/window/UploadToStorage.js b/www/manager6/window/UploadToStorage.js
index cdf548a8..3ce2d1f5 100644
--- a/www/manager6/window/UploadToStorage.js
+++ b/www/manager6/window/UploadToStorage.js
@@ -9,7 +9,7 @@ Ext.define('PVE.window.UploadToStorage', {
title: gettext('Upload'),
acceptedExtensions: {
- 'import': ['.ova'],
+ 'import': ['.ova', '.qcow2'],
iso: ['.img', '.iso'],
vztmpl: ['.tar.gz', '.tar.xz', '.tar.zst'],
},
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH manager v2 2/3] ui: form: file selector: allow optional filter
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH storage v2 1/1] import: allow upload of qcow2 files into import storage Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 1/3] ui: storage content: allow upload of qcow2 for import type Dominik Csapak
@ 2025-03-20 13:40 ` Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage Dominik Csapak
2025-03-25 15:16 ` [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2025-03-20 13:40 UTC (permalink / raw)
To: pve-devel
this sometimes comes in handy when we only want to show specific files.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
no changes in v2
www/manager6/form/FileSelector.js | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/www/manager6/form/FileSelector.js b/www/manager6/form/FileSelector.js
index ef2bedf9..9db20711 100644
--- a/www/manager6/form/FileSelector.js
+++ b/www/manager6/form/FileSelector.js
@@ -43,6 +43,13 @@ Ext.define('PVE.form.FileSelector', {
url: url,
});
+ if (Ext.isFunction(me.filter)) {
+ me.store.clearFilter();
+ me.store.addFilter([me.filter]);
+ } else {
+ me.store.clearFilter();
+ }
+
me.store.removeAll();
me.store.load();
},
@@ -60,6 +67,9 @@ Ext.define('PVE.form.FileSelector', {
valueField: 'volid',
displayField: 'text',
+ // An optional filter function
+ filter: undefined,
+
listConfig: {
width: 600,
columns: [
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
` (2 preceding siblings ...)
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 2/3] ui: form: file selector: allow optional filter Dominik Csapak
@ 2025-03-20 13:40 ` Dominik Csapak
2025-03-25 11:10 ` Filip Schauer
2025-03-25 15:16 ` [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
4 siblings, 1 reply; 7+ messages in thread
From: Dominik Csapak @ 2025-03-20 13:40 UTC (permalink / raw)
To: pve-devel
adds a checkbox 'import image' above the storage selector which:
* hides the original storage selector
* shows a 'source storage' selector
* shows a 'import file' selector
* shows a 'target storage' selector
Since the wizard and the hd edit share this panel, this also works in
the wizard.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* only enable the file selector if the storage selector is enabled
-> fixes an issue where it would be invalid but hidden, preventing
continuing
www/manager6/qemu/HDEdit.js | 72 ++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js
index b78647ec..aec23885 100644
--- a/www/manager6/qemu/HDEdit.js
+++ b/www/manager6/qemu/HDEdit.js
@@ -78,11 +78,17 @@ Ext.define('PVE.qemu.HDInputPanel', {
if (values.hdimage) {
me.drive.file = values.hdimage;
} else {
- me.drive.file = values.hdstorage + ":" + values.disksize;
+ let disksize = values.disksize;
+ if (values['import-from']) {
+ PVE.Utils.propertyStringSet(me.drive, values['import-from'], 'import-from');
+ disksize = 0;
+ }
+ me.drive.file = `${values.hdstorage}:${disksize}`;
}
me.drive.format = values.diskformat;
}
+
PVE.Utils.propertyStringSet(me.drive, !values.backup, 'backup', '0');
PVE.Utils.propertyStringSet(me.drive, values.noreplicate, 'replicate', 'no');
PVE.Utils.propertyStringSet(me.drive, values.discard, 'discard', 'on');
@@ -168,6 +174,11 @@ Ext.define('PVE.qemu.HDInputPanel', {
var me = this;
me.down('#hdstorage').setNodename(nodename);
me.down('#hdimage').setStorage(undefined, nodename);
+
+ me.lookup('new-disk').setNodename(nodename);
+ me.lookup('import-source').setNodename(nodename);
+ me.lookup('import-source-file').setNodename(nodename);
+ me.lookup('import-target').setNodename(nodename);
},
hasAdvanced: true,
@@ -221,12 +232,71 @@ Ext.define('PVE.qemu.HDInputPanel', {
column1.push(me.unusedDisks);
} else if (me.isCreate) {
column1.push({
+ xtype: 'proxmoxcheckbox',
+ isFormField: false,
+ fieldLabel: gettext("Import Image"),
+ listeners: {
+ change: function(_cb, value) {
+ me.lookup('new-disk').setVisible(!value);
+ me.lookup('new-disk').setDisabled(!!value);
+
+ me.lookup('import-source').setVisible(!!value);
+ me.lookup('import-source').setDisabled(!value);
+ me.lookup('import-source-file').setVisible(!!value);
+
+ me.lookup('import-target').setVisible(!!value);
+ me.lookup('import-target').setDisabled(!value);
+ },
+ },
+ });
+ column1.push({
+ reference: 'new-disk',
xtype: 'pveDiskStorageSelector',
storageContent: 'images',
name: 'disk',
nodename: me.nodename,
autoSelect: me.insideWizard,
});
+ column1.push({
+ xtype: 'pveStorageSelector',
+ reference: 'import-source',
+ fieldLabel: gettext('Import Storage'),
+ name: 'import-source-storage',
+ hidden: true,
+ disabled: true,
+ storageContent: 'import',
+ nodename: me.nodename,
+ autoSelect: me.insideWizard,
+ listeners: {
+ change: function(selector, storage) {
+ me.lookup('import-source-file').setStorage(storage);
+ me.lookup('import-source-file').setDisabled(!storage || selector.isDisabled());
+ },
+ },
+ });
+ column1.push({
+ xtype: 'pveFileSelector',
+ reference: 'import-source-file',
+ fieldLabel: gettext("Select Image"),
+ hidden: true,
+ disabled: true,
+ storageContent: 'import',
+ name: 'import-from',
+ filter: (rec) => rec?.data?.format === 'qcow2',
+ nodename: me.nodename,
+ });
+ column1.push({
+ xtype: 'pveDiskStorageSelector',
+ reference: 'import-target',
+ storageLabel: gettext('Target Storage'),
+ hidden: true,
+ disabled: true,
+ hideSize: true,
+ storageContent: 'images',
+ name: 'target',
+ nodename: me.nodename,
+ autoSelect: me.insideWizard,
+ });
} else {
column1.push({
xtype: 'textfield',
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage Dominik Csapak
@ 2025-03-25 11:10 ` Filip Schauer
0 siblings, 0 replies; 7+ messages in thread
From: Filip Schauer @ 2025-03-25 11:10 UTC (permalink / raw)
To: pve-devel
The bug from before is solved, but instead a different bug has appeared:
When I enable the "Import Image" checkbox on the "Disks" tab of the
virtual machine creation wizard, the "Select Image" selector is disabled
by default. It can be enabled by switching the import storage.
On 20/03/2025 14:40, Dominik Csapak wrote:
> + fieldLabel: gettext("Import Image"),
> + listeners: {
> + change: function(_cb, value) {
> + me.lookup('new-disk').setVisible(!value);
> + me.lookup('new-disk').setDisabled(!!value);
> +
> + me.lookup('import-source').setVisible(!!value);
> + me.lookup('import-source').setDisabled(!value);
> + me.lookup('import-source-file').setVisible(!!value);
> +
> + me.lookup('import-target').setVisible(!!value);
> + me.lookup('import-target').setDisabled(!value);
> + },
It seems this can be fixed by adding:
me.lookup('import-source-file').setDisabled(!value);
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
` (3 preceding siblings ...)
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage Dominik Csapak
@ 2025-03-25 15:16 ` Dominik Csapak
4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2025-03-25 15:16 UTC (permalink / raw)
To: pve-devel
sent a v3:
https://lore.proxmox.com/pve-devel/20250325151421.3182493-1-d.csapak@proxmox.com/
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-03-25 15:16 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-20 13:40 [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH storage v2 1/1] import: allow upload of qcow2 files into import storage Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 1/3] ui: storage content: allow upload of qcow2 for import type Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 2/3] ui: form: file selector: allow optional filter Dominik Csapak
2025-03-20 13:40 ` [pve-devel] [PATCH manager v2 3/3] ui: qemu hd edit: allow importing a disk from the import storage Dominik Csapak
2025-03-25 11:10 ` Filip Schauer
2025-03-25 15:16 ` [pve-devel] [PATCH storage/manager v2] allow upload & import of qcow2 in the web UI 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