From 7adbc4a457d619909a09b3fc11e7aff0561bc56e Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Thu, 22 Feb 2018 14:17:41 +0100 Subject: [PATCH] ui: declarative LXC Create Signed-off-by: Thomas Lamprecht --- www/manager6/lxc/CreateWizard.js | 596 +++++++++++++++---------------- 1 file changed, 292 insertions(+), 304 deletions(-) diff --git a/www/manager6/lxc/CreateWizard.js b/www/manager6/lxc/CreateWizard.js index 8a40c917..c39db169 100644 --- a/www/manager6/lxc/CreateWizard.js +++ b/www/manager6/lxc/CreateWizard.js @@ -1,328 +1,316 @@ -/*global - FileReader -*/ - +/*jslint confusion: true*/ Ext.define('PVE.lxc.CreateWizard', { extend: 'PVE.window.Wizard', + mixins: ['Proxmox.Mixin.CBind'], - initComponent: function() { - var me = this; + viewModel: { + data: { + nodename: '', + storage: '', + unprivileged: false + } + }, - var summarystore = Ext.create('Ext.data.Store', { - model: 'KeyValue', - sorters: [ + cbindData: { + nodename: undefined + }, + + subject: gettext('LXC Container'), + + items: [ + { + xtype: 'inputpanel', + title: gettext('General'), + onlineHelp: 'pct_general', + column1: [ { - property : 'key', - direction: 'ASC' + xtype: 'pveNodeSelector', + name: 'nodename', + cbind: { + selectCurNode: '{!nodename}', + preferredValue: '{nodename}' + }, + bind: { + value: '{nodename}' + }, + fieldLabel: gettext('Node'), + allowBlank: false, + onlineValidator: true + }, + { + xtype: 'pveGuestIDSelector', + name: 'vmid', // backend only knows vmid + guestType: 'lxc', + value: '', + loadNextFreeID: true, + validateExists: false + }, + { + xtype: 'proxmoxtextfield', + name: 'hostname', + vtype: 'DnsName', + value: '', + fieldLabel: gettext('Hostname'), + skipEmptyText: true, + allowBlank: true + }, + { + xtype: 'proxmoxcheckbox', + name: 'unprivileged', + value: false, + bind: { + value: '{unprivileged}' + }, + fieldLabel: gettext('Unprivileged container') + } + ], + column2: [ + { + xtype: 'pvePoolSelector', + fieldLabel: gettext('Resource Pool'), + name: 'pool', + submitValue: false, + value: '', + allowBlank: true + }, + { + xtype: 'textfield', + inputType: 'password', + name: 'password', + value: '', + fieldLabel: gettext('Password'), + allowBlank: false, + minLength: 5, + change: function(f, value) { + if (f.rendered) { + f.up().down('field[name=confirmpw]').validate(); + } + } + }, + { + xtype: 'textfield', + inputType: 'password', + name: 'confirmpw', + value: '', + fieldLabel: gettext('Confirm password'), + allowBlank: true, + submitValue: false, + validator: function(value) { + var pw = this.up().down('field[name=password]').getValue(); + if (pw !== value) { + return "Passwords do not match!"; + } + return true; + } + }, + { + xtype: 'proxmoxtextfield', + name: 'ssh-public-keys', + value: '', + fieldLabel: gettext('SSH public key'), + allowBlank: true, + validator: function(value) { + var pwfield = this.up().down('field[name=password]'); + if (value.length) { + var key = PVE.Parser.parseSSHKey(value); + if (!key) { + return "Failed to recognize ssh key"; + } + pwfield.allowBlank = true; + } else { + pwfield.allowBlank = false; + } + pwfield.validate(); + return true; + }, + afterRender: function() { + if (!window.FileReader) { + // No FileReader support in this browser + return; + } + var cancel = function(ev) { + ev = ev.event; + if (ev.preventDefault) { + ev.preventDefault(); + } + }; + var field = this; + field.inputEl.on('dragover', cancel); + field.inputEl.on('dragenter', cancel); + field.inputEl.on('drop', function(ev) { + ev = ev.event; + if (ev.preventDefault) { + ev.preventDefault(); + } + var files = ev.dataTransfer.files; + PVE.Utils.loadSSHKeyFromFile(files[0], function(v) { + field.setValue(v); + }); + }); + } + }, + { + xtype: 'filebutton', + name: 'file', + hidden: !window.FileReader, + text: gettext('Load SSH Key File'), + listeners: { + change: function(btn, e, value) { + e = e.event; + var field = this.up().down('proxmoxtextfield[name=ssh-public-keys]'); + PVE.Utils.loadSSHKeyFromFile(e.target.files[0], function(v) { + field.setValue(v); + }); + btn.reset(); + } + } } ] - }); - - var tmplsel = Ext.create('PVE.form.FileSelector', { - name: 'ostemplate', - storageContent: 'vztmpl', - fieldLabel: gettext('Template'), - allowBlank: false - }); - - var tmplstoragesel = Ext.create('PVE.form.StorageSelector', { - name: 'tmplstorage', - fieldLabel: gettext('Storage'), - storageContent: 'vztmpl', - autoSelect: true, - allowBlank: false, - listeners: { - change: function(f, value) { - tmplsel.setStorage(value); + }, + { + xtype: 'inputpanel', + title: gettext('Template'), + onlineHelp: 'pct_container_images', + column1: [ + { + xtype: 'pveStorageSelector', + name: 'tmplstorage', + fieldLabel: gettext('Storage'), + storageContent: 'vztmpl', + autoSelect: true, + allowBlank: false, + bind: { + value: '{storage}', + nodename: '{nodename}' + } + }, + { + xtype: 'pveFileSelector', + name: 'ostemplate', + storageContent: 'vztmpl', + fieldLabel: gettext('Template'), + bind: { + storage: '{storage}', + nodename: '{nodename}' + }, + allowBlank: false } - } - }); - - var rootfspanel = Ext.create('PVE.lxc.MountPointInputPanel', { + ] + }, + { + xtype: 'pveLxcMountPointInputPanel', title: gettext('Root Disk'), insideWizard: true, isCreate: true, unused: false, - unprivileged: false, + bind: { + nodename: '{nodename}', + unprivileged: '{unprivileged}' + }, confid: 'rootfs' - }); - - var networkpanel = Ext.create('PVE.lxc.NetworkInputPanel', { + }, + { + xtype: 'pveLxcCPUInputPanel', + title: gettext('CPU'), + insideWizard: true + }, + { + xtype: 'pveLxcMemoryInputPanel', + title: gettext('Memory'), + insideWizard: true + }, + { + xtype: 'pveLxcNetworkInputPanel', title: gettext('Network'), insideWizard: true, + bind: { + nodename: '{nodename}' + }, isCreate: true - }); - - var passwordfield = Ext.createWidget('textfield', { - inputType: 'password', - name: 'password', - value: '', - fieldLabel: gettext('Password'), - allowBlank: false, - minLength: 5, - change: function(f, value) { - if (!me.rendered) { - return; - } - me.down('field[name=confirmpw]').validate(); - } - }); - - /*jslint confusion: true */ - /* the validator function can return either a string or a boolean */ - me.sshkeyfield = Ext.createWidget('proxmoxtextfield', { - name: 'ssh-public-keys', - value: '', - fieldLabel: gettext('SSH public key'), - allowBlank: true, - validator: function(value) { - if (value.length) { - var key = PVE.Parser.parseSSHKey(value); - if (!key) { - return "Failed to recognize ssh key"; - } - me.down('field[name=password]').allowBlank = true; - } else { - me.down('field[name=password]').allowBlank = false; - } - me.down('field[name=password]').validate(); - return true; - }, - afterRender: function() { - if (!window.FileReader) { - // No FileReader support in this browser - return; - } - var cancel = function(ev) { - ev = ev.event; - if (ev.preventDefault) { - ev.preventDefault(); - } - }; - me.sshkeyfield.inputEl.on('dragover', cancel); - me.sshkeyfield.inputEl.on('dragenter', cancel); - me.sshkeyfield.inputEl.on('drop', function(ev) { - ev = ev.event; - if (ev.preventDefault) { - ev.preventDefault(); - } - var files = ev.dataTransfer.files; - PVE.Utils.loadSSHKeyFromFile(files[0], function (v) { - me.sshkeyfield.setValue(v); - }); - }); - } - }); - - var column2 = [ - { - xtype: 'pvePoolSelector', - fieldLabel: gettext('Resource Pool'), - name: 'pool', - value: '', - allowBlank: true - }, - passwordfield, - { - xtype: 'textfield', - inputType: 'password', - name: 'confirmpw', - value: '', - fieldLabel: gettext('Confirm password'), - allowBlank: true, - validator: function(value) { - var pw = me.down('field[name=password]').getValue(); - if (pw !== value) { - return "Passwords do not match!"; - } - return true; - } - }, - me.sshkeyfield - ]; - /*jslint confusion: false */ - - if (window.FileReader) { - column2.push({ - xtype: 'filebutton', - name: 'file', - text: gettext('Load SSH Key File'), - listeners: { - change: function(btn, e, value) { - e = e.event; - PVE.Utils.loadSSHKeyFromFile(e.target.files[0], function (v) { - me.sshkeyfield.setValue(v); - }); - btn.reset(); - } - } - }); - } - - Ext.applyIf(me, { - subject: gettext('LXC Container'), + }, + { + xtype: 'pveLxcDNSInputPanel', + title: gettext('DNS'), + insideWizard: true + }, + { + title: gettext('Confirm'), + layout: 'fit', items: [ { - xtype: 'inputpanel', - title: gettext('General'), - onlineHelp: 'pct_general', - column1: [ - { - xtype: 'pveNodeSelector', - name: 'nodename', - selectCurNode: !me.nodename, - preferredValue: me.nodename, - fieldLabel: gettext('Node'), - allowBlank: false, - onlineValidator: true, - listeners: { - change: function(f, value) { - tmplstoragesel.setNodename(value); - tmplsel.setStorage(undefined, value); - networkpanel.setNodename(value); - rootfspanel.setNodename(value); - } - } - }, - { - xtype: 'pveGuestIDSelector', - name: 'vmid', // backend only knows vmid - guestType: 'lxc', - value: '', - loadNextFreeID: true, - validateExists: false - }, - { - xtype: 'proxmoxtextfield', - name: 'hostname', - vtype: 'DnsName', - value: '', - fieldLabel: gettext('Hostname'), - skipEmptyText: true, - allowBlank: true - }, - { - xtype: 'proxmoxcheckbox', - name: 'unprivileged', - value: '', - listeners: { - change: function(f, value) { - if (value) { - rootfspanel.down('field[name=quota]').setValue(false); - } - rootfspanel.unprivileged = value; - var hdsel = rootfspanel.down('#hdstorage'); - hdsel.fireEvent('change', hdsel, hdsel.getValue()); - } - }, - fieldLabel: gettext('Unprivileged container') - } - ], - column2: column2, - onGetValues: function(values) { - delete values.confirmpw; - if (!values.pool) { - delete values.pool; - } - return values; - } - }, - { - xtype: 'inputpanel', - title: gettext('Template'), - onlineHelp: 'pct_container_images', - column1: [ tmplstoragesel, tmplsel] - }, - rootfspanel, - { - xtype: 'pveLxcCPUInputPanel', - title: gettext('CPU'), - insideWizard: true - }, - { - xtype: 'pveLxcMemoryInputPanel', - title: gettext('Memory'), - insideWizard: true - }, - networkpanel, - { - xtype: 'pveLxcDNSInputPanel', - title: gettext('DNS'), - insideWizard: true - }, - { - title: gettext('Confirm'), - layout: 'fit', - items: [ - { - xtype: 'grid', - store: summarystore, - columns: [ - {header: 'Key', width: 150, dataIndex: 'key'}, - {header: 'Value', flex: 1, dataIndex: 'value'} - ] - } - ], - listeners: { - show: function(panel) { - var form = me.down('form').getForm(); - var kv = me.getValues(); - var data = []; - Ext.Object.each(kv, function(key, value) { - if (key === 'delete' || key === 'tmplstorage') { // ignore - return; - } - if (key === 'password') { // don't show pw - return; - } - var html = Ext.htmlEncode(Ext.JSON.encode(value)); - data.push({ key: key, value: value }); - }); - summarystore.suspendEvents(); - summarystore.removeAll(); - summarystore.add(data); - summarystore.sort(); - summarystore.resumeEvents(); - summarystore.fireEvent('refresh'); - } + xtype: 'grid', + store: { + model: 'KeyValue', + sorters: [{ + property : 'key', + direction: 'ASC' + }] }, - onSubmit: function() { - var kv = me.getValues(); - delete kv['delete']; - - var nodename = kv.nodename; - delete kv.nodename; - delete kv.tmplstorage; - - if (!kv.password.length && kv['ssh-public-keys']) { - delete kv.password; - } - - Proxmox.Utils.API2Request({ - url: '/nodes/' + nodename + '/lxc', - waitMsgTarget: me, - method: 'POST', - params: kv, - success: function(response, opts){ - var upid = response.result.data; - - var win = Ext.create('Proxmox.window.TaskViewer', { - upid: upid - }); - win.show(); - me.close(); - }, - failure: function(response, opts) { - Ext.Msg.alert(gettext('Error'), response.htmlStatus); - } - }); - } + columns: [ + {header: 'Key', width: 150, dataIndex: 'key'}, + {header: 'Value', flex: 1, dataIndex: 'value'} + ] } - ] - }); + ], + listeners: { + show: function(panel) { + var wizard = this.up('window'); + var kv = wizard.getValues(); + var data = []; + Ext.Object.each(kv, function(key, value) { + if (key === 'delete' || key === 'tmplstorage') { // ignore + return; + } + if (key === 'password') { // don't show pw + return; + } + var html = Ext.htmlEncode(Ext.JSON.encode(value)); + data.push({ key: key, value: value }); + }); - me.callParent(); - } + var summarystore = panel.down('grid').getStore(); + summarystore.suspendEvents(); + summarystore.removeAll(); + summarystore.add(data); + summarystore.sort(); + summarystore.resumeEvents(); + summarystore.fireEvent('refresh'); + } + }, + onSubmit: function() { + var wizard = this.up('window'); + var kv = wizard.getValues(); + delete kv['delete']; + + var nodename = kv.nodename; + delete kv.nodename; + delete kv.tmplstorage; + + if (!kv.password.length && kv['ssh-public-keys']) { + delete kv.password; + } + + Proxmox.Utils.API2Request({ + url: '/nodes/' + nodename + '/lxc', + waitMsgTarget: wizard, + method: 'POST', + params: kv, + success: function(response, opts){ + var upid = response.result.data; + + var win = Ext.create('Proxmox.window.TaskViewer', { + upid: upid + }); + win.show(); + wizard.close(); + }, + failure: function(response, opts) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + } + }); + } + } + ] });