]>
git.proxmox.com Git - pve-manager.git/blob - PVE/CLI/pveceph.pm
1 package PVE
::CLI
::pveceph
;
16 use PVE
::RPCEnvironment
;
18 use PVE
::Tools
qw(run_command);
19 use PVE
::JSONSchema
qw(get_standard_option);
21 use PVE
::Ceph
::Services
;
23 use PVE
::API2
::Ceph
::FS
;
24 use PVE
::API2
::Ceph
::MDS
;
25 use PVE
::API2
::Ceph
::MGR
;
26 use PVE
::API2
::Ceph
::MON
;
27 use PVE
::API2
::Ceph
::OSD
;
31 use base
qw(PVE::CLIHandler);
33 my $nodename = PVE
::INotify
::nodename
();
37 my $status = PVE
::Tools
::upid_read_status
($upid);
38 exit(PVE
::Tools
::upid_status_is_error
($status) ?
-1 : 0);
41 sub setup_environment
{
42 PVE
::RPCEnvironment-
>setup_default_cli_env();
45 __PACKAGE__-
>register_method ({
49 description
=> "Destroy ceph related data and configuration files.",
51 additionalProperties
=> 0,
54 description
=> 'Additionally purge Ceph logs, /var/log/ceph.',
59 description
=> 'Additionally purge Ceph crash logs, /var/lib/ceph/crash.',
65 returns
=> { type
=> 'null' },
76 my $rados = PVE
::RADOS-
>new();
77 $pools = PVE
::Ceph
::Tools
::ls_pools
(undef, $rados);
78 $monstat = PVE
::Ceph
::Services
::get_services_info
('mon', undef, $rados);
79 $mdsstat = PVE
::Ceph
::Services
::get_services_info
('mds', undef, $rados);
80 $osdstat = $rados->mon_command({ prefix
=> 'osd metadata' });
82 warn "Error gathering ceph info, already purged? Message: $@" if $@;
84 my $osd = grep { $_->{hostname
} eq $nodename } @$osdstat;
85 my $mds = grep { $mdsstat->{$_}->{host
} eq $nodename } keys %$mdsstat;
86 my $mon = grep { $monstat->{$_}->{host
} eq $nodename } keys %$monstat;
89 $message .= "- remove pools, this will !!DESTROY DATA!!\n" if @$pools;
90 $message .= "- remove active OSD on $nodename\n" if $osd;
91 $message .= "- remove active MDS on $nodename\n" if $mds;
92 $message .= "- remove other MONs, $nodename is not the last MON\n"
93 if scalar(keys %$monstat) > 1 && $mon;
95 # display all steps at once
96 die "Unable to purge Ceph!\n\nTo continue:\n$message" if $message;
98 my $services = PVE
::Ceph
::Services
::get_local_services
();
99 $services->{mon
} = $monstat if $mon;
100 $services->{crash
}->{$nodename} = { direxists
=> 1 } if $param->{crash
};
101 $services->{logs
}->{$nodename} = { direxists
=> 1 } if $param->{logs
};
103 PVE
::Ceph
::Tools
::purge_all_ceph_services
($services);
104 PVE
::Ceph
::Tools
::purge_all_ceph_files
($services);
109 my $supported_ceph_versions = ['octopus', 'pacific', 'quincy'];
110 my $default_ceph_version = 'pacific';
112 __PACKAGE__-
>register_method ({
116 description
=> "Install ceph related packages.",
118 additionalProperties
=> 0,
122 enum
=> $supported_ceph_versions,
123 default => $default_ceph_version,
124 description
=> "Ceph version to install.",
127 'allow-experimental' => {
131 description
=> "Allow experimental versions. Use with care!",
133 'test-repository' => {
137 description
=> "Use the test, not the main repository. Use with care!",
141 returns
=> { type
=> 'null' },
145 my $cephver = $param->{version
} || $default_ceph_version;
147 my $repo = $param->{'test-repository'} ?
'test' : 'main';
150 if ($cephver eq 'octopus') {
151 warn "Ceph Octopus will go EOL after 2022-07\n";
152 $repolist = "deb http://download.proxmox.com/debian/ceph-octopus bullseye $repo\n";
153 } elsif ($cephver eq 'pacific') {
154 $repolist = "deb http://download.proxmox.com/debian/ceph-pacific bullseye $repo\n";
155 } elsif ($cephver eq 'quincy') {
156 $repolist = "deb http://download.proxmox.com/debian/ceph-quincy bullseye $repo\n";
158 die "unsupported ceph version: $cephver";
160 PVE
::Tools
::file_set_contents
("/etc/apt/sources.list.d/ceph.list", $repolist);
162 my $supported_re = join('|', $supported_ceph_versions->@*);
163 warn "WARNING: installing non-default ceph release '$cephver'!\n" if $cephver !~ qr/^(?:$supported_re)$/;
165 local $ENV{DEBIAN_FRONTEND
} = 'noninteractive';
166 print "update available package list\n";
169 ['apt-get', '-q', 'update'],
171 errfunc
=> sub { print STDERR
"$_[0]\n" },
175 my @apt_install = qw(apt-get --no-install-recommends -o Dpkg::Options::=--force-confnew install --);
176 my @ceph_packages = qw(
185 # got split out with quincy and is required by PVE tooling, conditionally exclude it for older
186 # FIXME: remove condition with PVE 8.0, i.e., once we only support quincy+ new installations
187 if ($cephver ne 'octopus' and $cephver ne 'pacific') {
188 push @ceph_packages, 'ceph-volume';
191 print "start installation\n";
193 # this flag helps to determine when apt is actually done installing (vs. partial extracing)
194 my $install_flag_fn = PVE
::Ceph
::Tools
::ceph_install_flag_file
();
195 open(my $install_flag, '>', $install_flag_fn) or die "could not create install flag - $!\n";
198 if (system(@apt_install, @ceph_packages) != 0) {
199 unlink $install_flag_fn or warn "could not remove Ceph installation flag - $!";
200 die "apt failed during ceph installation ($?)\n";
203 print "\ninstalled ceph $cephver successfully!\n";
204 # done: drop flag file so that the PVE::Ceph::Tools check returns Ok now.
205 unlink $install_flag_fn or warn "could not remove Ceph installation flag - $!";
207 print "\nreloading API to load new Ceph RADOS library...\n";
209 'systemctl', 'try-reload-or-restart', 'pvedaemon.service', 'pveproxy.service'
215 __PACKAGE__-
>register_method ({
219 description
=> "Get Ceph Status.",
221 additionalProperties
=> 0,
223 returns
=> { type
=> 'null' },
225 PVE
::Ceph
::Tools
::check_ceph_inited
();
229 outfunc
=> sub { print "$_[0]\n" },
230 errfunc
=> sub { print STDERR
"$_[0]\n" },
236 my $get_storages = sub {
237 my ($fs, $is_default) = @_;
239 my $cfg = PVE
::Storage
::config
();
241 my $storages = $cfg->{ids
};
243 foreach my $storeid (keys %$storages) {
244 my $curr = $storages->{$storeid};
245 next if $curr->{type
} ne 'cephfs';
246 my $cur_fs = $curr->{'fs-name'};
247 $res->{$storeid} = $storages->{$storeid}
248 if (!defined($cur_fs) && $is_default) || (defined($cur_fs) && $fs eq $cur_fs);
254 __PACKAGE__-
>register_method ({
258 description
=> "Destroy a Ceph filesystem",
260 additionalProperties
=> 0,
262 node
=> get_standard_option
('pve-node'),
264 description
=> "The ceph filesystem name.",
267 'remove-storages' => {
268 description
=> "Remove all pveceph-managed storages configured for this fs.",
274 description
=> "Remove data and metadata pools configured for this fs.",
281 returns
=> { type
=> 'string' },
285 PVE
::Ceph
::Tools
::check_ceph_inited
();
287 my $rpcenv = PVE
::RPCEnvironment
::get
();
288 my $user = $rpcenv->get_user();
290 my $fs_name = $param->{name
};
293 my $fs_list = PVE
::Ceph
::Tools
::ls_fs
();
294 for my $entry (@$fs_list) {
295 next if $entry->{name
} ne $fs_name;
299 die "no such cephfs '$fs_name'\n" if !$fs;
302 my $rados = PVE
::RADOS-
>new();
304 if ($param->{'remove-storages'}) {
306 my $fs_dump = $rados->mon_command({ prefix
=> "fs dump" });
307 for my $fs ($fs_dump->{filesystems
}->@*) {
308 next if $fs->{id
} != $fs_dump->{default_fscid
};
309 $defaultfs = $fs->{mdsmap
}->{fs_name
};
311 warn "no default fs found, maybe not all relevant storages are removed\n"
312 if !defined($defaultfs);
314 my $storages = $get_storages->($fs_name, $fs_name eq ($defaultfs // ''));
315 for my $storeid (keys %$storages) {
316 my $store = $storages->{$storeid};
317 if (!$store->{disable
}) {
318 die "storage '$storeid' is not disabled, make sure to disable ".
319 "and unmount the storage first\n";
324 for my $storeid (keys %$storages) {
325 # skip external clusters, not managed by pveceph
326 next if $storages->{$storeid}->{monhost
};
327 eval { PVE
::API2
::Storage
::Config-
>delete({storage
=> $storeid}) };
329 warn "failed to remove storage '$storeid': $@\n";
333 die "failed to remove (some) storages - check log and remove manually!\n"
337 PVE
::Ceph
::Tools
::destroy_fs
($fs_name, $rados);
339 if ($param->{'remove-pools'}) {
340 warn "removing metadata pool '$fs->{metadata_pool}'\n";
341 eval { PVE
::Ceph
::Tools
::destroy_pool
($fs->{metadata_pool
}, $rados) };
344 foreach my $pool ($fs->{data_pools
}->@*) {
345 warn "removing data pool '$pool'\n";
346 eval { PVE
::Ceph
::Tools
::destroy_pool
($pool, $rados) };
352 return $rpcenv->fork_worker('cephdestroyfs', $fs_name, $user, $worker);
356 init
=> [ 'PVE::API2::Ceph', 'init', [], { node
=> $nodename } ],
358 ls
=> [ 'PVE::API2::Ceph::Pool', 'lspools', [], { node
=> $nodename }, sub {
359 my ($data, $schema, $options) = @_;
360 PVE
::CLIFormatter
::print_api_result
($data, $schema,
376 }, $PVE::RESTHandler
::standard_output_options
],
377 create
=> [ 'PVE::API2::Ceph::Pool', 'createpool', ['name'], { node
=> $nodename }],
378 destroy
=> [ 'PVE::API2::Ceph::Pool', 'destroypool', ['name'], { node
=> $nodename } ],
379 set
=> [ 'PVE::API2::Ceph::Pool', 'setpool', ['name'], { node
=> $nodename } ],
380 get
=> [ 'PVE::API2::Ceph::Pool', 'getpool', ['name'], { node
=> $nodename }, sub {
381 my ($data, $schema, $options) = @_;
382 PVE
::CLIFormatter
::print_api_result
($data, $schema, undef, $options);
383 }, $PVE::RESTHandler
::standard_output_options
],
385 lspools
=> { alias
=> 'pool ls' },
386 createpool
=> { alias
=> 'pool create' },
387 destroypool
=> { alias
=> 'pool destroy' },
389 create
=> [ 'PVE::API2::Ceph::FS', 'createfs', [], { node
=> $nodename }],
390 destroy
=> [ __PACKAGE__
, 'destroyfs', ['name'], { node
=> $nodename }],
393 create
=> [ 'PVE::API2::Ceph::OSD', 'createosd', ['dev'], { node
=> $nodename }, $upid_exit],
394 destroy
=> [ 'PVE::API2::Ceph::OSD', 'destroyosd', ['osdid'], { node
=> $nodename }, $upid_exit],
396 createosd
=> { alias
=> 'osd create' },
397 destroyosd
=> { alias
=> 'osd destroy' },
399 create
=> [ 'PVE::API2::Ceph::MON', 'createmon', [], { node
=> $nodename }, $upid_exit],
400 destroy
=> [ 'PVE::API2::Ceph::MON', 'destroymon', ['monid'], { node
=> $nodename }, $upid_exit],
402 createmon
=> { alias
=> 'mon create' },
403 destroymon
=> { alias
=> 'mon destroy' },
405 create
=> [ 'PVE::API2::Ceph::MGR', 'createmgr', [], { node
=> $nodename }, $upid_exit],
406 destroy
=> [ 'PVE::API2::Ceph::MGR', 'destroymgr', ['id'], { node
=> $nodename }, $upid_exit],
408 createmgr
=> { alias
=> 'mgr create' },
409 destroymgr
=> { alias
=> 'mgr destroy' },
411 create
=> [ 'PVE::API2::Ceph::MDS', 'createmds', [], { node
=> $nodename }, $upid_exit],
412 destroy
=> [ 'PVE::API2::Ceph::MDS', 'destroymds', ['name'], { node
=> $nodename }, $upid_exit],
414 start
=> [ 'PVE::API2::Ceph', 'start', [], { node
=> $nodename }, $upid_exit],
415 stop
=> [ 'PVE::API2::Ceph', 'stop', [], { node
=> $nodename }, $upid_exit],
416 install
=> [ __PACKAGE__
, 'install', [] ],
417 purge
=> [ __PACKAGE__
, 'purge', [] ],
418 status
=> [ __PACKAGE__
, 'status', []],