This is actually broken, sorry. I'm just fixing it. But clicking through the 
wizard should work.

On Thu, Nov 19, 2020 at 10:46:18AM +0100, Dominic Jäger wrote:
> Make importing single disks easier.
> Required to import a whole VM via GUI.
> 
> Signed-off-by: Dominic Jäger <d.jae...@proxmox.com>
> ---
>  www/manager6/qemu/HDEdit.js       | 134 ++++++++++++++++++++++++++----
>  www/manager6/qemu/HardwareView.js |  24 ++++++
>  2 files changed, 141 insertions(+), 17 deletions(-)
> 
> diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js
> index e2a5b914..5e0a3981 100644
> --- a/www/manager6/qemu/HDEdit.js
> +++ b/www/manager6/qemu/HDEdit.js
> @@ -67,7 +67,8 @@ Ext.define('PVE.qemu.HDInputPanel', {
>       if (me.unused) {
>           me.drive.file = me.vmconfig[values.unusedId];
>           confid = values.controller + values.deviceid;
> -     } else if (me.isCreate) {
> +     } else if (me.isCreate && !me.isImport) {
> +         // disk format & size should not be part of propertyString for 
> import
>           if (values.hdimage) {
>               me.drive.file = values.hdimage;
>           } else {
> @@ -83,16 +84,22 @@ Ext.define('PVE.qemu.HDInputPanel', {
>       PVE.Utils.propertyStringSet(me.drive, values.iothread, 'iothread', 
> 'on');
>       PVE.Utils.propertyStringSet(me.drive, values.cache, 'cache');
>  
> -        var names = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr'];
> -        Ext.Array.each(names, function(name) {
> -            var burst_name = name + '_max';
> +     var names = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr'];
> +     Ext.Array.each(names, function(name) {
> +         var burst_name = name + '_max';
>           PVE.Utils.propertyStringSet(me.drive, values[name], name);
>           PVE.Utils.propertyStringSet(me.drive, values[burst_name], 
> burst_name);
> -        });
> -
> -
> -     params[confid] = PVE.Parser.printQemuDrive(me.drive);
> -
> +     });
> +     if (me.isImport) {
> +         params.device_options = PVE.Parser.printPropertyString(me.drive);
> +         params.source = values.sourceType === 'storage'
> +             ? values.sourceVolid : values.sourcePath;
> +         params.device = values.controller + values.deviceid;
> +         params.storage = values.hdstorage;
> +         if (values.diskformat) params.format = values.diskformat;
> +     } else {
> +         params[confid] = PVE.Parser.printQemuDrive(me.drive);
> +     }
>       return params;
>      },
>  
> @@ -169,10 +176,14 @@ Ext.define('PVE.qemu.HDInputPanel', {
>       me.advancedColumn2 = [];
>  
>       if (!me.confid || me.unused) {
> +         let controllerColumn = me.isImport ? me.column2 : me.column1;
>           me.bussel = Ext.create('PVE.form.ControllerSelector', {
>               vmconfig: me.insideWizard ? {ide2: 'cdrom'} : {}
>           });
> -         me.column1.push(me.bussel);
> +         if (me.isImport) {
> +             me.bussel.fieldLabel = 'Target Device';
> +         }
> +         controllerColumn.push(me.bussel);
>  
>           me.scsiController = Ext.create('Ext.form.field.Display', {
>               fieldLabel: gettext('SCSI Controller'),
> @@ -184,7 +195,7 @@ Ext.define('PVE.qemu.HDInputPanel', {
>               submitValue: false,
>               hidden: true
>           });
> -         me.column1.push(me.scsiController);
> +         controllerColumn.push(me.scsiController);
>       }
>  
>       if (me.unused) {
> @@ -199,14 +210,21 @@ Ext.define('PVE.qemu.HDInputPanel', {
>               allowBlank: false
>           });
>           me.column1.push(me.unusedDisks);
> -     } else if (me.isCreate) {
> -         me.column1.push({
> +     } else if (me.isCreate || me.isImport) {
> +         let selector = {
>               xtype: 'pveDiskStorageSelector',
>               storageContent: 'images',
>               name: 'disk',
>               nodename: me.nodename,
> -             autoSelect: me.insideWizard
> -         });
> +             hideSize: me.isImport,
> +             autoSelect: me.insideWizard || me.isImport,
> +         };
> +         if (me.isImport) {
> +             selector.storageLabel = gettext('Target storage');
> +             me.column2.push(selector);
> +         } else {
> +             me.column1.push(selector);
> +         }
>       } else {
>           me.column1.push({
>               xtype: 'textfield',
> @@ -217,6 +235,12 @@ Ext.define('PVE.qemu.HDInputPanel', {
>           });
>       }
>  
> +     if (me.isImport) {
> +         me.column2.push({
> +             xtype: 'box',
> +             autoEl: { tag: 'hr' },
> +         });
> +     }
>       me.column2.push(
>           {
>               xtype: 'CacheTypeSelector',
> @@ -231,6 +255,74 @@ Ext.define('PVE.qemu.HDInputPanel', {
>               name: 'discard'
>           }
>       );
> +     if (me.isImport) {
> +         let show = (element, value) => {
> +             element.setHidden(!value);
> +             element.setDisabled(!value);
> +         };
> +         me.sourceRadioStorage = Ext.create('Ext.form.field.Radio', {
> +             name: 'sourceType',
> +             inputValue: 'storage',
> +             boxLabel: gettext('Use a storage as source'),
> +             checked: true,
> +             hidden: Proxmox.UserName !== 'root@pam',
> +             listeners: {
> +                 added: () => show(me.sourcePathTextfield, false),
> +                 change: (_, storageRadioChecked) => {
> +                     show(me.sourcePathTextfield, !storageRadioChecked);
> +                     let selectors = [
> +                         me.sourceStorageSelector,
> +                         me.sourceFileSelector,
> +                     ];
> +                     for (const selector of selectors) {
> +                         show(selector, storageRadioChecked);
> +                     }
> +                 },
> +             },
> +         });
> +         me.sourceStorageSelector = Ext.create('PVE.form.StorageSelector', {
> +             name: 'inputImageStorage',
> +             nodename: me.nodename,
> +             fieldLabel: gettext('Source Storage'),
> +             storageContent: 'images',
> +             autoSelect: me.insideWizard,
> +             listeners: {
> +                 change: function(_, selectedStorage) {
> +                     me.sourceFileSelector.setStorage(selectedStorage);
> +                 },
> +             },
> +         });
> +         me.sourceFileSelector = Ext.create('PVE.form.FileSelector', {
> +             name: 'sourceVolid',
> +             nodename: me.nodename,
> +             storageContent: 'images',
> +             fieldLabel: gettext('Source Image'),
> +         });
> +         me.sourceRadioPath = Ext.create('Ext.form.field.Radio', {
> +             name: 'sourceType',
> +             inputValue: 'path',
> +             boxLabel: gettext('Use an absolute path as source'),
> +             hidden: Proxmox.UserName !== 'root@pam',
> +         });
> +         me.sourcePathTextfield = Ext.create('Ext.form.field.Text', {
> +             xtype: 'textfield',
> +             fieldLabel: gettext('Source Path'),
> +             name: 'sourcePath',
> +             emptyText: '/home/user/disk.qcow2',
> +             hidden: Proxmox.UserName !== 'root@pam',
> +             validator: function(insertedText) {
> +                 return insertedText.startsWith('/') ||
> +                     gettext('Must be an absolute path');
> +             },
> +         });
> +         me.column1.unshift(
> +             me.sourceRadioStorage,
> +             me.sourceStorageSelector,
> +             me.sourceFileSelector,
> +             me.sourceRadioPath,
> +             me.sourcePathTextfield,
> +         );
> +     }
>  
>       me.advancedColumn1.push(
>           {
> @@ -372,14 +464,19 @@ Ext.define('PVE.qemu.HDEdit', {
>           confid: me.confid,
>           nodename: nodename,
>           unused: unused,
> -         isCreate: me.isCreate
> +         isCreate: me.isCreate,
> +         isImport: me.isImport,
>       });
>  
>       var subject;
>       if (unused) {
>           me.subject = gettext('Unused Disk');
> +     } else if (me.isImport) {
> +         me.subject = gettext('Import Disk');
> +         me.submitText = 'Import';
> +         me.backgroundDelay = undefined;
>       } else if (me.isCreate) {
> -            me.subject = gettext('Hard Disk');
> +         me.subject = gettext('Hard Disk');
>       } else {
>             me.subject = gettext('Hard Disk') + ' (' + me.confid + ')';
>       }
> @@ -404,6 +501,9 @@ Ext.define('PVE.qemu.HDEdit', {
>                   ipanel.setDrive(drive);
>                   me.isValid(); // trigger validation
>               }
> +             if (me.isImport) {
> +                 me.url = me.url.replace(/\/config$/, "/importdisk");
> +             }
>           }
>       });
>      }
> diff --git a/www/manager6/qemu/HardwareView.js 
> b/www/manager6/qemu/HardwareView.js
> index 40b3fe86..dc5e217e 100644
> --- a/www/manager6/qemu/HardwareView.js
> +++ b/www/manager6/qemu/HardwareView.js
> @@ -436,6 +436,29 @@ Ext.define('PVE.qemu.HardwareView', {
>           handler: run_move
>       });
>  
> +     var import_btn = new Proxmox.button.Button({
> +         text: gettext('Import disk'),
> +         hidden: !(
> +             caps.storage['Datastore.Audit'] &&
> +             caps.storage['Datastore.Allocate'] &&
> +             caps.storage['Datastore.AllocateTemplate'] &&
> +             caps.storage['Datastore.AllocateSpace'] &&
> +             caps.vms['VM.Allocate'] &&
> +             caps.vms['VM.Config.Disk'] &&
> +             true
> +         ),
> +         handler: function() {
> +             var win = Ext.create('PVE.qemu.HDEdit', {
> +                 method: 'POST',
> +                 url: `/api2/extjs/${baseurl}`,
> +                 pveSelNode: me.pveSelNode,
> +                 isImport: true,
> +             });
> +             win.on('destroy', me.reload, me);
> +             win.show();
> +         },
> +     });
> +
>       var remove_btn = new Proxmox.button.Button({
>           text: gettext('Remove'),
>           defaultText: gettext('Remove'),
> @@ -752,6 +775,7 @@ Ext.define('PVE.qemu.HardwareView', {
>               edit_btn,
>               resize_btn,
>               move_btn,
> +             import_btn,
>               revert_btn
>           ],
>           rows: rows,
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to