[pve-devel] [PATCH manager 7/7] ceph: move Monitor API calls to API2/Ceph/MON.pm
Dominik Csapak
d.csapak at proxmox.com
Wed Dec 19 11:24:47 CET 2018
and adapt the paths
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
PVE/API2/Ceph.pm | 354 +----------------------------------------------
PVE/API2/Ceph/MON.pm | 369 +++++++++++++++++++++++++++++++++++++++++++++++++
PVE/API2/Ceph/Makefile | 1 +
PVE/CLI/pveceph.pm | 5 +-
4 files changed, 379 insertions(+), 350 deletions(-)
create mode 100644 PVE/API2/Ceph/MON.pm
diff --git a/PVE/API2/Ceph.pm b/PVE/API2/Ceph.pm
index 60988996..8304f4d0 100644
--- a/PVE/API2/Ceph.pm
+++ b/PVE/API2/Ceph.pm
@@ -22,6 +22,7 @@ use PVE::API2::Ceph::OSD;
use PVE::API2::Ceph::FS;
use PVE::API2::Ceph::MDS;
use PVE::API2::Ceph::MGR;
+use PVE::API2::Ceph::MON;
use PVE::API2::Storage::Config;
use base qw(PVE::RESTHandler);
@@ -44,6 +45,11 @@ __PACKAGE__->register_method ({
});
__PACKAGE__->register_method ({
+ subclass => "PVE::API2::Ceph::MON",
+ path => 'mon',
+});
+
+__PACKAGE__->register_method ({
subclass => "PVE::API2::Ceph::FS",
path => 'fs',
});
@@ -218,75 +224,6 @@ my $get_storages = sub {
};
__PACKAGE__->register_method ({
- name => 'listmon',
- path => 'mon',
- method => 'GET',
- description => "Get Ceph monitor list.",
- proxyto => 'node',
- protected => 1,
- permissions => {
- check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
- },
- parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- },
- },
- returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- name => { type => 'string' },
- addr => { type => 'string' },
- },
- },
- 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 $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 $rados = PVE::RADOS->new();
- my $monstat = $rados->mon_command({ prefix => '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',
method => 'POST',
@@ -416,285 +353,6 @@ __PACKAGE__->register_method ({
return undef;
}});
-my $find_mon_ip = sub {
- my ($pubnet, $node, $overwrite_ip) = @_;
-
- if (!$pubnet) {
- return $overwrite_ip // PVE::Cluster::remote_node_ip($node);
- }
-
- my $allowed_ips = PVE::Network::get_local_ip_from_cidr($pubnet);
- die "No IP configured and up from ceph public network '$pubnet'\n"
- if scalar(@$allowed_ips) < 1;
-
- if (!$overwrite_ip) {
- if (scalar(@$allowed_ips) == 1) {
- return $allowed_ips->[0];
- }
- die "Multiple IPs for ceph public network '$pubnet' detected on $node:\n".
- join("\n", @$allowed_ips) ."\nuse 'mon-address' to specify one of them.\n";
- } else {
- if (grep { $_ eq $overwrite_ip } @$allowed_ips) {
- return $overwrite_ip;
- }
- die "Monitor IP '$overwrite_ip' not in ceph public network '$pubnet'\n"
- if !PVE::Network::is_ip_in_cidr($overwrite_ip, $pubnet);
-
- die "Specified monitor IP '$overwrite_ip' not configured or up on $node!\n";
- }
-};
-
-__PACKAGE__->register_method ({
- name => 'createmon',
- path => 'mon',
- method => 'POST',
- description => "Create Ceph Monitor and Manager",
- proxyto => 'node',
- protected => 1,
- permissions => {
- check => ['perm', '/', [ 'Sys.Modify' ]],
- },
- parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- id => {
- type => 'string',
- optional => 1,
- pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
- description => "The ID for the monitor, when omitted the same as the nodename",
- },
- 'exclude-manager' => {
- type => 'boolean',
- optional => 1,
- default => 0,
- description => "When set, only a monitor will be created.",
- },
- 'mon-address' => {
- description => 'Overwrites autodetected monitor IP address. ' .
- 'Must be in the public network of ceph.',
- type => 'string', format => 'ip',
- optional => 1,
- },
- },
- },
- returns => { type => 'string' },
- code => sub {
- my ($param) = @_;
-
- PVE::Ceph::Tools::check_ceph_installed('ceph_mon');
-
- PVE::Ceph::Tools::check_ceph_installed('ceph_mgr')
- if (!$param->{'exclude-manager'});
-
- PVE::Ceph::Tools::check_ceph_inited();
-
- PVE::Ceph::Tools::setup_pve_symlinks();
-
- my $rpcenv = PVE::RPCEnvironment::get();
-
- my $authuser = $rpcenv->get_user();
-
- my $cfg = cfs_read_file('ceph.conf');
-
- my $moncount = 0;
-
- my $monaddrhash = {};
-
- my $systemd_managed = PVE::Ceph::Tools::systemd_managed();
-
- foreach my $section (keys %$cfg) {
- next if $section eq 'global';
- my $d = $cfg->{$section};
- if ($section =~ m/^mon\./) {
- $moncount++;
- if ($d->{'mon addr'}) {
- $monaddrhash->{$d->{'mon addr'}} = $section;
- }
- }
- }
-
- my $monid = $param->{id} // $param->{node};
-
- my $monsection = "mon.$monid";
- my $pubnet = $cfg->{global}->{'public network'};
- my $ip = $find_mon_ip->($pubnet, $param->{node}, $param->{'mon-address'});
-
- my $monaddr = Net::IP::ip_is_ipv6($ip) ? "[$ip]:6789" : "$ip:6789";
- my $monname = $param->{node};
-
- die "monitor '$monsection' already exists\n" if $cfg->{$monsection};
- die "monitor address '$monaddr' already in use by '$monaddrhash->{$monaddr}'\n"
- if $monaddrhash->{$monaddr};
-
- my $worker = sub {
- my $upid = shift;
-
- my $pve_ckeyring_path = PVE::Ceph::Tools::get_config('pve_ckeyring_path');
-
- if (! -f $pve_ckeyring_path) {
- run_command("ceph-authtool $pve_ckeyring_path --create-keyring " .
- "--gen-key -n client.admin");
- }
-
- my $pve_mon_key_path = PVE::Ceph::Tools::get_config('pve_mon_key_path');
- if (! -f $pve_mon_key_path) {
- run_command("cp $pve_ckeyring_path $pve_mon_key_path.tmp");
- run_command("ceph-authtool $pve_mon_key_path.tmp -n client.admin --set-uid=0 " .
- "--cap mds 'allow' " .
- "--cap osd 'allow *' " .
- "--cap mgr 'allow *' " .
- "--cap mon 'allow *'");
- run_command("cp $pve_mon_key_path.tmp /etc/ceph/ceph.client.admin.keyring") if $systemd_managed;
- run_command("chown ceph:ceph /etc/ceph/ceph.client.admin.keyring") if $systemd_managed;
- run_command("ceph-authtool $pve_mon_key_path.tmp --gen-key -n mon. --cap mon 'allow *'");
- run_command("mv $pve_mon_key_path.tmp $pve_mon_key_path");
- }
-
- my $ccname = PVE::Ceph::Tools::get_config('ccname');
-
- my $mondir = "/var/lib/ceph/mon/$ccname-$monid";
- -d $mondir && die "monitor filesystem '$mondir' already exist\n";
-
- my $monmap = "/tmp/monmap";
-
- eval {
- mkdir $mondir;
-
- run_command("chown ceph:ceph $mondir") if $systemd_managed;
-
- if ($moncount > 0) {
- my $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
- my $mapdata = $rados->mon_command({ prefix => 'mon getmap', format => 'plain' });
- file_set_contents($monmap, $mapdata);
- } else {
- run_command("monmaptool --create --clobber --add $monid $monaddr --print $monmap");
- }
-
- run_command("ceph-mon --mkfs -i $monid --monmap $monmap --keyring $pve_mon_key_path");
- run_command("chown ceph:ceph -R $mondir") if $systemd_managed;
- };
- my $err = $@;
- unlink $monmap;
- if ($err) {
- File::Path::remove_tree($mondir);
- die $err;
- }
-
- $cfg->{$monsection} = {
- 'host' => $monname,
- 'mon addr' => $monaddr,
- };
-
- cfs_write_file('ceph.conf', $cfg);
-
- my $create_keys_pid = fork();
- if (!defined($create_keys_pid)) {
- die "Could not spawn ceph-create-keys to create bootstrap keys\n";
- } elsif ($create_keys_pid == 0) {
- exit PVE::Tools::run_command(['ceph-create-keys', '-i', $monid]);
- } else {
- PVE::Ceph::Services::ceph_service_cmd('start', $monsection);
-
- if ($systemd_managed) {
- #to ensure we have the correct startup order.
- eval { PVE::Tools::run_command(['/bin/systemctl', 'enable', "ceph-mon\@${monid}.service"]); };
- warn "Enable ceph-mon\@${monid}.service manually"if $@;
- }
- waitpid($create_keys_pid, 0);
- }
-
- # create manager
- if (!$param->{'exclude-manager'}) {
- my $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
- PVE::Ceph::Services::create_mgr($monid, $rados);
- }
- };
-
- return $rpcenv->fork_worker('cephcreatemon', $monsection, $authuser, $worker);
- }});
-
-__PACKAGE__->register_method ({
- name => 'destroymon',
- path => 'mon/{monid}',
- method => 'DELETE',
- description => "Destroy Ceph Monitor and Manager.",
- proxyto => 'node',
- protected => 1,
- permissions => {
- check => ['perm', '/', [ 'Sys.Modify' ]],
- },
- parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- monid => {
- description => 'Monitor ID',
- type => 'string',
- pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
- },
- 'exclude-manager' => {
- type => 'boolean',
- default => 0,
- optional => 1,
- description => "When set, removes only the monitor, not the manager"
- }
- },
- },
- returns => { type => 'string' },
- code => sub {
- my ($param) = @_;
-
- my $rpcenv = PVE::RPCEnvironment::get();
-
- my $authuser = $rpcenv->get_user();
-
- PVE::Ceph::Tools::check_ceph_inited();
-
- my $cfg = cfs_read_file('ceph.conf');
-
- my $monid = $param->{monid};
- my $monsection = "mon.$monid";
-
- my $rados = PVE::RADOS->new();
- my $monstat = $rados->mon_command({ prefix => 'mon_status' });
- my $monlist = $monstat->{monmap}->{mons};
-
- die "no such monitor id '$monid'\n"
- if !defined($cfg->{$monsection});
-
- my $ccname = PVE::Ceph::Tools::get_config('ccname');
-
- my $mondir = "/var/lib/ceph/mon/$ccname-$monid";
- -d $mondir || die "monitor filesystem '$mondir' does not exist on this node\n";
-
- die "can't remove last monitor\n" if scalar(@$monlist) <= 1;
-
- my $worker = sub {
- my $upid = shift;
-
- # reopen with longer timeout
- $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
-
- $rados->mon_command({ prefix => "mon remove", name => $monid, format => 'plain' });
-
- eval { PVE::Ceph::Services::ceph_service_cmd('stop', $monsection); };
- warn $@ if $@;
-
- delete $cfg->{$monsection};
- cfs_write_file('ceph.conf', $cfg);
- File::Path::remove_tree($mondir);
-
- # remove manager
- if (!$param->{'exclude-manager'}) {
- eval { PVE::Ceph::Services::destroy_mgr($mgrid) };
- warn $@ if $@;
- }
- };
-
- return $rpcenv->fork_worker('cephdestroymon', $monsection, $authuser, $worker);
- }});
-
__PACKAGE__->register_method ({
name => 'stop',
path => 'stop',
diff --git a/PVE/API2/Ceph/MON.pm b/PVE/API2/Ceph/MON.pm
new file mode 100644
index 00000000..ff7db73b
--- /dev/null
+++ b/PVE/API2/Ceph/MON.pm
@@ -0,0 +1,369 @@
+package PVE::API2::Ceph::MON;
+
+use strict;
+use warnings;
+
+use Net::IP;
+use File::Path;
+
+use PVE::Ceph::Tools;
+use PVE::Ceph::Services;
+use PVE::Cluster qw(cfs_read_file cfs_write_file);
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::Network;
+use PVE::RADOS;
+use PVE::RESTHandler;
+use PVE::RPCEnvironment;
+use PVE::Tools qw(run_command file_set_contents);
+
+use base qw(PVE::RESTHandler);
+
+my $find_mon_ip = sub {
+ my ($pubnet, $node, $overwrite_ip) = @_;
+
+ if (!$pubnet) {
+ return $overwrite_ip // PVE::Cluster::remote_node_ip($node);
+ }
+
+ my $allowed_ips = PVE::Network::get_local_ip_from_cidr($pubnet);
+ die "No IP configured and up from ceph public network '$pubnet'\n"
+ if scalar(@$allowed_ips) < 1;
+
+ if (!$overwrite_ip) {
+ if (scalar(@$allowed_ips) == 1) {
+ return $allowed_ips->[0];
+ }
+ die "Multiple IPs for ceph public network '$pubnet' detected on $node:\n".
+ join("\n", @$allowed_ips) ."\nuse 'mon-address' to specify one of them.\n";
+ } else {
+ if (grep { $_ eq $overwrite_ip } @$allowed_ips) {
+ return $overwrite_ip;
+ }
+ die "Monitor IP '$overwrite_ip' not in ceph public network '$pubnet'\n"
+ if !PVE::Network::is_ip_in_cidr($overwrite_ip, $pubnet);
+
+ die "Specified monitor IP '$overwrite_ip' not configured or up on $node!\n";
+ }
+};
+
+__PACKAGE__->register_method ({
+ name => 'listmon',
+ path => '',
+ method => 'GET',
+ description => "Get Ceph monitor list.",
+ proxyto => 'node',
+ protected => 1,
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ name => { type => 'string' },
+ addr => { type => 'string' },
+ },
+ },
+ 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 $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 $rados = PVE::RADOS->new();
+ my $monstat = $rados->mon_command({ prefix => '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 => 'createmon',
+ path => '',
+ method => 'POST',
+ description => "Create Ceph Monitor and Manager",
+ proxyto => 'node',
+ protected => 1,
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Modify' ]],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ id => {
+ type => 'string',
+ optional => 1,
+ pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
+ description => "The ID for the monitor, when omitted the same as the nodename",
+ },
+ 'exclude-manager' => {
+ type => 'boolean',
+ optional => 1,
+ default => 0,
+ description => "When set, only a monitor will be created.",
+ },
+ 'mon-address' => {
+ description => 'Overwrites autodetected monitor IP address. ' .
+ 'Must be in the public network of ceph.',
+ type => 'string', format => 'ip',
+ optional => 1,
+ },
+ },
+ },
+ returns => { type => 'string' },
+ code => sub {
+ my ($param) = @_;
+
+ PVE::Ceph::Tools::check_ceph_installed('ceph_mon');
+
+ PVE::Ceph::Tools::check_ceph_installed('ceph_mgr')
+ if (!$param->{'exclude-manager'});
+
+ PVE::Ceph::Tools::check_ceph_inited();
+
+ PVE::Ceph::Tools::setup_pve_symlinks();
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $authuser = $rpcenv->get_user();
+
+ my $cfg = cfs_read_file('ceph.conf');
+
+ my $moncount = 0;
+
+ my $monaddrhash = {};
+
+ my $systemd_managed = PVE::Ceph::Tools::systemd_managed();
+
+ foreach my $section (keys %$cfg) {
+ next if $section eq 'global';
+ my $d = $cfg->{$section};
+ if ($section =~ m/^mon\./) {
+ $moncount++;
+ if ($d->{'mon addr'}) {
+ $monaddrhash->{$d->{'mon addr'}} = $section;
+ }
+ }
+ }
+
+ my $monid = $param->{id} // $param->{node};
+
+ my $monsection = "mon.$monid";
+ my $pubnet = $cfg->{global}->{'public network'};
+ my $ip = $find_mon_ip->($pubnet, $param->{node}, $param->{'mon-address'});
+
+ my $monaddr = Net::IP::ip_is_ipv6($ip) ? "[$ip]:6789" : "$ip:6789";
+ my $monname = $param->{node};
+
+ die "monitor '$monsection' already exists\n" if $cfg->{$monsection};
+ die "monitor address '$monaddr' already in use by '$monaddrhash->{$monaddr}'\n"
+ if $monaddrhash->{$monaddr};
+
+ my $worker = sub {
+ my $upid = shift;
+
+ my $pve_ckeyring_path = PVE::Ceph::Tools::get_config('pve_ckeyring_path');
+
+ if (! -f $pve_ckeyring_path) {
+ run_command("ceph-authtool $pve_ckeyring_path --create-keyring " .
+ "--gen-key -n client.admin");
+ }
+
+ my $pve_mon_key_path = PVE::Ceph::Tools::get_config('pve_mon_key_path');
+ if (! -f $pve_mon_key_path) {
+ run_command("cp $pve_ckeyring_path $pve_mon_key_path.tmp");
+ run_command("ceph-authtool $pve_mon_key_path.tmp -n client.admin --set-uid=0 " .
+ "--cap mds 'allow' " .
+ "--cap osd 'allow *' " .
+ "--cap mgr 'allow *' " .
+ "--cap mon 'allow *'");
+ run_command("cp $pve_mon_key_path.tmp /etc/ceph/ceph.client.admin.keyring") if $systemd_managed;
+ run_command("chown ceph:ceph /etc/ceph/ceph.client.admin.keyring") if $systemd_managed;
+ run_command("ceph-authtool $pve_mon_key_path.tmp --gen-key -n mon. --cap mon 'allow *'");
+ run_command("mv $pve_mon_key_path.tmp $pve_mon_key_path");
+ }
+
+ my $ccname = PVE::Ceph::Tools::get_config('ccname');
+
+ my $mondir = "/var/lib/ceph/mon/$ccname-$monid";
+ -d $mondir && die "monitor filesystem '$mondir' already exist\n";
+
+ my $monmap = "/tmp/monmap";
+
+ eval {
+ mkdir $mondir;
+
+ run_command("chown ceph:ceph $mondir") if $systemd_managed;
+
+ if ($moncount > 0) {
+ my $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
+ my $mapdata = $rados->mon_command({ prefix => 'mon getmap', format => 'plain' });
+ file_set_contents($monmap, $mapdata);
+ } else {
+ run_command("monmaptool --create --clobber --add $monid $monaddr --print $monmap");
+ }
+
+ run_command("ceph-mon --mkfs -i $monid --monmap $monmap --keyring $pve_mon_key_path");
+ run_command("chown ceph:ceph -R $mondir") if $systemd_managed;
+ };
+ my $err = $@;
+ unlink $monmap;
+ if ($err) {
+ File::Path::remove_tree($mondir);
+ die $err;
+ }
+
+ $cfg->{$monsection} = {
+ 'host' => $monname,
+ 'mon addr' => $monaddr,
+ };
+
+ cfs_write_file('ceph.conf', $cfg);
+
+ my $create_keys_pid = fork();
+ if (!defined($create_keys_pid)) {
+ die "Could not spawn ceph-create-keys to create bootstrap keys\n";
+ } elsif ($create_keys_pid == 0) {
+ exit PVE::Tools::run_command(['ceph-create-keys', '-i', $monid]);
+ } else {
+ PVE::Ceph::Services::ceph_service_cmd('start', $monsection);
+
+ if ($systemd_managed) {
+ #to ensure we have the correct startup order.
+ eval { PVE::Tools::run_command(['/bin/systemctl', 'enable', "ceph-mon\@${monid}.service"]); };
+ warn "Enable ceph-mon\@${monid}.service manually"if $@;
+ }
+ waitpid($create_keys_pid, 0);
+ }
+
+ # create manager
+ if (!$param->{'exclude-manager'}) {
+ my $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
+ PVE::Ceph::Services::create_mgr($monid, $rados);
+ }
+ };
+
+ return $rpcenv->fork_worker('cephcreatemon', $monsection, $authuser, $worker);
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'destroymon',
+ path => '{monid}',
+ method => 'DELETE',
+ description => "Destroy Ceph Monitor and Manager.",
+ proxyto => 'node',
+ protected => 1,
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Modify' ]],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ monid => {
+ description => 'Monitor ID',
+ type => 'string',
+ pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?',
+ },
+ 'exclude-manager' => {
+ type => 'boolean',
+ default => 0,
+ optional => 1,
+ description => "When set, removes only the monitor, not the manager"
+ }
+ },
+ },
+ returns => { type => 'string' },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $authuser = $rpcenv->get_user();
+
+ PVE::Ceph::Tools::check_ceph_inited();
+
+ my $cfg = cfs_read_file('ceph.conf');
+
+ my $monid = $param->{monid};
+ my $monsection = "mon.$monid";
+
+ my $rados = PVE::RADOS->new();
+ my $monstat = $rados->mon_command({ prefix => 'mon_status' });
+ my $monlist = $monstat->{monmap}->{mons};
+
+ die "no such monitor id '$monid'\n"
+ if !defined($cfg->{$monsection});
+
+ my $ccname = PVE::Ceph::Tools::get_config('ccname');
+
+ my $mondir = "/var/lib/ceph/mon/$ccname-$monid";
+ -d $mondir || die "monitor filesystem '$mondir' does not exist on this node\n";
+
+ die "can't remove last monitor\n" if scalar(@$monlist) <= 1;
+
+ my $worker = sub {
+ my $upid = shift;
+
+ # reopen with longer timeout
+ $rados = PVE::RADOS->new(timeout => PVE::Ceph::Tools::get_config('long_rados_timeout'));
+
+ $rados->mon_command({ prefix => "mon remove", name => $monid, format => 'plain' });
+
+ eval { PVE::Ceph::Services::ceph_service_cmd('stop', $monsection); };
+ warn $@ if $@;
+
+ delete $cfg->{$monsection};
+ cfs_write_file('ceph.conf', $cfg);
+ File::Path::remove_tree($mondir);
+
+ # remove manager
+ if (!$param->{'exclude-manager'}) {
+ eval { PVE::Ceph::Services::destroy_mgr($monid) };
+ warn $@ if $@;
+ }
+ };
+
+ return $rpcenv->fork_worker('cephdestroymon', $monsection, $authuser, $worker);
+ }});
+
+1;
diff --git a/PVE/API2/Ceph/Makefile b/PVE/API2/Ceph/Makefile
index 99566cfd..5b6493d5 100644
--- a/PVE/API2/Ceph/Makefile
+++ b/PVE/API2/Ceph/Makefile
@@ -2,6 +2,7 @@ include ../../../defines.mk
PERLSOURCE= \
MGR.pm \
+ MON.pm \
OSD.pm \
FS.pm \
MDS.pm
diff --git a/PVE/CLI/pveceph.pm b/PVE/CLI/pveceph.pm
index 294b1b82..71a5a2f0 100755
--- a/PVE/CLI/pveceph.pm
+++ b/PVE/CLI/pveceph.pm
@@ -22,6 +22,7 @@ use PVE::API2::Ceph;
use PVE::API2::Ceph::FS;
use PVE::API2::Ceph::MDS;
use PVE::API2::Ceph::MGR;
+use PVE::API2::Ceph::MON;
use PVE::API2::Ceph::OSD;
use PVE::CLIHandler;
@@ -188,8 +189,8 @@ our $cmddef = {
createosd => { alias => 'osd create' },
destroyosd => { alias => 'osd destroy' },
mon => {
- create => [ 'PVE::API2::Ceph', 'createmon', [], { node => $nodename }, $upid_exit],
- destroy => [ 'PVE::API2::Ceph', 'destroymon', ['monid'], { node => $nodename }, $upid_exit],
+ create => [ 'PVE::API2::Ceph::MON', 'createmon', [], { node => $nodename }, $upid_exit],
+ destroy => [ 'PVE::API2::Ceph::MON', 'destroymon', ['monid'], { node => $nodename }, $upid_exit],
},
createmon => { alias => 'mon create' },
destroymon => { alias => 'mon destroy' },
--
2.11.0
More information about the pve-devel
mailing list