pve-manager/PVE/API2/Ceph/MDS.pm
Tim Marx 1aa902ae90 ceph api: added check for /etc/pve/ceph.conf to remaining/new endpoints
Signed-off-by: Tim Marx <t.marx@proxmox.com>
2018-12-13 10:14:39 +01:00

246 lines
5.8 KiB
Perl

package PVE::API2::Ceph::MDS;
use strict;
use warnings;
use PVE::CephTools;
use PVE::INotify;
use PVE::JSONSchema qw(get_standard_option);
use PVE::RADOS;
use PVE::RESTHandler;
use PVE::RPCEnvironment;
use base qw(PVE::RESTHandler);
__PACKAGE__->register_method ({
name => 'index',
path => '',
method => 'GET',
description => "MDS directory index.",
permissions => {
check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
},
proxyto => 'node',
protected => 1,
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
},
},
returns => {
type => 'array',
items => {
type => "object",
properties => {
name => {
description => "The name (ID) for the MDS",
},
addr => {
type => 'string',
optional => 1,
},
host => {
type => 'string',
optional => 1,
},
state => {
type => 'string',
description => 'State of the MDS',
},
standby_replay => {
type => 'boolean',
optional => 1,
description => 'If true, the standby MDS is polling the active MDS for faster recovery (hot standby).',
},
rank => {
type => 'integer',
optional => 1,
},
},
},
links => [ { rel => 'child', href => "{name}" } ],
},
code => sub {
my ($param) = @_;
PVE::CephTools::check_ceph_inited();
my $res = [];
my $cfg = PVE::CephTools::parse_ceph_config();
my $mds_hash = {};
foreach my $section (keys %$cfg) {
my $d = $cfg->{$section};
if ($section =~ m/^mds\.(\S+)$/) {
my $mds_id = $1;
if (defined($d->{host})) {
$mds_hash->{$mds_id} = {
name => $mds_id,
state => 'unknown',
addr => $d->{host},
host => $d->{host},
};
}
}
}
my $mds_state = PVE::CephTools::get_cluster_mds_state();
foreach my $name (keys %$mds_state) {
my $d = $mds_state->{$name};
# just overwrite, this always provides more info
$mds_hash->{$name}->{$_} = $d->{$_} for keys %$d;
}
return PVE::RESTHandler::hash_to_array($mds_hash, 'name');
}
});
__PACKAGE__->register_method ({
name => 'createmds',
path => '{name}',
method => 'POST',
description => "Create Ceph Metadata Server (MDS)",
proxyto => 'node',
protected => 1,
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
name => {
type => 'string',
optional => 1,
default => 'nodename',
pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
description => "The ID for the mds, when omitted the same as the nodename",
},
hotstandby => {
type => 'boolean',
optional => 1,
default => '0',
description => "Determines whether a ceph-mds daemon should poll and replay the log of an active MDS. ".
"Faster switch on MDS failure, but needs more idle resources.",
},
},
},
returns => { type => 'string' },
code => sub {
my ($param) = @_;
PVE::CephTools::check_ceph_installed('ceph_mds');
PVE::CephTools::check_ceph_inited();
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
my $nodename = $param->{node};
$nodename = INotify::nodename() if $nodename eq 'localhost';
my $mds_id = $param->{name} // $nodename;
my $worker = sub {
my $timeout = PVE::CephTools::get_config('long_rados_timeout');
my $rados = PVE::RADOS->new(timeout => $timeout);
my $cfg = PVE::CephTools::parse_ceph_config();
my $section = "mds.$mds_id";
if (defined($cfg->{$section})) {
die "MDS '$mds_id' already referenced in ceph config, abort!\n"
}
if (!defined($cfg->{mds}->{keyring})) {
# $id isn't a perl variable but a ceph metavariable
my $keyring = '/var/lib/ceph/mds/ceph-$id/keyring';
$cfg->{mds}->{keyring} = $keyring;
}
$cfg->{$section}->{host} = $nodename;
$cfg->{$section}->{"mds standby for name"} = 'pve';
if ($param->{hotstandby}) {
$cfg->{$section}->{"mds standby replay"} = 'true';
}
PVE::CephTools::write_ceph_config($cfg);
eval { PVE::CephTools::create_mds($mds_id, $rados) };
if (my $err = $@) {
# we abort early if the section is defined, so we know that we
# wrote it at this point. Do not auto remove the service, could
# do real harm for previously manual setup MDS
warn "Encountered error, remove '$section' from ceph.conf\n";
$cfg = PVE::CephTools::parse_ceph_config();
delete $cfg->{$section};
PVE::CephTools::write_ceph_config($cfg);
die "$err\n";
}
};
return $rpcenv->fork_worker('cephcreatemds', "mds.$mds_id", $authuser, $worker);
}
});
__PACKAGE__->register_method ({
name => 'destroymds',
path => '{name}',
method => 'DELETE',
description => "Destroy Ceph Metadata Server",
proxyto => 'node',
protected => 1,
permissions => {
check => ['perm', '/', [ 'Sys.Modify' ]],
},
parameters => {
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
name => {
description => 'The name (ID) of the mds',
type => 'string',
pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
},
},
},
returns => { type => 'string' },
code => sub {
my ($param) = @_;
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
PVE::CephTools::check_ceph_inited();
my $mds_id = $param->{name};
my $worker = sub {
my $timeout = PVE::CephTools::get_config('long_rados_timeout');
my $rados = PVE::RADOS->new(timeout => $timeout);
my $cfg = PVE::CephTools::parse_ceph_config();
if (defined($cfg->{"mds.$mds_id"})) {
delete $cfg->{"mds.$mds_id"};
PVE::CephTools::write_ceph_config($cfg);
}
PVE::CephTools::destroy_mds($mds_id, $rados);
};
return $rpcenv->fork_worker('cephdestroymds', "mds.$mds_id", $authuser, $worker);
}
});
1;