mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-05-01 14:09:36 +00:00

include the version as string and as parts, as we do the split already. Also include the build commit, so if we re-release a ceph version, we can differ here too. Use node as key, to make the new entry a bit more general, could be easily expanded with other infos, if required. Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
343 lines
7.6 KiB
Perl
343 lines
7.6 KiB
Perl
package PVE::API2::Cluster::Ceph;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use JSON;
|
|
|
|
use PVE::Ceph::Services;
|
|
use PVE::Ceph::Tools;
|
|
use PVE::Cluster;
|
|
use PVE::Exception qw(raise_param_exc);
|
|
use PVE::JSONSchema qw(get_standard_option);
|
|
use PVE::RADOS;
|
|
use PVE::RESTHandler;
|
|
use PVE::SafeSyslog;
|
|
use PVE::Tools qw(extract_param);
|
|
|
|
use base qw(PVE::RESTHandler);
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'cephindex',
|
|
path => '',
|
|
method => 'GET',
|
|
description => "Cluster ceph index.",
|
|
permissions => { user => 'all' },
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {},
|
|
},
|
|
returns => {
|
|
type => 'array',
|
|
items => {
|
|
type => "object",
|
|
properties => {},
|
|
},
|
|
links => [ { rel => 'child', href => "{name}" } ],
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
my $result = [
|
|
{ name => 'metadata' },
|
|
{ name => 'status' },
|
|
{ name => 'flags' },
|
|
];
|
|
|
|
return $result;
|
|
}
|
|
});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'metadata',
|
|
path => 'metadata',
|
|
method => 'GET',
|
|
description => "Get ceph metadata.",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {},
|
|
},
|
|
returns => { type => 'object' },
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
PVE::Ceph::Tools::check_ceph_inited();
|
|
|
|
my $rados = PVE::RADOS->new();
|
|
|
|
my $res = {
|
|
# FIXME: remove with 7.0 depreacated by structured 'versions'
|
|
version => PVE::Cluster::get_node_kv("ceph-version"),
|
|
};
|
|
|
|
if (defined(my $vers = PVE::Cluster::get_node_kv("ceph-versions"))) {
|
|
$res->{node} = {
|
|
map { eval { $_ => decode_json($vers->{$_}) } } keys %$vers
|
|
};
|
|
}
|
|
|
|
for my $type ( qw(mon mgr mds) ) {
|
|
my $typedata = PVE::Ceph::Services::get_cluster_service($type);
|
|
my $data = {};
|
|
for my $host (sort keys %$typedata) {
|
|
for my $service (sort keys %{$typedata->{$host}}) {
|
|
$data->{"$service\@$host"} = $typedata->{$host}->{$service};
|
|
}
|
|
}
|
|
|
|
# get data from metadata call and merge 'our' data
|
|
my $services = $rados->mon_command({ prefix => "$type metadata" });
|
|
for my $service ( @$services ) {
|
|
my $hostname = $service->{hostname};
|
|
my $servicename = $service->{name} // $service->{id};
|
|
my $id = "$servicename\@$hostname";
|
|
|
|
if ($data->{$id}) {
|
|
# copy values over to the metadata hash
|
|
for my $k (keys %{$data->{$id}}) {
|
|
$service->{$k} = $data->{$id}->{$k};
|
|
}
|
|
}
|
|
$data->{$id} = $service;
|
|
}
|
|
|
|
$res->{$type} = $data;
|
|
}
|
|
|
|
$res->{osd} = $rados->mon_command({ prefix => "osd metadata" });
|
|
|
|
return $res;
|
|
}
|
|
});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'status',
|
|
path => 'status',
|
|
method => 'GET',
|
|
description => "Get ceph status.",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => { },
|
|
},
|
|
returns => { type => 'object' },
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
PVE::Ceph::Tools::check_ceph_inited();
|
|
|
|
my $rados = PVE::RADOS->new();
|
|
my $status = $rados->mon_command({ prefix => 'status' });
|
|
$status->{health} = $rados->mon_command({ prefix => 'health', detail => 'detail' });
|
|
return $status;
|
|
}
|
|
});
|
|
|
|
my $possible_flags = PVE::Ceph::Tools::get_possible_osd_flags();
|
|
my $possible_flags_list = [ sort keys %$possible_flags ];
|
|
|
|
my $get_current_set_flags = sub {
|
|
my $rados = shift;
|
|
|
|
$rados //= PVE::RADOS->new();
|
|
|
|
my $stat = $rados->mon_command({ prefix => 'osd dump' });
|
|
my $setflags = $stat->{flags} // '';
|
|
return { map { $_ => 1 } PVE::Tools::split_list($setflags) };
|
|
};
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'get_all_flags',
|
|
path => 'flags',
|
|
method => 'GET',
|
|
description => "get the status of all ceph flags",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Audit' ]],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
},
|
|
},
|
|
returns => {
|
|
type => 'array',
|
|
items => {
|
|
type => "object",
|
|
additionalProperties => 1,
|
|
properties => {
|
|
name => {
|
|
description => "Flag name.",
|
|
type => 'string', enum => $possible_flags_list,
|
|
},
|
|
},
|
|
},
|
|
links => [ { rel => 'child', href => "{name}" } ],
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
PVE::Ceph::Tools::check_ceph_configured();
|
|
|
|
my $setflags = $get_current_set_flags->();
|
|
|
|
my $res = [];
|
|
foreach my $flag (@$possible_flags_list) {
|
|
my $el = {
|
|
name => $flag,
|
|
description => $possible_flags->{$flag}->{description},
|
|
value => 0,
|
|
};
|
|
|
|
my $realflag = PVE::Ceph::Tools::get_real_flag_name($flag);
|
|
if ($setflags->{$realflag}) {
|
|
$el->{value} = 1;
|
|
}
|
|
|
|
push @$res, $el;
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'set_flags',
|
|
path => 'flags',
|
|
method => 'PUT',
|
|
description => "Set/Unset multiple ceph flags at once.",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Modify' ]],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => $possible_flags,
|
|
},
|
|
returns => { type => 'string' },
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
my $rpcenv = PVE::RPCEnvironment::get();
|
|
my $user = $rpcenv->get_user();
|
|
PVE::Ceph::Tools::check_ceph_configured();
|
|
|
|
my $worker = sub {
|
|
my $rados = PVE::RADOS->new(); # (re-)open for forked worker
|
|
|
|
my $setflags = $get_current_set_flags->($rados);
|
|
|
|
my $errors = 0;
|
|
foreach my $flag (@$possible_flags_list) {
|
|
next if !defined($param->{$flag});
|
|
my $val = $param->{$flag};
|
|
my $realflag = PVE::Ceph::Tools::get_real_flag_name($flag);
|
|
|
|
next if !$val == !$setflags->{$realflag}; # we do not set/unset flags to the same state
|
|
|
|
my $prefix = $val ? 'set' : 'unset';
|
|
eval {
|
|
print "$prefix $flag\n";
|
|
$rados->mon_command({ prefix => "osd $prefix", key => $flag, });
|
|
};
|
|
if (my $err = $@) {
|
|
warn "error with $flag: '$err'\n";
|
|
$errors++;
|
|
}
|
|
}
|
|
|
|
if ($errors) {
|
|
die "could not set/unset $errors flags\n";
|
|
}
|
|
};
|
|
|
|
return $rpcenv->fork_worker('cephsetflags', undef, $user, $worker);
|
|
}});
|
|
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'get_flag',
|
|
path => 'flags/{flag}',
|
|
method => 'GET',
|
|
description => "Get the status of a specific ceph flag.",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Audit' ]],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
flag => {
|
|
description => "The name of the flag name to get.",
|
|
type => 'string', enum => $possible_flags_list,
|
|
},
|
|
},
|
|
},
|
|
returns => {
|
|
type => 'boolean',
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
PVE::Ceph::Tools::check_ceph_configured();
|
|
|
|
my $realflag = PVE::Ceph::Tools::get_real_flag_name($param->{flag});
|
|
|
|
my $setflags = $get_current_set_flags->();
|
|
if ($setflags->{$realflag}) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'update_flag',
|
|
path => 'flags/{flag}',
|
|
method => 'PUT',
|
|
description => "Set or clear (unset) a specific ceph flag",
|
|
protected => 1,
|
|
permissions => {
|
|
check => ['perm', '/', [ 'Sys.Modify' ]],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
flag => {
|
|
description => 'The ceph flag to update',
|
|
type => 'string',
|
|
enum => $possible_flags_list,
|
|
},
|
|
value => {
|
|
description => 'The new value of the flag',
|
|
type => 'boolean',
|
|
},
|
|
},
|
|
},
|
|
returns => { type => 'null' },
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
PVE::Ceph::Tools::check_ceph_configured();
|
|
|
|
my $cmd = $param->{value} ? 'set' : 'unset';
|
|
|
|
my $rados = PVE::RADOS->new();
|
|
$rados->mon_command({
|
|
prefix => "osd $cmd",
|
|
key => $param->{flag},
|
|
});
|
|
|
|
return undef;
|
|
}});
|
|
|
|
|
|
1;
|