From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id BBD4B6707B for ; Wed, 29 Jul 2020 15:25:04 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id AD809EF64 for ; Wed, 29 Jul 2020 15:25:04 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id B4C01EF5A for ; Wed, 29 Jul 2020 15:25:03 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 77DD7433CF for ; Wed, 29 Jul 2020 15:25:03 +0200 (CEST) To: pve-devel@lists.proxmox.com References: <20200707100412.81731-1-d.jaeger@proxmox.com> <20200707100412.81731-3-d.jaeger@proxmox.com> From: Aaron Lauterer Message-ID: <2405749c-bc36-0a9a-0302-5d73a307b93a@proxmox.com> Date: Wed, 29 Jul 2020 15:25:02 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.0.1 MIME-Version: 1.0 In-Reply-To: <20200707100412.81731-3-d.jaeger@proxmox.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.467 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment NICE_REPLY_A -0.951 Looks like a legit reply (A) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [params.storage, caps.storage] Subject: Re: [pve-devel] [PATCH manager 2/3] Hardware View: Add GUI for importdisk X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Jul 2020 13:25:04 -0000 Some thing inline. On 7/7/20 12:04 PM, Dominic Jäger wrote: > Make importing single disks easier. > Required to import a whole VM via GUI. > > Signed-off-by: Dominic Jäger > --- > www/manager6/qemu/HDEdit.js | 80 ++++++++++++++++++++++--------- > www/manager6/qemu/HardwareView.js | 18 +++++++ > 2 files changed, 76 insertions(+), 22 deletions(-) > > diff --git a/www/manager6/qemu/HDEdit.js b/www/manager6/qemu/HDEdit.js > index e2a5b914..7f6a7b2b 100644 > --- a/www/manager6/qemu/HDEdit.js > +++ b/www/manager6/qemu/HDEdit.js > @@ -76,23 +76,43 @@ Ext.define('PVE.qemu.HDInputPanel', { > 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'); > - PVE.Utils.propertyStringSet(me.drive, values.ssd, 'ssd', 'on'); > - 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'; > - 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) { > + // These keys & values are accepted by the API as they are > + let simple = ['backup', 'ssd', 'iothread', 'cache']; > + let burst = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr']; > + burst = burst.concat(burst.map(x => `${x}_max`)); > + let available = simple.concat(burst); > + let addValues = key => `${key}=${values[key]}`; > + let selectedKeys = x => values[x]; > + let options = available.filter(selectedKeys).map(addValues).join(); > + // These need modification for the API > + options += values.discard ? ',discard=on' : ''; > + options += values.noreplicate ? ',replicate=0' : ''; > + params.device_options = options; One or two newlines in the above block would be nice to make the distinction between the logical blocks more obvious. > + } else { > + 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'); > + PVE.Utils.propertyStringSet(me.drive, values.ssd, 'ssd', 'on'); > + 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'; > + PVE.Utils.propertyStringSet(me.drive, values[name], name); > + PVE.Utils.propertyStringSet(me.drive, values[burst_name], burst_name); > + }); > + } > > + if (me.isImport) { > + params.source = values.inputImage; > + 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; > }, > > @@ -199,14 +219,17 @@ 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 = 'Target storage'; this should be a `gettext('Target storage')` so it can be translated. > + me.column1.push(selector); > } else { > me.column1.push({ > xtype: 'textfield', > @@ -231,6 +254,14 @@ Ext.define('PVE.qemu.HDInputPanel', { > name: 'discard' > } > ); > + if (me.isImport) { > + me.column2.push({ > + xtype: 'textfield', > + fieldLabel: gettext('Source image'), > + name: 'inputImage', > + emptyText: '/home/user/disk.qcow2', > + }); > + } > > me.advancedColumn1.push( > { > @@ -372,14 +403,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.title = 'Import Hard Disk'; for consistency I would not change the title and instead set the following: 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 + ')'; > } > diff --git a/www/manager6/qemu/HardwareView.js b/www/manager6/qemu/HardwareView.js > index 40b3fe86..f9735998 100644 > --- a/www/manager6/qemu/HardwareView.js > +++ b/www/manager6/qemu/HardwareView.js > @@ -436,6 +436,23 @@ Ext.define('PVE.qemu.HardwareView', { > handler: run_move > }); > > + var import_btn = new Proxmox.button.Button({ > + text: gettext('Import disk'), > + hidden: !(caps.vms['VM.Allocate'] && > + caps.storage['Datastore.AllocateTemplate'] && > + caps.storage['Datastore.AllocateSpace']), > + 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 +769,7 @@ Ext.define('PVE.qemu.HardwareView', { > edit_btn, > resize_btn, > move_btn, > + import_btn, > revert_btn > ], > rows: rows, >