[pve-devel] [PATCH v6 manager 6/6] added basic ability to install ceph via gui

Tim Marx t.marx at proxmox.com
Wed Feb 27 15:01:23 CET 2019


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);
+	});
     }
 },
 
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', {
+				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")){
+						me.store.stopUpdate();
+						me.down('textfield').setValue('success');
+					    } else if (!response.statusText.match("not installed", "i")) {
+						me.store.stopUpdate();
+						var wizard = me.up('#wizcontent');
+						var tabs = wizard.items;
+						var lastTab = tabs.items[tabs.length-1];
+						lastTab.enable();
+						wizard.setActiveTab(lastTab);
+					    }
+					}
+				    }
+				},
+				listeners: {
+				    load: function(rec, response, success){
+					if(success){
+					    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();
+		    }
+		},
+		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')
+		    }
+		],
+		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);
+			}
+		    },
+		    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");
+		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']);
+		    }
+		}
 	    },
 	    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']);
+			}
+		    });
 		    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) + "<br>";
+		});
+
+		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']);
+	    }
+	});
+
 	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',
+    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') + '<br>' +
+	    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();
+		});
+
+	    }
+	}
+    ]
+});
-- 
2.11.0



More information about the pve-devel mailing list