gui: ceph: add ServiceList component and use it
this is an abstraction for listing Ceph Services with a few improvements: * start/stop/restart buttons for all services (incl. icons) * a syslog button to view the syslog of that service * correct reloading behaviour when creating/destroying Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
c081e24cff
commit
c1814e6174
@ -96,6 +96,7 @@ JSSRC= \
|
|||||||
panel/IPSet.js \
|
panel/IPSet.js \
|
||||||
panel/ConfigPanel.js \
|
panel/ConfigPanel.js \
|
||||||
grid/BackupView.js \
|
grid/BackupView.js \
|
||||||
|
ceph/ServiceList.js \
|
||||||
ceph/FS.js \
|
ceph/FS.js \
|
||||||
ceph/Pool.js \
|
ceph/Pool.js \
|
||||||
ceph/OSD.js \
|
ceph/OSD.js \
|
||||||
|
@ -1,234 +1,46 @@
|
|||||||
Ext.define('PVE.CephCreateMon', {
|
Ext.define('PVE.node.CephMonMgrList', {
|
||||||
extend: 'Proxmox.window.Edit',
|
extend: 'Ext.container.Container',
|
||||||
alias: ['widget.pveCephCreateMon'],
|
xtype: 'pveNodeCephMonMgr',
|
||||||
|
|
||||||
subject: 'Ceph Monitor/Manager',
|
mixins: ['Proxmox.Mixin.CBind' ],
|
||||||
onlineHelp: 'pve_ceph_monitors',
|
|
||||||
|
|
||||||
showProgress: true,
|
|
||||||
|
|
||||||
setNode: function(nodename) {
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
me.nodename = nodename;
|
|
||||||
me.url = "/nodes/" + nodename + "/ceph/mon";
|
|
||||||
},
|
|
||||||
|
|
||||||
initComponent : function() {
|
|
||||||
|
|
||||||
var me = this;
|
|
||||||
|
|
||||||
if (!me.nodename) {
|
|
||||||
throw "no node name specified";
|
|
||||||
}
|
|
||||||
|
|
||||||
me.setNode(me.nodename);
|
|
||||||
|
|
||||||
me.isCreate = true;
|
|
||||||
|
|
||||||
Ext.applyIf(me, {
|
|
||||||
method: 'POST',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
xtype: 'pveNodeSelector',
|
|
||||||
submitValue: false,
|
|
||||||
fieldLabel: gettext('Host'),
|
|
||||||
selectCurNode: true,
|
|
||||||
allowBlank: false,
|
|
||||||
listeners: {
|
|
||||||
change: function(f, value) {
|
|
||||||
me.setNode(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
me.callParent();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ext.define('PVE.node.CephMonList', {
|
|
||||||
extend: 'Ext.grid.GridPanel',
|
|
||||||
alias: ['widget.pveNodeCephMonList'],
|
|
||||||
|
|
||||||
onlineHelp: 'chapter_pveceph',
|
onlineHelp: 'chapter_pveceph',
|
||||||
|
|
||||||
stateful: true,
|
defaults: {
|
||||||
stateId: 'grid-ceph-monitor',
|
border: false,
|
||||||
|
onlineHelp: 'chapter_pveceph',
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
|
||||||
initComponent: function() {
|
layout: {
|
||||||
var me = this;
|
type: 'vbox',
|
||||||
|
align: 'stretch'
|
||||||
|
},
|
||||||
|
|
||||||
var nodename = me.pveSelNode.data.node;
|
items: [
|
||||||
if (!nodename) {
|
{
|
||||||
throw "no node name specified";
|
xtype: 'pveNodeCephServiceList',
|
||||||
}
|
cbind: { pveSelNode: '{pveSelNode}' },
|
||||||
|
type: 'mon',
|
||||||
var sm = Ext.create('Ext.selection.RowModel', {});
|
additionalColumns: [
|
||||||
|
|
||||||
var rstore = Ext.create('Proxmox.data.UpdateStore', {
|
|
||||||
interval: 3000,
|
|
||||||
storeid: 'ceph-mon-list' + nodename,
|
|
||||||
model: 'ceph-mon-list',
|
|
||||||
proxy: {
|
|
||||||
type: 'proxmox',
|
|
||||||
url: "/api2/json/nodes/" + nodename + "/ceph/mon"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var store = Ext.create('Proxmox.data.DiffStore', {
|
|
||||||
rstore: rstore,
|
|
||||||
sorters: [{ property: 'name'}]
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var service_cmd = function(cmd) {
|
|
||||||
var rec = sm.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/" + cmd,
|
|
||||||
method: 'POST',
|
|
||||||
params: { service: "mon." + rec.data.name },
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var start_btn = new Proxmox.button.Button({
|
|
||||||
text: gettext('Start'),
|
|
||||||
selModel: sm,
|
|
||||||
disabled: true,
|
|
||||||
handler: function(){
|
|
||||||
service_cmd("start");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var stop_btn = new Proxmox.button.Button({
|
|
||||||
text: gettext('Stop'),
|
|
||||||
selModel: sm,
|
|
||||||
disabled: true,
|
|
||||||
handler: function(){
|
|
||||||
service_cmd("stop");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var restart_btn = new Proxmox.button.Button({
|
|
||||||
text: gettext('Restart'),
|
|
||||||
selModel: sm,
|
|
||||||
disabled: true,
|
|
||||||
handler: function(){
|
|
||||||
service_cmd("restart");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var create_btn = new Ext.Button({
|
|
||||||
text: gettext('Create'),
|
|
||||||
handler: function(){
|
|
||||||
var win = Ext.create('PVE.CephCreateMon', {
|
|
||||||
nodename: nodename
|
|
||||||
});
|
|
||||||
win.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var remove_btn = new Proxmox.button.Button({
|
|
||||||
text: gettext('Remove'),
|
|
||||||
selModel: sm,
|
|
||||||
disabled: true,
|
|
||||||
handler: function() {
|
|
||||||
var rec = sm.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/mon/" +
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ext.apply(me, {
|
|
||||||
store: store,
|
|
||||||
selModel: sm,
|
|
||||||
tbar: [ start_btn, stop_btn, restart_btn, '-', create_btn, remove_btn ],
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
header: gettext('Name'),
|
|
||||||
width: 100,
|
|
||||||
sortable: true,
|
|
||||||
renderer: function(v) { return "mon." + v; },
|
|
||||||
dataIndex: 'name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext('Host'),
|
|
||||||
width: 100,
|
|
||||||
sortable: true,
|
|
||||||
renderer: function(v) {
|
|
||||||
return v || 'unknown';
|
|
||||||
},
|
|
||||||
dataIndex: 'host'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
header: gettext('Quorum'),
|
header: gettext('Quorum'),
|
||||||
width: 70,
|
width: 70,
|
||||||
sortable: false,
|
sortable: true,
|
||||||
renderer: Proxmox.Utils.format_boolean,
|
renderer: Proxmox.Utils.format_boolean,
|
||||||
dataIndex: 'quorum'
|
dataIndex: 'quorum'
|
||||||
},
|
|
||||||
{
|
|
||||||
header: gettext('Address'),
|
|
||||||
flex: 1,
|
|
||||||
sortable: true,
|
|
||||||
dataIndex: 'addr'
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
listeners: {
|
stateId: 'grid-ceph-monitor',
|
||||||
activate: rstore.startUpdate,
|
showCephInstallMask: true,
|
||||||
destroy: rstore.stopUpdate
|
title: gettext('Monitor')
|
||||||
}
|
},
|
||||||
});
|
{
|
||||||
|
xtype: 'pveNodeCephServiceList',
|
||||||
var regex = new RegExp("not (installed|initialized)", "i");
|
type: 'mgr',
|
||||||
PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
|
stateId: 'grid-ceph-manager',
|
||||||
me.store.rstore.stopUpdate();
|
cbind: { pveSelNode: '{pveSelNode}' },
|
||||||
PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
|
title: gettext('Manager')
|
||||||
function(win){
|
}
|
||||||
me.mon(win, 'cephInstallWindowClosed', function(){
|
]
|
||||||
me.store.rstore.startUpdate();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
me.callParent();
|
|
||||||
}
|
|
||||||
}, function() {
|
|
||||||
|
|
||||||
Ext.define('ceph-mon-list', {
|
|
||||||
extend: 'Ext.data.Model',
|
|
||||||
fields: [ 'addr', 'name', 'rank', 'host', 'quorum' ],
|
|
||||||
idProperty: 'name'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
324
www/manager6/ceph/ServiceList.js
Normal file
324
www/manager6/ceph/ServiceList.js
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
Ext.define('PVE.CephCreateService', {
|
||||||
|
extend: 'Proxmox.window.Edit',
|
||||||
|
xtype: 'pveCephCreateService',
|
||||||
|
|
||||||
|
showProgress: true,
|
||||||
|
|
||||||
|
setNode: function(nodename) {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
me.nodename = nodename;
|
||||||
|
me.url = "/nodes/" + nodename + "/ceph/" + me.type;
|
||||||
|
},
|
||||||
|
|
||||||
|
method: 'POST',
|
||||||
|
isCreate: true,
|
||||||
|
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
xtype: 'pveNodeSelector',
|
||||||
|
submitValue: false,
|
||||||
|
fieldLabel: gettext('Host'),
|
||||||
|
selectCurNode: true,
|
||||||
|
allowBlank: false,
|
||||||
|
listeners: {
|
||||||
|
change: function(f, value) {
|
||||||
|
var me = this.up('pveCephCreateService');
|
||||||
|
me.setNode(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
initComponent : function() {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
if (!me.nodename) {
|
||||||
|
throw "no node name specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!me.type) {
|
||||||
|
throw "no type specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
me.setNode(me.nodename);
|
||||||
|
|
||||||
|
me.callParent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.define('PVE.node.CephServiceList', {
|
||||||
|
extend: 'Ext.grid.GridPanel',
|
||||||
|
xtype: 'pveNodeCephServiceList',
|
||||||
|
|
||||||
|
onlineHelp: 'chapter_pveceph',
|
||||||
|
emptyText: Ext.String.format(gettext('No {0} configured.'), 'MDS'),
|
||||||
|
|
||||||
|
stateful: true,
|
||||||
|
|
||||||
|
// will be called when the store loads
|
||||||
|
storeLoadCallback: Ext.emptyFn,
|
||||||
|
|
||||||
|
// if set to true, does shows the ceph install mask if needed
|
||||||
|
showCephInstallMask: false,
|
||||||
|
|
||||||
|
controller: {
|
||||||
|
xclass: 'Ext.app.ViewController',
|
||||||
|
|
||||||
|
init: function(view) {
|
||||||
|
if (view.pveSelNode) {
|
||||||
|
view.nodename = view.pveSelNode.data.node;
|
||||||
|
}
|
||||||
|
if (!view.nodename) {
|
||||||
|
throw "no node name specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!view.type) {
|
||||||
|
throw "no type specified";
|
||||||
|
}
|
||||||
|
|
||||||
|
view.rstore = Ext.create('Proxmox.data.UpdateStore', {
|
||||||
|
autoLoad: true,
|
||||||
|
autoStart: true,
|
||||||
|
interval: 3000,
|
||||||
|
storeid: 'ceph-' + view.type + '-list' + view.nodename,
|
||||||
|
model: 'ceph-service-list',
|
||||||
|
proxy: {
|
||||||
|
type: 'proxmox',
|
||||||
|
url: "/api2/json/nodes/" + view.nodename + "/ceph/" + view.type
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
view.setStore(Ext.create('Proxmox.data.DiffStore', {
|
||||||
|
rstore: view.rstore,
|
||||||
|
sorters: [{ property: 'name' }]
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (view.storeLoadCallback) {
|
||||||
|
view.rstore.on('load', view.storeLoadCallback, this);
|
||||||
|
}
|
||||||
|
view.on('destroy', view.rstore.stopUpdate);
|
||||||
|
|
||||||
|
if (view.showCephInstallMask) {
|
||||||
|
var regex = new RegExp("not (installed|initialized)", "i");
|
||||||
|
PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error) {
|
||||||
|
view.rstore.stopUpdate();
|
||||||
|
PVE.Utils.showCephInstallOrMask(view.ownerCt, error.statusText, view.nodename,
|
||||||
|
function(win){
|
||||||
|
me.mon(win, 'cephInstallWindowClosed', function(){
|
||||||
|
view.rstore.startUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
service_cmd: function(rec, cmd) {
|
||||||
|
var view = this.getView();
|
||||||
|
if (!rec.data.host) {
|
||||||
|
Ext.Msg.alert(gettext('Error'), "entry has no host");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Proxmox.Utils.API2Request({
|
||||||
|
url: "/nodes/" + rec.data.host + "/ceph/" + cmd,
|
||||||
|
method: 'POST',
|
||||||
|
params: { service: view.type + '.' + rec.data.name },
|
||||||
|
success: function(response, options) {
|
||||||
|
var upid = response.result.data;
|
||||||
|
var win = Ext.create('Proxmox.window.TaskProgress', {
|
||||||
|
upid: upid,
|
||||||
|
taskDone: function() {
|
||||||
|
view.rstore.load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
win.show();
|
||||||
|
},
|
||||||
|
failure: function(response, opts) {
|
||||||
|
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onChangeService: function(btn) {
|
||||||
|
var me = this;
|
||||||
|
var view = this.getView();
|
||||||
|
var cmd = btn.action;
|
||||||
|
var rec = view.getSelection()[0];
|
||||||
|
me.service_cmd(rec, cmd);
|
||||||
|
},
|
||||||
|
|
||||||
|
showSyslog: function() {
|
||||||
|
var view = this.getView();
|
||||||
|
var rec = view.getSelection()[0];
|
||||||
|
var servicename = 'ceph-' + view.type + '@' + rec.data.name;
|
||||||
|
var url = "/api2/extjs/nodes/" + rec.data.host + "/syslog?service=" + encodeURIComponent(servicename);
|
||||||
|
var win = Ext.create('Ext.window.Window', {
|
||||||
|
title: gettext('Syslog') + ': ' + servicename,
|
||||||
|
modal: true,
|
||||||
|
items: [{
|
||||||
|
xtype: 'proxmoxLogView',
|
||||||
|
width: 800,
|
||||||
|
height: 400,
|
||||||
|
url: url,
|
||||||
|
log_select_timespan: 1
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
win.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
onCreate: function() {
|
||||||
|
var view = this.getView();
|
||||||
|
var win = Ext.create('PVE.CephCreateService', {
|
||||||
|
autoShow: true,
|
||||||
|
nodename: view.nodename,
|
||||||
|
subject: view.getTitle(),
|
||||||
|
type: view.type,
|
||||||
|
taskDone: function() {
|
||||||
|
view.rstore.load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
tbar: [
|
||||||
|
{
|
||||||
|
xtype: 'proxmoxButton',
|
||||||
|
text: gettext('Start'),
|
||||||
|
iconCls: 'fa fa-play',
|
||||||
|
action: 'start',
|
||||||
|
disabled: true,
|
||||||
|
enableFn: function(rec) {
|
||||||
|
return rec.data.state === 'stopped' ||
|
||||||
|
rec.data.state === 'unknown';
|
||||||
|
},
|
||||||
|
handler: 'onChangeService'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xtype: 'proxmoxButton',
|
||||||
|
text: gettext('Stop'),
|
||||||
|
iconCls: 'fa fa-stop',
|
||||||
|
action: 'stop',
|
||||||
|
enableFn: function(rec) {
|
||||||
|
return rec.data.state !== 'stopped';
|
||||||
|
},
|
||||||
|
disabled: true,
|
||||||
|
handler: 'onChangeService'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xtype: 'proxmoxButton',
|
||||||
|
text: gettext('Restart'),
|
||||||
|
iconCls: 'fa fa-refresh',
|
||||||
|
action: 'restart',
|
||||||
|
disabled: true,
|
||||||
|
enableFn: function(rec) {
|
||||||
|
return rec.data.state !== 'stopped';
|
||||||
|
},
|
||||||
|
handler: 'onChangeService'
|
||||||
|
},
|
||||||
|
'-',
|
||||||
|
{
|
||||||
|
text: gettext('Create'),
|
||||||
|
reference: 'createButton',
|
||||||
|
handler: 'onCreate'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: gettext('Destroy'),
|
||||||
|
xtype: 'proxmoxStdRemoveButton',
|
||||||
|
getUrl: function(rec) {
|
||||||
|
var view = this.up('grid');
|
||||||
|
if (!rec.data.host) {
|
||||||
|
Ext.Msg.alert(gettext('Error'), "entry has no host");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return "/nodes/" + rec.data.host + "/ceph/" + view.type + "/" + rec.data.name;
|
||||||
|
},
|
||||||
|
callback: function(options, success, response) {
|
||||||
|
var view = this.up('grid');
|
||||||
|
if (!success) {
|
||||||
|
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var upid = response.result.data;
|
||||||
|
var win = Ext.create('Proxmox.window.TaskProgress', {
|
||||||
|
upid: upid,
|
||||||
|
taskDone: function() {
|
||||||
|
view.rstore.load();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
win.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'-',
|
||||||
|
{
|
||||||
|
xtype: 'proxmoxButton',
|
||||||
|
text: gettext('Syslog'),
|
||||||
|
disabled: true,
|
||||||
|
handler: 'showSyslog'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
header: gettext('Name'),
|
||||||
|
width: 100,
|
||||||
|
sortable: true,
|
||||||
|
renderer: function(v) {
|
||||||
|
return this.type + '.' + v;
|
||||||
|
},
|
||||||
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Host'),
|
||||||
|
width: 100,
|
||||||
|
sortable: true,
|
||||||
|
renderer: function(v) {
|
||||||
|
return v || Proxmox.Utils.unknownText;
|
||||||
|
},
|
||||||
|
dataIndex: 'host'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Status'),
|
||||||
|
width: 70,
|
||||||
|
sortable: false,
|
||||||
|
dataIndex: 'state'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Address'),
|
||||||
|
flex: 1,
|
||||||
|
sortable: true,
|
||||||
|
renderer: function(v) {
|
||||||
|
return v || Proxmox.Utils.unknownText;
|
||||||
|
},
|
||||||
|
dataIndex: 'addr'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: gettext('Version'),
|
||||||
|
flex: 1,
|
||||||
|
sortable: true,
|
||||||
|
dataIndex: 'version'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
initComponent: function() {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
if (me.additionalColumns) {
|
||||||
|
me.columns = me.columns.concat(me.additionalColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
me.callParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, function() {
|
||||||
|
|
||||||
|
Ext.define('ceph-service-list', {
|
||||||
|
extend: 'Ext.data.Model',
|
||||||
|
fields: [ 'addr', 'name', 'rank', 'host', 'quorum', 'state',
|
||||||
|
'ceph_version', 'ceph_version_short',
|
||||||
|
{ type: 'string', name: 'version', calculate: function(data) {
|
||||||
|
return PVE.Utils.parse_ceph_version(data);
|
||||||
|
} }
|
||||||
|
],
|
||||||
|
idProperty: 'name'
|
||||||
|
});
|
||||||
|
});
|
@ -326,7 +326,7 @@ Ext.define('PVE.node.Config', {
|
|||||||
itemId: 'ceph-config'
|
itemId: 'ceph-config'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'pveNodeCephMonList',
|
xtype: 'pveNodeCephMonMgr',
|
||||||
title: gettext('Monitor'),
|
title: gettext('Monitor'),
|
||||||
iconCls: 'fa fa-tv',
|
iconCls: 'fa fa-tv',
|
||||||
groups: ['ceph'],
|
groups: ['ceph'],
|
||||||
|
Loading…
Reference in New Issue
Block a user