to clean service directories as well as disable and stop Ceph services. Addtionally provide the option to remove crash and log information.
This patch is also in addtion to #2607, as the current cleanup doesn't allow to re-configure Ceph, without manual steps during purge. Signed-off-by: Alwin Antreich <a.antre...@proxmox.com> --- v1 -> v2: * incorporate Thomas suggestions. Thanks. - add warning for failed ceph connection - use grep instead of map - change $ceph variable name to $service in purge methods PVE/CLI/pveceph.pm | 48 ++++++++++++++++++++++++++----- PVE/Ceph/Tools.pm | 71 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/PVE/CLI/pveceph.pm b/PVE/CLI/pveceph.pm index 064ae545..448d3ec1 100755 --- a/PVE/CLI/pveceph.pm +++ b/PVE/CLI/pveceph.pm @@ -18,6 +18,7 @@ use PVE::Storage; use PVE::Tools qw(run_command); use PVE::JSONSchema qw(get_standard_option); use PVE::Ceph::Tools; +use PVE::Ceph::Services; use PVE::API2::Ceph; use PVE::API2::Ceph::FS; use PVE::API2::Ceph::MDS; @@ -49,25 +50,58 @@ __PACKAGE__->register_method ({ 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 "Could not connect: $@" 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::Ceph::Tools::purge_all_ceph_files(); + PVE::Ceph::Tools::purge_all_ceph_services($services); + PVE::Ceph::Tools::purge_all_ceph_files($services); return undef; }}); diff --git a/PVE/Ceph/Tools.pm b/PVE/Ceph/Tools.pm index e6225b78..acec746a 100644 --- a/PVE/Ceph/Tools.pm +++ b/PVE/Ceph/Tools.pm @@ -11,6 +11,8 @@ use JSON; use PVE::Tools qw(run_command dir_glob_foreach); use PVE::Cluster qw(cfs_read_file); use PVE::RADOS; +use PVE::Ceph::Services; +use PVE::CephConfig; my $ccname = 'ceph'; # ceph cluster name my $ceph_cfgdir = "/etc/ceph"; @@ -42,6 +44,7 @@ my $config_hash = { ceph_bootstrap_mds_keyring => $ceph_bootstrap_mds_keyring, ceph_mds_data_dir => $ceph_mds_data_dir, long_rados_timeout => 60, + ceph_cfgpath => $ceph_cfgpath, }; sub get_local_version { @@ -89,20 +92,64 @@ sub get_config { } sub purge_all_ceph_files { - # fixme: this is very dangerous - should we really support this function? - - unlink $ceph_cfgpath; - - unlink $pve_ceph_cfgpath; - unlink $pve_ckeyring_path; - unlink $pve_mon_key_path; - - unlink $ceph_bootstrap_osd_keyring; - unlink $ceph_bootstrap_mds_keyring; + my ($services) = @_; + my $is_local_mon; + my $monlist = [ split(',', PVE::CephConfig::get_monaddr_list($pve_ceph_cfgpath)) ]; + + foreach my $service (keys %$services) { + my $type = $services->{$service}; + next if (!%$type); + + foreach my $name (keys %$type) { + my $dir_exists = $type->{$name}->{direxists}; + + $is_local_mon = grep($type->{$name}->{addr}, @$monlist) + if $service eq 'mon'; + + my $path = "/var/lib/ceph/$service"; + $path = '/var/log/ceph' if $service eq 'logs'; + if ($dir_exists) { + my $err; + File::Path::remove_tree($path, { + keep_root => 1, + error => \$err, + }); + warn "Error removing path, '$path'\n" if @$err; + } + } + } - system("rm -rf /var/lib/ceph/mon/ceph-*"); + if (scalar @$monlist > 0 && !$is_local_mon) { + warn "Foreign MON address in ceph.conf. Keeping config & keyrings\n" + } else { + print "Removing config & keyring files\n"; + foreach my $file (%$config_hash) { + unlink $file if (-e $file); + } + } +} - # remove osd? +sub purge_all_ceph_services { + my ($services) = @_; + + foreach my $service (keys %$services) { + my $type = $services->{$service}; + next if (!%$type); + + foreach my $name (keys %$type) { + my $service_exists = $type->{$name}->{service}; + + if ($service_exists) { + eval { + PVE::Ceph::Services::ceph_service_cmd('disable', "$service.$name"); + PVE::Ceph::Services::ceph_service_cmd('stop', "$service.$name"); + }; + my $err = $@ if $@; + warn "Could not disable/stop ceph-$service\@$name, error: $err\n" + if $err; + } + } + } } sub check_ceph_installed { -- 2.26.2 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel