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 088126461E for ; Mon, 20 Jul 2020 12:36:22 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 015B7D63E for ; Mon, 20 Jul 2020 12:36:22 +0200 (CEST) Received: from dev.dominic.proxmox.com (212-186-127-178.static.upcbusiness.at [212.186.127.178]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1E293D60D for ; Mon, 20 Jul 2020 12:36:20 +0200 (CEST) Received: by dev.dominic.proxmox.com (Postfix, from userid 0) id 54EDC216D2; Tue, 7 Jul 2020 12:04:18 +0200 (CEST) From: =?UTF-8?q?Dominic=20J=C3=A4ger?= To: pve-devel@pve.proxmox.com Date: Tue, 7 Jul 2020 12:04:11 +0200 Message-Id: <20200707100412.81731-3-d.jaeger@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200707100412.81731-1-d.jaeger@proxmox.com> References: <20200707100412.81731-1-d.jaeger@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 2 AWL 0.625 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.251 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [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: Mon, 20 Jul 2020 10:36:22 -0000 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; + } 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'; + 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'; + 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, -- 2.20.1