Commit e67078ee authored by Dietmar Maurer's avatar Dietmar Maurer

add monitor GUI

parent a89d3dd1
......@@ -261,17 +261,104 @@ __PACKAGE__->register_method ({
{ name => 'init' },
{ name => 'createmon' },
{ name => 'destroymon' },
{ name => 'listmon' },
{ name => 'createosd' },
{ name => 'destroyosd' },
{ name => 'stop' },
{ name => 'start' },
{ name => 'status' },
{ name => 'crush' },
{ name => 'config' },
];
return $result;
}});
__PACKAGE__->register_method ({
name => 'config',
path => 'config',
method => 'GET',
description => "Get Ceph configuration.",
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => { type => 'string' },
code => sub {
my ($param) = @_;
&$check_ceph_inited();
return PVE::Tools::file_get_contents($pve_ceph_cfgpath);
}});
__PACKAGE__->register_method ({
name => 'listmon',
path => 'listmon',
method => 'GET',
description => "Get Ceph monitor list.",
proxyto => 'node',
protected => 1,
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
name => { type => 'string' },
addr => { type => 'string' },
},
},
},
code => sub {
my ($param) = @_;
&$check_ceph_inited();
my $res = [];
my $cfg = &$parse_ceph_config($pve_ceph_cfgpath);
my $monhash = {};
foreach my $section (keys %$cfg) {
my $d = $cfg->{$section};
if ($section =~ m/^mon\.(\S+)$/) {
my $monid = $1;
if ($d->{'mon addr'} && $d->{'host'}) {
$monhash->{$monid} = {
addr => $d->{'mon addr'},
host => $d->{'host'},
name => $monid,
}
}
}
}
eval {
my $monstat = ceph_mon_status();
my $mons = $monstat->{monmap}->{mons};
foreach my $d (@$mons) {
next if !defined($d->{name});
$monhash->{$d->{name}}->{rank} = $d->{rank};
$monhash->{$d->{name}}->{addr} = $d->{addr};
if (grep { $_ eq $d->{rank} } @{$monstat->{quorum}}) {
$monhash->{$d->{name}}->{quorum} = 1;
}
}
};
warn $@ if $@;
return PVE::RESTHandler::hash_to_array($monhash, 'name');
}});
__PACKAGE__->register_method ({
name => 'init',
path => 'init',
......@@ -509,20 +596,40 @@ __PACKAGE__->register_method ({
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
service => {
description => 'Ceph service name.',
type => 'string',
optional => 1,
pattern => '(mon|mds|osd)\.[A-Za-z0-9]{1,32}',
},
},
},
returns => { type => 'null' },
returns => { type => 'string' },
code => sub {
my ($param) = @_;
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
&$check_ceph_inited();
my $cfg = &$parse_ceph_config($pve_ceph_cfgpath);
scalar(keys %$cfg) || die "no configuration\n";
&$ceph_service_cmd('stop');
my $worker = sub {
my $upid = shift;
return undef;
my $cmd = ['stop'];
if ($param->{service}) {
push @$cmd, $param->{service};
}
&$ceph_service_cmd(@$cmd);
};
return $rpcenv->fork_worker('srvstop', $param->{service} || 'ceph',
$authuser, $worker);
}});
__PACKAGE__->register_method ({
......@@ -536,20 +643,40 @@ __PACKAGE__->register_method ({
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
service => {
description => 'Ceph service name.',
type => 'string',
optional => 1,
pattern => '(mon|mds|osd)\.[A-Za-z0-9]{1,32}',
},
},
},
returns => { type => 'null' },
returns => { type => 'string' },
code => sub {
my ($param) = @_;
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
&$check_ceph_inited();
my $cfg = &$parse_ceph_config($pve_ceph_cfgpath);
scalar(keys %$cfg) || die "no configuration\n";
&$ceph_service_cmd('start');
my $worker = sub {
my $upid = shift;
return undef;
my $cmd = ['start'];
if ($param->{service}) {
push @$cmd, $param->{service};
}
&$ceph_service_cmd(@$cmd);
};
return $rpcenv->fork_worker('srvstart', $param->{service} || 'ceph',
$authuser, $worker);
}});
__PACKAGE__->register_method ({
......
......@@ -36,6 +36,12 @@ $rpcenv->init_request();
$rpcenv->set_language($ENV{LANG});
$rpcenv->set_user('root@pam');
my $upid_exit = sub {
my $upid = shift;
my $status = PVE::Tools::upid_read_status($upid);
exit($status eq 'OK' ? 0 : -1);
};
my $nodename = PVE::INotify::nodename();
__PACKAGE__->register_method ({
......@@ -112,8 +118,10 @@ my $cmddef = {
destroyosd => [ 'PVE::API2::Ceph', 'destroyosd', ['osdid'], { node => $nodename } ],
createmon => [ 'PVE::API2::Ceph', 'createmon', [], { node => $nodename } ],
destroymon => [ 'PVE::API2::Ceph', 'destroymon', ['monid'], { node => $nodename } ],
start => [ 'PVE::API2::Ceph', 'start', [], { node => $nodename } ],
stop => [ 'PVE::API2::Ceph', 'stop', [], { node => $nodename } ],
start => [ 'PVE::API2::Ceph', 'start', ['service'], { node => $nodename },
$upid_exit],
stop => [ 'PVE::API2::Ceph', 'stop', ['service'], { node => $nodename },
$upid_exit],
install => [ __PACKAGE__, 'install', [] ],
purge => [ __PACKAGE__, 'purge', [] ],
status => [ 'PVE::API2::Ceph', 'status', [], { node => $nodename }, sub {
......
Ext.define('PVE.node.CephMonList', {
extend: 'Ext.grid.GridPanel',
alias: 'widget.pveNodeCephMonList',
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename) {
throw "no node name specified";
}
var sm = Ext.create('Ext.selection.RowModel', {});
var rstore = Ext.create('PVE.data.UpdateStore', {
interval: 3000,
storeid: 'ceph-mon-list',
model: 'ceph-mon-list',
proxy: {
type: 'pve',
url: "/api2/json/nodes/" + nodename + "/ceph/listmon"
}
});
var store = Ext.create('PVE.data.DiffStore', { rstore: rstore });
PVE.Utils.monStoreErrors(me, rstore);
var service_cmd = function(cmd) {
var rec = sm.getSelection()[0];
PVE.Utils.API2Request({
url: "/nodes/" + nodename + "/ceph/" + cmd,
method: 'POST',
params: { service: "mon." + rec.data.name },
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
}
});
};
var start_btn = new PVE.button.Button({
text: gettext('Start'),
selModel: sm,
disabled: true,
handler: function(){
service_cmd("start");
}
});
var stop_btn = new PVE.button.Button({
text: gettext('Stop'),
selModel: sm,
disabled: true,
handler: function(){
service_cmd("stop");
}
});
Ext.apply(me, {
store: store,
selModel: sm,
stateful: false,
tbar: [ start_btn, stop_btn ],
columns: [
{
header: gettext('Name'),
width: 50,
sortable: true,
renderer: function(v) { return "mon." + v; },
dataIndex: 'name'
},
{
header: gettext('Host'),
width: 100,
sortable: true,
renderer: function(v) {
return v ? v : 'unknown';
},
dataIndex: 'host'
},
{
header: gettext('Quorum'),
width: 50,
sortable: false,
renderer: PVE.Utils.format_boolean,
dataIndex: 'quorum'
},
{
header: gettext('Address'),
flex: 1,
sortable: true,
dataIndex: 'addr'
}
],
listeners: {
show: rstore.startUpdate,
hide: rstore.stopUpdate,
destroy: rstore.stopUpdate
}
});
me.callParent();
}
}, function() {
Ext.define('ceph-mon-list', {
extend: 'Ext.data.Model',
fields: [ 'addr', 'name', 'rank', 'host', 'quorum' ],
idProperty: 'name'
});
});
Ext.define('PVE.node.CephConfig', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveNodeCephConfig',
load: function() {
var me = this;
PVE.Utils.API2Request({
url: me.url,
waitMsgTarget: me,
failure: function(response, opts) {
me.update(gettext('Error') + " " + response.htmlStatus);
},
success: function(response, opts) {
var data = response.result.data;
me.update(Ext.htmlEncode(data));
}
});
},
initComponent: function() {
var me = this;
var nodename = me.pveSelNode.data.node;
if (!nodename) {
throw "no node name specified";
}
Ext.apply(me, {
url: '/api2/extjs/nodes/' + nodename + '/ceph/config',
// style: 'padding-left:10px',
bodyStyle: 'white-space:pre',
bodyPadding: 5,
autoScroll: true,
listeners: {
show: function() {
me.load();
}
}
});
me.callParent();
me.load();
}
});
Ext.define('PVE.node.CephCrushMap', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveNodeCephCrushMap',
......@@ -28,7 +188,7 @@ Ext.define('PVE.node.CephCrushMap', {
Ext.apply(me, {
url: '/api2/extjs/nodes/' + nodename + '/ceph/crush',
style: 'padding-left:10px',
// style: 'padding-left:10px',
bodyStyle: 'white-space:pre',
bodyPadding: 5,
autoScroll: true,
......@@ -199,14 +359,14 @@ Ext.define('PVE.node.Ceph', {
itemId: 'status'
},
{
xtype: 'pveNodeCephConfig',
title: 'Config',
itemId: 'config',
html: "ABCD"
itemId: 'config'
},
{
xtype: 'pveNodeCephMonList',
title: 'Monitor',
itemId: 'test2',
html: "ABCD"
itemId: 'monlist'
},
{
title: 'OSD',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment