[pve-devel] [PATCH manager v2 5/5] ui: add CephFS integration
Thomas Lamprecht
t.lamprecht at proxmox.com
Thu Nov 22 20:34:22 CET 2018
create/destroy MDS and create CephFS (if none is configured yet).
Can be improved, e.g., start/stop/restart for MDS this should be enough for a
starter, though.
Basic code and ui layout is based off my dc/Cluster view. We may want to split
the two grids out in separate defines, it could be a bit much to have all
inline.
Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
new in v2
www/manager6/Makefile | 1 +
www/manager6/ceph/FS.js | 385 ++++++++++++++++++++++++++++++++++++
www/manager6/node/Config.js | 8 +
3 files changed, 394 insertions(+)
create mode 100644 www/manager6/ceph/FS.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index d005d714..e75f0de6 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -93,6 +93,7 @@ JSSRC= \
panel/IPSet.js \
panel/ConfigPanel.js \
grid/BackupView.js \
+ ceph/FS.js \
ceph/Pool.js \
ceph/OSD.js \
ceph/Monitor.js \
diff --git a/www/manager6/ceph/FS.js b/www/manager6/ceph/FS.js
new file mode 100644
index 00000000..f2743a4d
--- /dev/null
+++ b/www/manager6/ceph/FS.js
@@ -0,0 +1,385 @@
+/*jslint confusion: true */
+Ext.define('PVE.CephCreateFS', {
+ extend: 'Proxmox.window.Edit',
+ alias: 'widget.pveCephCreateFS',
+
+ showTaskViewer: true,
+ //onlineHelp: 'pve_ceph_fs',
+
+ subject: 'Ceph FS',
+ isCreate: true,
+ method: 'POST',
+
+ setFSName: function(fsName) {
+ var me = this;
+
+ if (fsName === '') {
+ fsName = 'cephfs';
+ }
+
+ me.url = "/nodes/" + me.nodename + "/ceph/fs/" + fsName;
+ },
+
+ items: [
+ {
+ xtype: 'textfield',
+ fieldLabel: gettext('Name'),
+ name: 'name',
+ value: 'cephfs',
+ listeners: {
+ change: function(f, value) {
+ this.up('pveCephCreateFS').setFSName(value);
+ }
+ },
+ submitValue: false, // already encoded in apicall URL
+ emptyText: 'cephfs'
+ },
+ {
+ xtype: 'proxmoxintegerfield',
+ fieldLabel: 'pg_num',
+ name: 'pg_num',
+ value: 64,
+ emptyText: 64,
+ minValue: 8,
+ maxValue: 32768,
+ allowBlank: false
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ fieldLabel: gettext('Add Storage'),
+ value: true,
+ name: 'add_storage'
+ }
+ ],
+
+ initComponent : function() {
+ var me = this;
+
+ if (!me.nodename) {
+ throw "no node name specified";
+ }
+
+ Ext.apply(me, {
+ url: "/nodes/" + me.nodename + "/ceph/fs/cephfs",
+ defaults: {
+ nodename: me.nodename
+ }
+ });
+
+ me.callParent();
+ }
+});
+
+Ext.define('PVE.CephCreateMDS', {
+ extend: 'Proxmox.window.Edit',
+ alias: 'widget.pveCephCreateMDS',
+
+ showProgress: true,
+ //onlineHelp: 'pve_ceph_mds',
+
+ subject: 'Ceph MDS',
+ isCreate: true,
+ method: 'POST',
+
+ setNode: function(nodename) {
+ var me = this;
+
+ me.nodename = nodename;
+ me.url = "/nodes/" + nodename + "/ceph/mds/" + nodename;
+ },
+
+ items: [
+ {
+ xtype: 'pveNodeSelector',
+ fieldLabel: gettext('Node'),
+ selectCurNode: true,
+ submitValue: false,
+ allowBlank: false,
+ listeners: {
+ change: function(f, value) {
+ this.up('pveCephCreateMDS').setNode(value);
+ }
+ }
+ }
+ ],
+
+ initComponent : function() {
+ var me = this;
+
+ if (!me.nodename) {
+ throw "no node name specified";
+ }
+
+ Ext.apply(me, {
+ url: "/nodes/" + me.nodename + "/ceph/mds/" + me.nodename
+ });
+
+ me.callParent();
+ }
+});
+
+Ext.define('PVE.NodeCephFSPanel', {
+ extend: 'Ext.panel.Panel',
+ xtype: 'pveNodeCephFSPanel',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ title: gettext('Cluster Administration'),
+ onlineHelp: 'chapter_pvecm',
+
+ border: false,
+ defaults: {
+ border: false,
+ cbind: {
+ nodename: '{nodename}'
+ }
+ },
+
+ viewModel: {
+ parent: null,
+ data: {
+ cephfsConfigured: false,
+ mdscount: 0
+ }
+ },
+
+ /*initComponent: function() {
+ var me = this;
+ Ext.apply(me, {
+ defaults: {
+ nodename: me.nodename,
+ border: false
+ }
+ });
+
+ me.callParent();
+ },*/
+
+ items: [
+ {
+ xtype: 'grid',
+ title: gettext('CephFS'),
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ init: function(view) {
+ view.rstore = Ext.create('Proxmox.data.UpdateStore', {
+ autoLoad: true,
+ xtype: 'update',
+ interval: 5 * 1000,
+ autoStart: true,
+ storeid: 'pve-ceph-fs',
+ model: 'pve-ceph-fs'
+ });
+ view.setStore(Ext.create('Proxmox.data.DiffStore', {
+ rstore: view.rstore,
+ sorters: {
+ property: 'name',
+ order: 'DESC'
+ }
+ }));
+ Proxmox.Utils.monStoreErrors(view, view.rstore);
+ view.rstore.on('load', this.onLoad, this);
+ view.on('destroy', view.rstore.stopUpdate);
+ },
+
+ onCreate: function() {
+ var view = this.getView();
+ view.rstore.stopUpdate();
+ var win = Ext.create('PVE.CephCreateFS', {
+ autoShow: true,
+ nodename: view.nodename,
+ listeners: {
+ destroy: function() {
+ view.rstore.startUpdate();
+ }
+ }
+ });
+ },
+
+ onLoad: function(store, records, success) {
+ var vm = this.getViewModel();
+ if (!(success && records && records.length > 0)) {
+ vm.set('cephfsConfigured', false);
+ return;
+ }
+ vm.set('cephfsConfigured', true);
+ }
+ },
+ tbar: [
+ {
+ text: gettext('Create CephFS'),
+ reference: 'createButton',
+ handler: 'onCreate',
+ bind: {
+ // only one CephFS per Ceph cluster makes sense for now
+ disabled: '{cephfsConfigured}'
+ }
+ }
+ ],
+ columns: [
+ {
+ header: gettext('Name'),
+ flex: 1,
+ dataIndex: 'name'
+ },
+ {
+ header: 'Data Pool',
+ flex: 1,
+ dataIndex: 'data_pool'
+ },
+ {
+ header: 'Metadata Pool',
+ flex: 1,
+ dataIndex: 'metadata_pool'
+ }
+ ],
+ cbind: {
+ nodename: '{nodename}'
+ }
+ },
+ {
+ xtype: 'grid',
+ title: gettext('Metadata Servers'),
+ viewModel: {
+ data: {
+ rowSelected: false
+ }
+ },
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ init: function(view) {
+ view.rstore = Ext.create('Proxmox.data.UpdateStore', {
+ autoLoad: true,
+ xtype: 'update',
+ interval: 3 * 1000,
+ autoStart: true,
+ storeid: 'pve-ceph-mds',
+ model: 'pve-ceph-mds'
+ });
+ view.setStore(Ext.create('Proxmox.data.DiffStore', {
+ rstore: view.rstore,
+ sorters: {
+ property: 'id',
+ order: 'DESC'
+ }
+ }));
+ Proxmox.Utils.monStoreErrors(view, view.rstore);
+ view.rstore.on('load', this.onLoad, this);
+ view.on('destroy', view.rstore.stopUpdate);
+
+ var vm = this.getViewModel();
+ view.mon(view.selModel, "selectionchange", function() {
+ var rec = view.selModel.getSelection()[0];
+
+ vm.set('rowSelected', !!rec);
+ });
+ },
+
+ onCreateMDS: function() {
+ var view = this.getView();
+ view.rstore.stopUpdate();
+ var win = Ext.create('PVE.CephCreateMDS', {
+ autoShow: true,
+ nodename: view.nodename,
+ listeners: {
+ destroy: function() {
+ view.rstore.startUpdate();
+ }
+ }
+ });
+ },
+
+ onDestroyMDS: function() {
+ var view = this.getView();
+ var rec = view.selModel.getSelection()[0];
+
+ if (!rec.data.host) {
+ Ext.Msg.alert(gettext('Error'), "entry has no host");
+ return;
+ }
+
+ Proxmox.Utils.API2Request({
+ url: "/nodes/" + rec.data.host + "/ceph/mds/" + rec.data.name,
+ method: 'DELETE',
+ success: function(response, options) {
+ var upid = response.result.data;
+ var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
+ win.show();
+ },
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ }
+ });
+ },
+
+ onLoad: function(store, records, success) {
+ var vm = this.getViewModel();
+ if (!success || !records) {
+ vm.set('mdscount', 0);
+ return;
+ }
+ vm.set('mdscount', records.length);
+ }
+ },
+ tbar: [
+ {
+ text: gettext('Create MDS'),
+ reference: 'createButton',
+ handler: 'onCreateMDS'
+ },
+ {
+ text: gettext('Destroy MDS'),
+ bind: {
+ disabled: '{!rowSelected}'
+ },
+ handler: 'onDestroyMDS'
+ }
+ ],
+ columns: [
+ {
+ header: gettext('Name'),
+ flex: 1,
+ dataIndex: 'name'
+ },
+ {
+ header: gettext('Host'),
+ flex: 1,
+ dataIndex: 'host'
+ },
+ {
+ header: gettext('Address'),
+ flex: 1,
+ dataIndex: 'addr'
+ },
+ {
+ header: gettext('State'),
+ flex: 1,
+ dataIndex: 'state'
+ }
+ ],
+ cbind: {
+ nodename: '{nodename}'
+ }
+ }
+ ]
+}, function() {
+ Ext.define('pve-ceph-mds', {
+ extend: 'Ext.data.Model',
+ fields: [ 'name', 'host', 'addr', 'state' ],
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/nodes/localhost/ceph/mds"
+ },
+ idProperty: 'name'
+ });
+ Ext.define('pve-ceph-fs', {
+ extend: 'Ext.data.Model',
+ fields: [ 'name', 'data_pool', 'metadata_pool' ],
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/nodes/localhost/ceph/fs"
+ },
+ idProperty: 'name'
+ });
+});
diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index 8b2b802a..f9a62670 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -340,6 +340,14 @@ Ext.define('PVE.node.Config', {
groups: ['ceph'],
itemId: 'ceph-osdtree'
},
+ {
+ xtype: 'pveNodeCephFSPanel',
+ title: 'CephFS',
+ iconCls: 'fa fa-folder',
+ groups: ['ceph'],
+ nodename: nodename,
+ itemId: 'ceph-cephfspanel'
+ },
{
xtype: 'pveNodeCephPoolList',
title: 'Pools',
--
2.19.1
More information about the pve-devel
mailing list