use PVE::Storage;
use PVE::Tools qw(run_command);
use PVE::JSONSchema qw(get_standard_option);
-use PVE::CephTools;
+use PVE::Ceph::Tools;
+use PVE::Ceph::Services;
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;
exit($status eq 'OK' ? 0 : -1);
};
+sub setup_environment {
+ PVE::RPCEnvironment->setup_default_cli_env();
+}
+
__PACKAGE__->register_method ({
name => 'purge',
path => 'purge',
parameters => {
additionalProperties => 0,
properties => {
+ logs => {
+ description => 'Additionally purge Ceph logs, /var/log/ceph.',
+ type => 'boolean',
+ optional => 1,
+ },
+ crash => {
+ description => 'Additionally purge Ceph crash logs, /var/lib/ceph/crash.',
+ type => 'boolean',
+ optional => 1,
+ },
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
- my $monstat;
+ my $message;
+ my $pools = [];
+ my $monstat = {};
+ my $mdsstat = {};
+ my $osdstat = [];
eval {
my $rados = PVE::RADOS->new();
- my $monstat = $rados->mon_command({ prefix => 'mon_status' });
+ $pools = PVE::Ceph::Tools::ls_pools(undef, $rados);
+ $monstat = PVE::Ceph::Services::get_services_info('mon', undef, $rados);
+ $mdsstat = PVE::Ceph::Services::get_services_info('mds', undef, $rados);
+ $osdstat = $rados->mon_command({ prefix => 'osd metadata' });
};
- my $err = $@;
+ warn "Error gathering ceph info, already purged? Message: $@" if $@;
+
+ my $osd = grep { $_->{hostname} eq $nodename } @$osdstat;
+ my $mds = grep { $mdsstat->{$_}->{host} eq $nodename } keys %$mdsstat;
+ my $mon = grep { $monstat->{$_}->{host} eq $nodename } keys %$monstat;
+
+ # no pools = no data
+ $message .= "- remove pools, this will !!DESTROY DATA!!\n" if @$pools;
+ $message .= "- remove active OSD on $nodename\n" if $osd;
+ $message .= "- remove active MDS on $nodename\n" if $mds;
+ $message .= "- remove other MONs, $nodename is not the last MON\n"
+ if scalar(keys %$monstat) > 1 && $mon;
+
+ # display all steps at once
+ die "Unable to purge Ceph!\n\nTo continue:\n$message" if $message;
- die "detected running ceph services- unable to purge data\n"
- if !$err;
+ my $services = PVE::Ceph::Services::get_local_services();
+ $services->{mon} = $monstat if $mon;
+ $services->{crash}->{$nodename} = { direxists => 1 } if $param->{crash};
+ $services->{logs}->{$nodename} = { direxists => 1 } if $param->{logs};
- # fixme: this is dangerous - should we really support this function?
- PVE::CephTools::purge_all_ceph_files();
+ PVE::Ceph::Tools::purge_all_ceph_services($services);
+ PVE::Ceph::Tools::purge_all_ceph_files($services);
return undef;
}});
properties => {
version => {
type => 'string',
- enum => ['dumpling', 'emperor', 'firefly', 'giant', 'hammer'],
+ # for buster, luminous kept for testing/upgrade purposes only! - FIXME: remove with 6.2?
+ enum => ['luminous', 'nautilus', 'octopus'],
+ default => 'nautilus',
+ description => "Ceph version to install.",
optional => 1,
- }
+ },
+ 'allow-experimental' => {
+ type => 'boolean',
+ default => 0,
+ optional => 1,
+ description => "Allow experimental versions. Use with care!",
+ },
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
- my $cephver = $param->{version} || 'hammer';
-
- local $ENV{DEBIAN_FRONTEND} = 'noninteractive';
-
- my $keyurl = "https://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/release.asc";
-
- print "download and import ceph repository keys\n";
-
- # Note: wget on Debian wheezy cannot handle new ceph.com certificates, so
- # we use LWP::UserAgent
- #system("wget -q -O- '$keyurl'| apt-key add - 2>&1 >/dev/null") == 0 ||
- #die "unable to download ceph release key\n";
-
- my $tmp_key_file = "/tmp/ceph-release-keys.asc";
- my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
- $ua->env_proxy;
- my $response = $ua->get($keyurl);
- if ($response->is_success) {
- my $data = $response->decoded_content;
- PVE::Tools::file_set_contents($tmp_key_file, $data);
- } else {
- die "unable to download ceph release key: " . $response->status_line . "\n";
+ my $default_vers = 'nautilus';
+ my $cephver = $param->{version} || $default_vers;
+
+ my $repolist;
+ if ($cephver eq 'nautilus') {
+ $repolist = "deb http://download.proxmox.com/debian/ceph-nautilus buster main\n";
+ } elsif ($cephver eq 'luminous') {
+ die "Not allowed to select version '$cephver'\n" if !$param->{'allow-experimental'};
+ $repolist = "deb http://download.proxmox.com/debian/ceph-luminous buster main\n";
+ } elsif ($cephver eq 'octopus') {
+ $repolist = "deb http://download.proxmox.com/debian/ceph-octopus buster main\n";
+ } else {
+ die "not implemented ceph version: $cephver";
}
+ PVE::Tools::file_set_contents("/etc/apt/sources.list.d/ceph.list", $repolist);
- system("apt-key add $tmp_key_file 2>&1 >/dev/null") == 0 ||
- die "unable to download ceph release key\n";
-
- unlink $tmp_key_file;
+ warn "WARNING: installing non-default ceph release '$cephver'!\n\n" if $cephver ne $default_vers;
- my $source = "deb http://ceph.com/debian-$cephver wheezy main\n";
+ local $ENV{DEBIAN_FRONTEND} = 'noninteractive';
+ print "update available package list\n";
+ eval { run_command(['apt-get', '-q', 'update'], outfunc => sub {}, errfunc => sub { print STDERR "$_[0]\n" }) };
+
+ my @apt_install = qw(apt-get --no-install-recommends -o Dpkg::Options::=--force-confnew install --);
+ my @ceph_packages = qw(
+ ceph
+ ceph-common
+ ceph-mds
+ ceph-fuse
+ gdisk
+ );
+
+ print "start installation\n";
+ if (system(@apt_install, @ceph_packages) != 0) {
+ die "apt failed during ceph installation ($?)\n";
+ }
- PVE::Tools::file_set_contents("/etc/apt/sources.list.d/ceph.list", $source);
+ print "\ninstalled ceph $cephver successfully\n";
- print "update available package list\n";
- eval { run_command(['apt-get', '-q', 'update'], outfunc => sub {}, errfunc => sub {}); };
+ return undef;
+ }});
- run_command(['apt-get', '-q', '--assume-yes', '--no-install-recommends',
- '-o', 'Dpkg::Options::=--force-confnew',
- 'install', '--',
- 'ceph', 'ceph-common', 'gdisk']);
+__PACKAGE__->register_method ({
+ name => 'status',
+ path => 'status',
+ method => 'GET',
+ description => "Get Ceph Status.",
+ parameters => {
+ additionalProperties => 0,
+ },
+ returns => { type => 'null' },
+ code => sub {
+ PVE::Ceph::Tools::check_ceph_inited();
+ run_command(
+ ['ceph', '-s'],
+ outfunc => sub { print "$_[0]\n" },
+ errfunc => sub { print STDERR "$_[0]\n" }
+ );
return undef;
}});
our $cmddef = {
init => [ 'PVE::API2::Ceph', 'init', [], { node => $nodename } ],
- lspools => [ 'PVE::API2::Ceph', 'lspools', [], { node => $nodename }, sub {
- my $res = shift;
-
- printf("%-20s %10s %10s %20s\n", "Name", "size", "pg_num", "used");
- foreach my $p (sort {$a->{pool_name} cmp $b->{pool_name}} @$res) {
- printf("%-20s %10d %10d %20d\n", $p->{pool_name}, $p->{size}, $p->{pg_num}, $p->{bytes_used});
- }
- }],
- createpool => [ 'PVE::API2::Ceph', 'createpool', ['name'], { node => $nodename }],
- destroypool => [ 'PVE::API2::Ceph', 'destroypool', ['name'], { node => $nodename } ],
- createosd => [ 'PVE::API2::CephOSD', 'createosd', ['dev'], { node => $nodename }, $upid_exit],
- destroyosd => [ 'PVE::API2::CephOSD', 'destroyosd', ['osdid'], { node => $nodename }, $upid_exit],
- createmon => [ 'PVE::API2::Ceph', 'createmon', [], { node => $nodename }, $upid_exit],
- destroymon => [ 'PVE::API2::Ceph', 'destroymon', ['monid'], { node => $nodename }, $upid_exit],
- start => [ 'PVE::API2::Ceph', 'start', ['service'], { node => $nodename }, $upid_exit],
- stop => [ 'PVE::API2::Ceph', 'stop', ['service'], { node => $nodename }, $upid_exit],
+ pool => {
+ ls => [ 'PVE::API2::Ceph', 'lspools', [], { node => $nodename }, sub {
+ my ($data, $schema, $options) = @_;
+ PVE::CLIFormatter::print_api_result($data, $schema,
+ [
+ 'pool_name',
+ 'size',
+ 'min_size',
+ 'pg_num',
+ 'pg_autoscale_mode',
+ 'crush_rule_name',
+ 'percent_used',
+ 'bytes_used',
+ ],
+ $options);
+ }, $PVE::RESTHandler::standard_output_options],
+ create => [ 'PVE::API2::Ceph', 'createpool', ['name'], { node => $nodename }],
+ destroy => [ 'PVE::API2::Ceph', 'destroypool', ['name'], { node => $nodename } ],
+ set => [ 'PVE::API2::Ceph', 'setpool', ['name'], { node => $nodename } ],
+ },
+ lspools => { alias => 'pool ls' },
+ createpool => { alias => 'pool create' },
+ destroypool => { alias => 'pool destroy' },
+ fs => {
+ create => [ 'PVE::API2::Ceph::FS', 'createfs', [], { node => $nodename }],
+ },
+ osd => {
+ create => [ 'PVE::API2::Ceph::OSD', 'createosd', ['dev'], { node => $nodename }, $upid_exit],
+ destroy => [ 'PVE::API2::Ceph::OSD', 'destroyosd', ['osdid'], { node => $nodename }, $upid_exit],
+ },
+ createosd => { alias => 'osd create' },
+ destroyosd => { alias => 'osd destroy' },
+ mon => {
+ 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' },
+ mgr => {
+ create => [ 'PVE::API2::Ceph::MGR', 'createmgr', [], { node => $nodename }, $upid_exit],
+ destroy => [ 'PVE::API2::Ceph::MGR', 'destroymgr', ['id'], { node => $nodename }, $upid_exit],
+ },
+ createmgr => { alias => 'mgr create' },
+ destroymgr => { alias => 'mgr destroy' },
+ mds => {
+ create => [ 'PVE::API2::Ceph::MDS', 'createmds', [], { node => $nodename }, $upid_exit],
+ destroy => [ 'PVE::API2::Ceph::MDS', 'destroymds', ['name'], { node => $nodename }, $upid_exit],
+ },
+ start => [ 'PVE::API2::Ceph', 'start', [], { node => $nodename }, $upid_exit],
+ stop => [ 'PVE::API2::Ceph', 'stop', [], { node => $nodename }, $upid_exit],
install => [ __PACKAGE__, 'install', [] ],
purge => [ __PACKAGE__, 'purge', [] ],
- status => [ 'PVE::API2::Ceph', 'status', [], { node => $nodename }, sub {
- my $res = shift;
- my $json = JSON->new->allow_nonref;
- print $json->pretty->encode($res) . "\n";
- }],
+ status => [ __PACKAGE__, 'status', []],
};
1;
-
-__END__
-
-=head1 NAME
-
-pveceph - tool to manage ceph services on pve nodes
-
-=head1 SYNOPSIS
-
-=include synopsis
-
-=head1 DESCRIPTION
-
-Tool to manage ceph services on pve nodes.
-
-=include pve_copyright