mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-07-15 07:05:05 +00:00

As suggested in [1], it is recommended to use `_` in all cases when dealing with config files. Note that this is for creation only, and we enforce that there cannot be an existing MDS with the same ID, so we do not have to bother how ceph would handle the case where both exist. [1] https://docs.ceph.com/en/reef/rados/configuration/ceph-conf/#option-names Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com> Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
234 lines
5.7 KiB
Perl
234 lines
5.7 KiB
Perl
package PVE::API2::Ceph::MDS;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use PVE::Ceph::Tools;
|
|
use PVE::Ceph::Services;
|
|
use PVE::Cluster qw(cfs_read_file cfs_write_file);
|
|
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::Ceph::Tools::check_ceph_inited();
|
|
|
|
my $res = [];
|
|
|
|
my $cfg = cfs_read_file('ceph.conf');
|
|
my $rados = PVE::RADOS->new();
|
|
|
|
my $mds_hash = PVE::Ceph::Services::get_services_info("mds", $cfg, $rados);
|
|
|
|
my $mds_state = PVE::Ceph::Services::get_cluster_mds_state($rados);
|
|
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 => PVE::Ceph::Services::SERVICE_REGEX,
|
|
maxLength => 200,
|
|
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::Ceph::Tools::check_ceph_installed('ceph_mds');
|
|
|
|
PVE::Ceph::Tools::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::Ceph::Tools::get_config('long_rados_timeout');
|
|
my $rados = PVE::RADOS->new(timeout => $timeout);
|
|
|
|
my $cfg = cfs_read_file('ceph.conf');
|
|
|
|
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';
|
|
}
|
|
|
|
cfs_write_file('ceph.conf', $cfg);
|
|
|
|
eval { PVE::Ceph::Services::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";
|
|
my $cfg = cfs_read_file('ceph.conf');
|
|
delete $cfg->{$section};
|
|
cfs_write_file('ceph.conf', $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 => PVE::Ceph::Services::SERVICE_REGEX,
|
|
},
|
|
},
|
|
},
|
|
returns => { type => 'string' },
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
my $rpcenv = PVE::RPCEnvironment::get();
|
|
|
|
my $authuser = $rpcenv->get_user();
|
|
|
|
PVE::Ceph::Tools::check_ceph_inited();
|
|
|
|
my $mds_id = $param->{name};
|
|
|
|
my $worker = sub {
|
|
my $timeout = PVE::Ceph::Tools::get_config('long_rados_timeout');
|
|
my $rados = PVE::RADOS->new(timeout => $timeout);
|
|
|
|
my $cfg = cfs_read_file('ceph.conf');
|
|
|
|
if (defined($cfg->{"mds.$mds_id"})) {
|
|
delete $cfg->{"mds.$mds_id"};
|
|
cfs_write_file('ceph.conf', $cfg);
|
|
}
|
|
|
|
PVE::Ceph::Services::destroy_mds($mds_id, $rados);
|
|
};
|
|
|
|
return $rpcenv->fork_worker('cephdestroymds', "mds.$mds_id", $authuser, $worker);
|
|
}
|
|
});
|
|
|
|
1;
|