[pve-devel] [PATCH v6 manager 6/6] added basic ability to install ceph via gui
Tim Marx
t.marx at proxmox.com
Mon Mar 4 11:58:58 CET 2019
Just for the records, I recap here what we already discussed off list.
> Dominik Csapak <d.csapak at proxmox.com> hat am 28. Februar 2019 um 11:46 geschrieben:
>
>
> high level comments:
>
> closing the wizard right after opening it, produces an error in the
> console (stopUpdate on undefined, or something similar)
>
I will fix this, its due to the on destroy of the second tab and not checking if a store even exists already.
> after initializing i get the error: rados_connect failed - No such file
> or directory (500)
>
> maybe a 'mon create' in the wizard could also be done? (optionally)
I will sum up the next steps to do in the last tab, including a hint to our docs. As there is already an option to install the mon via gui I don't think that this is really necessary, but I do agree that it would be nice to have.
>
> also when installing, the next button got activated early, but
> i did not click on it, is there any better way to detect
> when it is finished?
>
If there is a better way to check if the installation is finished, I would rework it, for now I use the APIs check_ceph_inited method and this checks for the mon binary.
> also when we already have ceph installed from the beginning, does it
> make sense to show the install tab at all?
>
I think it does no harm and as it is called a installation wizard it do make sense for me to show it.
> some more comments inline
>
> On 2/27/19 3:01 PM, Tim Marx wrote:
> > Signed-off-by: Tim Marx <t.marx at proxmox.com>
> > ---
> > www/css/ext6-pve.css | 5 +
> > www/manager6/Makefile | 3 +
> > www/manager6/Utils.js | 31 ++++
> > www/manager6/ceph/CephInstallWizard.js | 259 +++++++++++++++++++++++++++++++++
> > www/manager6/ceph/Config.js | 16 ++
> > www/manager6/ceph/Crush.js | 16 ++
> > www/manager6/ceph/FS.js | 42 +++++-
> > www/manager6/ceph/Log.js | 70 +++++++++
> > www/manager6/ceph/Monitor.js | 19 ++-
> > www/manager6/ceph/OSD.js | 19 ++-
> > www/manager6/ceph/Pool.js | 18 ++-
> > www/manager6/ceph/Status.js | 21 ++-
> > www/manager6/node/Config.js | 5 +-
> > www/manager6/window/CephInstall.js | 66 +++++++++
> > 14 files changed, 582 insertions(+), 8 deletions(-)
> > create mode 100644 www/manager6/ceph/CephInstallWizard.js
> > create mode 100644 www/manager6/ceph/Log.js
> > create mode 100644 www/manager6/window/CephInstall.js
> >
> > diff --git a/www/css/ext6-pve.css b/www/css/ext6-pve.css
> > index 174511ac..7ac35603 100644
> > --- a/www/css/ext6-pve.css
> > +++ b/www/css/ext6-pve.css
> > @@ -582,3 +582,8 @@ table.osds td:first-of-type {
> > right: 0px;
> > background-color: #555;
> > }
> > +
> > +.install-mask {
> > + background-color: rgb(245, 245, 245);
> > + color: #000;
> > +}
> > \ No newline at end of file
> > diff --git a/www/manager6/Makefile b/www/manager6/Makefile
> > index e75f0de6..db5ced2d 100644
> > --- a/www/manager6/Makefile
> > +++ b/www/manager6/Makefile
> > @@ -83,6 +83,7 @@ JSSRC= \
> > window/BackupConfig.js \
> > window/Settings.js \
> > window/StartupEdit.js \
> > + window/CephInstall.js \
> > panel/NotesView.js \
> > grid/ResourceGrid.js \
> > grid/PoolMembers.js \
> > @@ -101,6 +102,8 @@ JSSRC= \
> > ceph/Status.js \
> > ceph/StatusDetail.js \
> > ceph/Config.js \
> > + ceph/Log.js \
> > + ceph/CephInstallWizard.js \
> > node/Disks.js \
> > node/LVM.js \
> > node/LVMThin.js \
> > diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> > index b9fa25b7..83ff8a3e 100644
> > --- a/www/manager6/Utils.js
> > +++ b/www/manager6/Utils.js
> > @@ -1091,6 +1091,37 @@ Ext.define('PVE.Utils', { utilities: {
> > return;
> > }
> > }
> > + },
> > +
> > + handleStoreErrorOrMask: function(me, store, regex, callback) {
> > +
> > + if (!(store.proxy instanceof Proxmox.RestProxy)) {
> > + throw "Proxy must implement afterload event!";
> > + }
> > +
> > + me.mon(store.proxy, 'afterload', function (proxy, request, success) {
> > +
> > + if (success) {
> > + Proxmox.Utils.setErrorMask(me, false);
> > + return;
> > + }
> > + var msg;
> > + /*jslint nomen: true */
> > + var operation = request._operation;
> > + var error = operation.getError();
> > +
> > + if (error.statusText) {
> > + if (error.statusText.match(regex)) {
> > + callback(me, error);
> > + return;
> > + } else {
> > + msg = error.statusText + ' (' + error.status + ')';
> > + }
> > + } else {
> > + msg = gettext('Connection error');
> > + }
> > + Proxmox.Utils.setErrorMask(me, msg);
> > + });
> > }
>
> like discussed off-list, i think it would be better to use the
> stores 'load' event, since we get the operation object directly
> as parameter (saves us the access of private properties and the jslint
> override)
I will change it.
>
> > },
> >
> > diff --git a/www/manager6/ceph/CephInstallWizard.js b/www/manager6/ceph/CephInstallWizard.js
> > new file mode 100644
> > index 00000000..a6789a88
> > --- /dev/null
> > +++ b/www/manager6/ceph/CephInstallWizard.js
> > @@ -0,0 +1,259 @@
> > +Ext.define('PVE.ceph.CephInstallWizard', {
> > + extend: 'PVE.window.Wizard',
> > + alias: 'widget.pveCephInstallWizard',
> > + mixins: ['Proxmox.Mixin.CBind'],
> > + resizable: false,
> > + nodename: undefined,
> > + viewModel: {
> > + data: {
> > + nodename: ''
> > + }
> > + },
> > + cbindData: {
> > + nodename: undefined
> > + },
> > + title: gettext('Installation'),
> > + items: [
> > + {
> > + title: gettext('Info'),
> > + xtype: 'panel',
> > + border: false,
> > + bodyBorder: false,
> > + onlineHelp: 'chapter_pveceph',
> > + html: '<h3>Ceph?</h3>'+
> > + '<blockquote cite="https://ceph.com/"><p>"<b>Ceph</b> is a unified, distributed storage system designed for excellent performance, reliability and scalability."</p></blockquote>'+
> > + '<p><b>Ceph</b> is currently <b>not installed</b> on this node, click on the next button below to start the installation.'+
> > + ' This wizard will guide you through the nessecery steps, after the inital installation you will be offered to create a inital configuration.'+
> > + ' The configuration step is only needed once per cluster and will be skipped if a config is already present.</p>'+
> > + '<p>If you want to learn more visit <a href="http://docs.ceph.com/docs/master/">ceph.com</a> or click the help button below.</p>',
> > + listeners: {
> > + activate: function() {
> > + // notify owning container that it should display a help button
> > + if (this.onlineHelp) {
> > + Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
> > + }
> > + },
> > + deactivate: function() {
> > + if (this.onlineHelp) {
> > + Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
> > + }
> > + }
> > + }
> > + },
> > + {
> > + title: gettext('Installation'),
> > + xtype: 'panel',
> > + layout: 'fit',
> > + cbind:{
> > + nodename: '{nodename}'
> > + },
> > + listeners: {
> > + afterrender: function() {
> > + var me = this;
> > + me.down('pveNoVncConsole').fireEvent('activate');
> > + },
> > + activate: function() {
> > + var me = this;
> > + var nodename = me.nodename;
> > + me.store = Ext.create('Proxmox.data.UpdateStore', {
>
> i would not use the 'store' property, since extjs may use that. e.g.
> destroy it on the destroy event (i think)
> maybe 'updateStore' just to be safe
>
Ok
> > + storeid: 'ceph-status-' + nodename,
> > + interval: 1000,
> > + proxy: {
> > + type: 'proxmox',
> > + url: '/api2/json/nodes/' + nodename + '/ceph/status',
> > + listeners: {
> > + exception: function(proxy, response, options){
> > +
> > + if(response.statusText.match("not initialized", "i")){
>
> nit: space after if and between ) and {
>
> > + me.store.stopUpdate();
> > + me.down('textfield').setValue('success');
> > + } else if (!response.statusText.match("not installed", "i")) {
>
> are you sure this code path is correct?
> we have a failing api call but are neither in 'not initialized' nor 'not
> installed' state... what do we do then?
>
I could try to mask the window with the error message.
> > + me.store.stopUpdate();
> > + var wizard = me.up('#wizcontent');
> > + var tabs = wizard.items;
> > + var lastTab = tabs.items[tabs.length-1];
> > + lastTab.enable();
> > + wizard.setActiveTab(lastTab);
> > + }
> > + }
> > + }
>
> any particular reason why the use of this listener?
> wouldn't it be possible to use the load event with !success and the
> operation argument (the 4th that you did not specify)
>
will check that.
> > + },
> > + listeners: {
> > + load: function(rec, response, success){
> > + if(success){
>
> nit: spaces around ()
>
> > + me.store.stopUpdate();
> > + var wizard = me.up('#wizcontent');
> > + var tabs = wizard.items;
> > + var lastTab = tabs.items[tabs.length-1];
> > + lastTab.enable();
> > + wizard.setActiveTab(lastTab);
> > + }
> > + }
> > + }
> > + });
> > + me.store.startUpdate();
> > + },
> > + destroy: function(){
> > + var me = this;
> > + me.store.stopUpdate();
> > + }
>
> i guess we want the 'deactivate' event, not destroy? or both?
> also check if the store exists, since it does not have to (exit on first
> panel for example)
Answered at the beginning.
>
> > + },
> > + items: [
> > + {
> > + itemId: 'jsconsole',
> > + consoleType: 'cmd',
> > + xtermjs: true,
> > + xtype: 'pveNoVncConsole',
> > + cbind:{
> > + nodename: '{nodename}'
> > + },
> > + cmd: 'ceph_install'
> > + },
> > + {
> > + xtype: 'textfield',
> > + name: 'installSuccess',
> > + value: '',
> > + allowBlank: false,
> > + submitValue: false,
> > + hidden: true
> > + }
> > + ]
> > + },
> > + {
> > + xtype: 'inputpanel',
> > + title: gettext('Configuration'),
> > + onlineHelp: 'chapter_pveceph',
> > + cbind: {
> > + nodename: '{nodename}'
> > + },
> > + listeners: {
> > + activate: function() {
> > + this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
> > + },
> > + deactivate: function() {
> > + this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
> > + }
> > + },
> > + column1: [
> > + {
> > + xtype: 'displayfield',
> > + name: 'nodename',
> > + fieldLabel: gettext('Node'),
> > + cbind: {
> > + value: '{nodename}'
> > + },
> > + padding: 5
> > + },
> > + {
> > + xtype: 'textfield',
> > + name: 'network',
> > + vtype: 'IPCIDRAddress',
> > + value: '',
> > + fieldLabel: 'Network IPv4/CIDR',
> > + allowBlank: false
> > + },
> > + {
> > + xtype: 'textfield',
> > + name: 'cluster-network',
> > + vtype: 'IPCIDRAddress',
> > + fieldLabel: 'Cluster-Network IPv4/CIDR',
> > + allowBlank: true,
> > + emptyText: gettext('default')
> > + }
> > + ],
> > + advancedColumn1: [
> > + {
> > + xtype: 'numberfield',
> > + name: 'size',
> > + fieldLabel: gettext('Number of replicas'),
> > + value: '',
> > + maxValue: 7,
> > + minValue: 1,
> > + allowBlank: true,
> > + emptyText: gettext('default')
> > + },
> > + {
> > + xtype: 'numberfield',
> > + name: 'min_size',
> > + fieldLabel: gettext('Minimum replicas'),
> > + value: '',
> > + maxValue: 7,
> > + minValue: 1,
> > + allowBlank: true,
> > + emptyText: gettext('default')
> > + },
> > + {
> > + xtype: 'numberfield',
> > + name: 'pg_bits',
> > + fieldLabel: 'Placement group bits',
> > + value: '',
> > + maxValue: 14,
> > + minValue: 6,
> > + allowBlank: true,
> > + emptyText: gettext('default')
> > + }
>
> i would prefer if we use the same gettexts as with the pools
> (while i like yours better, so maybe change the fieldlabels for pools?
> can ofc be done later on)
>
> also it is not really clear that this are the defaults we are setting,
> maybe 'Default number of replicas' ? etc.
>
ok
> > + ],
> > + onGetValues: function(values) {
> > + ['cluster-network', 'size', 'min_size', 'pg_bits'].forEach(function(field) {
> > + if (!values[field]) {
> > + delete values[field];
> > + }
> > + });
> > + return values;
> > + },
> > + onSubmit: function() {
> > + var me = this;
> > + var wizard = me.up('window');
> > + var kv = wizard.getValues();
> > + delete kv['delete'];
> > + var nodename = me.nodename;
> > + delete kv.nodename;
> > + Proxmox.Utils.API2Request({
> > + url: '/nodes/'+nodename+'/ceph/init',
> > + waitMsgTarget: wizard,
> > + method: 'POST',
> > + params: kv,
> > + success: function() {
> > + var tp = me.up('#wizcontent');
> > + var atab = tp.getActiveTab();
> > +
> > + var next = tp.items.indexOf(atab) + 1;
> > + var ntab = tp.items.getAt(next);
> > + if (ntab) {
> > + ntab.enable();
> > + tp.setActiveTab(ntab);
> > + }
> > + },
> > + failure: function(response, opts) {
> > + Ext.Msg.alert(gettext('Error'), response.htmlStatus);
> > + }
> > + });
> > + }
> > + },
> > + {
> > + title: gettext('Success'),
> > + xtype: 'panel',
> > + border: false,
> > + bodyBorder: false,
> > + onlineHelp: 'chapter_pveceph',
> > + html: '<h3>Installation successfull!</h3>',
> > + listeners: {
> > + activate: function() {
> > + // notify owning container that it should display a help button
> > + if (this.onlineHelp) {
> > + Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
> > + }
>
> maybe deactivate all old panels/backbutton here? else i can get back and
> submit again
ok
>
> > + },
> > + deactivate: function() {
> > + if (this.onlineHelp) {
> > + Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
> > + }
> > + }
> > + },
> > + onSubmit: function() {
> > + var wizard = this.up('pveCephInstallWizard');
> > + wizard.close();
> > + }
> > + }
> > + ]
> > + });
> > \ No newline at end of file
> > diff --git a/www/manager6/ceph/Config.js b/www/manager6/ceph/Config.js
> > index 04124684..447a9682 100644
> > --- a/www/manager6/ceph/Config.js
> > +++ b/www/manager6/ceph/Config.js
> > @@ -14,6 +14,22 @@ Ext.define('PVE.node.CephConfig', {
> > waitMsgTarget: me,
> > failure: function(response, opts) {
> > me.update(gettext('Error') + " " + response.htmlStatus);
> > + var msg = response.htmlStatus;
> > + var regex = new RegExp("(not installed|not initialized)", "i");
>
> a better regex: 'not (installed|initialized)'
ok
>
> > + if (msg.match(regex)) {
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.ownerCt.el.mask();
> > + if (!me.ownerCt.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: me.pveSelNode.data.node
> > + });
> > + me.ownerCt.add(win);
> > + win.show();
> > + }
> > + } else {
> > + me.ownerCt.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + }
> > },
> > success: function(response, opts) {
> > var data = response.result.data;
> > diff --git a/www/manager6/ceph/Crush.js b/www/manager6/ceph/Crush.js
> > index ebd46c83..7cdfdf6d 100644
> > --- a/www/manager6/ceph/Crush.js
> > +++ b/www/manager6/ceph/Crush.js
> > @@ -15,6 +15,22 @@ Ext.define('PVE.node.CephCrushMap', {
> > waitMsgTarget: me,
> > failure: function(response, opts) {
> > me.update(gettext('Error') + " " + response.htmlStatus);
> > + var msg = response.htmlStatus;
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + if (msg.match(regex)) {
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.ownerCt.el.mask();
> > + if (!me.ownerCt.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: me.pveSelNode.data.node
> > + });
> > + me.ownerCt.add(win);
> > + win.show();
> > + }
> > + } else {
> > + me.ownerCt.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + }
>
> this code looks very much like it could be factored out
>
will take a look.
> > },
> > success: function(response, opts) {
> > var data = response.result.data;
> > diff --git a/www/manager6/ceph/FS.js b/www/manager6/ceph/FS.js
> > index a1c34d73..bff1837b 100644
> > --- a/www/manager6/ceph/FS.js
> > +++ b/www/manager6/ceph/FS.js
> > @@ -161,7 +161,26 @@ Ext.define('PVE.NodeCephFSPanel', {
> > order: 'DESC'
> > }
> > }));
> > - Proxmox.Utils.monStoreErrors(view, view.rstore);
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error){
> > + me.rstore.stopUpdate();
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.ownerCt.el.mask();
> > +
> > + if (!me.ownerCt.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: view.nodename
> > + });
> > + me.ownerCt.add(win);
> > + me.ownerCt.mon(win, 'cephInstallWindowClosed', function(){
> > + me.rstore.startUpdate();
> > + });
> > + win.show();
> > + }
> > + } else {
> > + me.ownerCt.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + });
> > view.rstore.on('load', this.onLoad, this);
> > view.on('destroy', view.rstore.stopUpdate);
> > },
> > @@ -244,7 +263,26 @@ Ext.define('PVE.NodeCephFSPanel', {
> > order: 'DESC'
> > }
> > }));
> > - Proxmox.Utils.monStoreErrors(view, view.rstore);
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error){
> > + me.rstore.stopUpdate();
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.ownerCt.el.mask();
> > +
> > + if (!me.ownerCt.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: view.nodename
> > + });
> > + me.ownerCt.add(win);
> > + me.ownerCt.mon(win, 'cephInstallWindowClosed', function(){
> > + me.rstore.startUpdate();
> > + });
> > + win.show();
> > + }
> > + } else {
> > + me.ownerCt.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + });
>
> same here, those two codepaths look very much alike
>
> > view.rstore.on('load', this.onLoad, this);
> > view.on('destroy', view.rstore.stopUpdate);
> > },
> > diff --git a/www/manager6/ceph/Log.js b/www/manager6/ceph/Log.js
> > new file mode 100644
> > index 00000000..25178923
> > --- /dev/null
> > +++ b/www/manager6/ceph/Log.js
> > @@ -0,0 +1,70 @@
> > +Ext.define('PVE.ceph.Log', {
> > + extend: 'Proxmox.panel.LogView',
> > + xtype: 'cephLogView',
> > + nodename: undefined,
> > + doAttemptLoad: function(start) {
> > + var me = this;
> > +
> > + var req_params = {
> > + start: start,
> > + limit: me.pageSize
> > + };
> > +
> > + if (me.log_select_timespan) {
> > + // always show log until the end of the selected day
> > + req_params.until = Ext.Date.format(me.until_date, 'Y-m-d') + ' 23:59:59';
> > + req_params.since = Ext.Date.format(me.since_date, 'Y-m-d');
> > + }
> > +
> > + Proxmox.Utils.API2Request({
> > + url: me.url,
> > + params: req_params,
> > + method: 'GET',
> > + success: function(response) {
> > + Proxmox.Utils.setErrorMask(me, false);
> > + var list = response.result.data;
> > + var total = response.result.total;
> > + var first = 0, last = 0;
> > + var text = '';
> > + Ext.Array.each(list, function(item) {
> > + if (!first|| item.n < first) {
> > + first = item.n;
> > + }
> > + if (!last || item.n > last) {
> > + last = item.n;
> > + }
> > + text = text + Ext.htmlEncode(item.t) + "
";
> > + });
> > +
> > + if (first && last && total) {
> > + me.updateView(first -1 , last -1, total, text);
> > + } else {
> > + me.updateView(0, 0, 0, '');
> > + }
> > + },
> > + failure: function(response) {
> > + var msg = response.htmlStatus;
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + if (msg.match(regex)) {
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.el.mask();
> > +
> > + if (!me.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: me.nodename
> > + });
> > + me.add(win);
> > + win.show();
> > + }
> > +
> > + } else {
> > + me.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > +
> > + } else {
> > + Proxmox.Utils.setErrorMask(me, msg);
> > + }
> > + }
> > + });
> > + }
> > +});
> > \ No newline at end of file
> > diff --git a/www/manager6/ceph/Monitor.js b/www/manager6/ceph/Monitor.js
> > index a3a18a83..476ed8cc 100644
> > --- a/www/manager6/ceph/Monitor.js
> > +++ b/www/manager6/ceph/Monitor.js
> > @@ -82,7 +82,6 @@ Ext.define('PVE.node.CephMonList', {
> > sorters: [{ property: 'name'}]
> > });
> >
> > - Proxmox.Utils.monStoreErrors(me, rstore);
> >
> > var service_cmd = function(cmd) {
> > var rec = sm.getSelection()[0];
> > @@ -211,6 +210,24 @@ Ext.define('PVE.node.CephMonList', {
> > }
> > });
> >
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
> > + me.store.rstore.stopUpdate();
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.el.mask();
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: nodename
> > + });
> > + me.add(win);
> > + me.mon(win, 'cephInstallWindowClosed', function(){
> > + me.store.rstore.startUpdate();
> > + });
> > + win.show();
> > + } else {
> > + me.el.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + });
> > +
> > me.callParent();
> > }
> > }, function() {
> > diff --git a/www/manager6/ceph/OSD.js b/www/manager6/ceph/OSD.js
> > index 144fab7e..f635cbd6 100644
> > --- a/www/manager6/ceph/OSD.js
> > +++ b/www/manager6/ceph/OSD.js
> > @@ -281,7 +281,24 @@ Ext.define('PVE.node.CephOsdTree', {
> > waitMsgTarget: me,
> > method: 'GET',
> > failure: function(response, opts) {
> > - Proxmox.Utils.setErrorMask(me, response.htmlStatus);
> > + var msg = response.htmlStatus;
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + if (msg.match(regex)) {
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.el.mask();
> > + if (!me.down('pveCephInstallWindow')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: me.pveSelNode.data.node
> > + });
> > + me.add(win);
> > + win.show();
> > + }
> > + } else {
> > + me.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + } else {
> > + Proxmox.Utils.setErrorMask(me, msg);
> > + }
> > },
> > success: function(response, opts) {
> > sm.deselectAll();
> > diff --git a/www/manager6/ceph/Pool.js b/www/manager6/ceph/Pool.js
> > index 27eba024..c7dd2248 100644
> > --- a/www/manager6/ceph/Pool.js
> > +++ b/www/manager6/ceph/Pool.js
> > @@ -164,7 +164,23 @@ Ext.define('PVE.node.CephPoolList', {
> >
> > var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore });
> >
> > - Proxmox.Utils.monStoreErrors(me, rstore);
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
> > + me.store.rstore.stopUpdate();
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.el.mask();
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: nodename
> > + });
> > + me.add(win);
> > + me.mon(win, 'cephInstallWindowClosed', function(){
> > + me.store.rstore.startUpdate();
> > + });
> > + win.show();
> > + } else {
> > + me.el.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + });
> >
> > var create_btn = new Ext.Button({
> > text: gettext('Create'),
> > diff --git a/www/manager6/ceph/Status.js b/www/manager6/ceph/Status.js
> > index 78fa1cf8..ea4e27e7 100644
> > --- a/www/manager6/ceph/Status.js
> > +++ b/www/manager6/ceph/Status.js
> > @@ -308,7 +308,26 @@ Ext.define('PVE.node.CephStatus', {
> > me.version = me.sp.get('ceph-version');
> > me.change_version(me.version);
> >
> > - Proxmox.Utils.monStoreErrors(me,me.store);
> > + var regex = new RegExp("(not installed|not initialized)", "i");
> > + PVE.Utils.handleStoreErrorOrMask(me, me.store, regex, function(me, error){
> > + me.store.stopUpdate();
> > + if (Proxmox.UserName === 'root at pam') {
> > + me.el.mask();
> > + if (!me.down('PVE.ceph.Install')){
> > + var win = Ext.create('PVE.ceph.Install', {
> > + nodename: nodename
> > + });
> > + me.add(win);
> > + me.mon(win, 'cephInstallWindowClosed', function(){
> > + me.store.startUpdate();
> > + });
> > + win.show();
> > + }
> > + } else {
> > + me.el.mask(Ext.String.format(gettext('{0} not installed.') + gettext(' Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
> > + }
> > + });
>
> most of these look very much alike and should be refactored imo
>
> > +
> > me.mon(me.store, 'load', me.updateAll, me);
> > me.on('destroy', me.store.stopUpdate);
> > me.store.startUpdate();
> > diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
> > index f9a62670..831d2e02 100644
> > --- a/www/manager6/node/Config.js
> > +++ b/www/manager6/node/Config.js
> > @@ -375,8 +375,9 @@ Ext.define('PVE.node.Config', {
> > iconCls: 'fa fa-list',
> > groups: ['ceph'],
> > onlineHelp: 'chapter_pveceph',
> > - xtype: 'proxmoxLogView',
> > - url: "/api2/extjs/nodes/" + nodename + "/ceph/log"
> > + xtype: 'cephLogView',
> > + url: "/api2/extjs/nodes/" + nodename + "/ceph/log",
> > + nodename: nodename
> > });
> > }
> >
> > diff --git a/www/manager6/window/CephInstall.js b/www/manager6/window/CephInstall.js
> > new file mode 100644
> > index 00000000..20ecdd16
> > --- /dev/null
> > +++ b/www/manager6/window/CephInstall.js
> > @@ -0,0 +1,66 @@
> > +/*jslint confusion: true*/
> > +Ext.define('PVE.ceph.Install', {
> > + extend: 'Ext.window.Window',
> > + xtype: 'pveCephInstallWindow',
> > + mixins: ['Proxmox.Mixin.CBind'],
> > +
> > + width: 220,
> > + header: false,
> > + resizable: false,
> > + draggable: false,
> > + modal: true,
> > + nodename: undefined,
> > + shadow: false,
> > + border: false,
> > + bodyBorder: false,
> > + closable: false,
> > + cls: 'install-mask',
> > + bodyCls: 'install-mask',
>
> i think for the padding issue, a
> padding: 5
> or
> bodyPadding: 5
> here could help
>
> > + layout: {
> > + align: 'stretch',
> > + pack: 'center',
> > + type: 'vbox'
> > + },
> > + viewModel: {
> > + parent: null,
> > + data: {
> > + cephVersion: 'luminous'
> > + },
> > + formulas: {
> > + buttonText: function (get){
> > + return gettext('Install Ceph-') + get('cephVersion');
> > + }
> > + }
> > + },
> > + items: [
> > + {
> > + html: '<p class="install-mask">' + Ext.String.format(gettext('{0} is not installed on this node.'), 'Ceph') + '
' +
> > + gettext('Would you like to install it now?') + '</p>',
> > + border: false,
> > + padding: 5,
> > + bodyCls: 'install-mask'
> > +
> > + },
> > + {
> > + xtype: 'button',
> > + bind: {
> > + text: '{buttonText}'
> > + },
> > + cbind: {
> > + nodename: '{nodename}'
> > + },
> > + handler: function() {
> > + var me = this.up('pveCephInstallWindow');
> > + var win = Ext.create('PVE.ceph.CephInstallWizard',{
> > + nodename: me.nodename
> > + });
> > + win.show();
> > + me.mon(win,'beforeClose', function(){
> > + me.fireEvent("cephInstallWindowClosed");
> > + me.close();
> > + });
> > +
> > + }
> > + }
> > + ]
> > +});
> >
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
More information about the pve-devel
mailing list