]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Ceph.pm
api: ceph: sort and update index sub-directory list
[pve-manager.git] / PVE / API2 / Ceph.pm
CommitLineData
7d4fc5ef
DM
1package PVE::API2::Ceph;
2
3use strict;
4use warnings;
0cd34b00 5
7d4fc5ef 6use File::Path;
7d4fc5ef 7use Net::IP;
0cd34b00 8use UUID;
7d4fc5ef 9
6fb08cb9 10use PVE::Ceph::Tools;
27439be6 11use PVE::Ceph::Services;
c31f487e 12use PVE::Cluster qw(cfs_read_file cfs_write_file);
0cd34b00 13use PVE::JSONSchema qw(get_standard_option);
9f4ff798 14use PVE::Network;
0cd34b00
TL
15use PVE::RADOS;
16use PVE::RESTHandler;
17use PVE::RPCEnvironment;
18use PVE::Storage;
063b6d5e 19use PVE::Tools qw(run_command file_get_contents file_set_contents extract_param);
7d4fc5ef 20
79fa41a2 21use PVE::API2::Ceph::OSD;
7e1a9d25 22use PVE::API2::Ceph::FS;
b82649cc 23use PVE::API2::Ceph::MDS;
4fec2764 24use PVE::API2::Ceph::MGR;
98fe93ae 25use PVE::API2::Ceph::MON;
56d02a86 26use PVE::API2::Ceph::Pools;
0cd34b00 27use PVE::API2::Storage::Config;
7d4fc5ef 28
0cd34b00 29use base qw(PVE::RESTHandler);
7d4fc5ef
DM
30
31my $pve_osd_default_journal_size = 1024*5;
32
33__PACKAGE__->register_method ({
79fa41a2 34 subclass => "PVE::API2::Ceph::OSD",
7d4fc5ef
DM
35 path => 'osd',
36});
37
b82649cc
TL
38__PACKAGE__->register_method ({
39 subclass => "PVE::API2::Ceph::MDS",
40 path => 'mds',
41});
42
4fec2764
DC
43__PACKAGE__->register_method ({
44 subclass => "PVE::API2::Ceph::MGR",
45 path => 'mgr',
46});
47
98fe93ae
DC
48__PACKAGE__->register_method ({
49 subclass => "PVE::API2::Ceph::MON",
50 path => 'mon',
51});
52
7e1a9d25
TL
53__PACKAGE__->register_method ({
54 subclass => "PVE::API2::Ceph::FS",
55 path => 'fs',
56});
57
56d02a86
AA
58__PACKAGE__->register_method ({
59 subclass => "PVE::API2::Ceph::Pools",
60 path => 'pools',
61});
62
7d4fc5ef
DM
63__PACKAGE__->register_method ({
64 name => 'index',
65 path => '',
66 method => 'GET',
67 description => "Directory index.",
68 permissions => { user => 'all' },
90c75580
TL
69 permissions => {
70 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
71 },
7d4fc5ef 72 parameters => {
be753927 73 additionalProperties => 0,
7d4fc5ef
DM
74 properties => {
75 node => get_standard_option('pve-node'),
76 },
77 },
78 returns => {
79 type => 'array',
80 items => {
81 type => "object",
82 properties => {},
83 },
84 links => [ { rel => 'child', href => "{name}" } ],
85 },
86 code => sub {
87 my ($param) = @_;
88
89 my $result = [
56b03211
AL
90 { name => 'cmd-safety' },
91 { name => 'config' },
92 { name => 'configdb' },
93 { name => 'crush' },
94 { name => 'fs' },
7d4fc5ef 95 { name => 'init' },
56b03211
AL
96 { name => 'log' },
97 { name => 'mds' },
98 { name => 'mgr' },
7d4fc5ef
DM
99 { name => 'mon' },
100 { name => 'osd' },
101 { name => 'pools' },
2d7d6c9a 102 { name => 'restart' },
d2692b86 103 { name => 'rules' },
56b03211
AL
104 { name => 'start' },
105 { name => 'status' },
106 { name => 'stop' },
7d4fc5ef
DM
107 ];
108
109 return $result;
110 }});
111
7d4fc5ef
DM
112__PACKAGE__->register_method ({
113 name => 'config',
114 path => 'config',
115 method => 'GET',
410f2cb0 116 proxyto => 'node',
90c75580
TL
117 permissions => {
118 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
119 },
f18b7ddd 120 description => "Get the Ceph configuration file.",
7d4fc5ef 121 parameters => {
be753927 122 additionalProperties => 0,
7d4fc5ef
DM
123 properties => {
124 node => get_standard_option('pve-node'),
125 },
126 },
127 returns => { type => 'string' },
128 code => sub {
129 my ($param) = @_;
130
6fb08cb9 131 PVE::Ceph::Tools::check_ceph_inited();
7d4fc5ef 132
6fb08cb9 133 my $path = PVE::Ceph::Tools::get_config('pve_ceph_cfgpath');
400742e4 134 return file_get_contents($path);
7d4fc5ef
DM
135
136 }});
137
21e413dc
DC
138__PACKAGE__->register_method ({
139 name => 'configdb',
140 path => 'configdb',
141 method => 'GET',
142 proxyto => 'node',
143 protected => 1,
144 permissions => {
145 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
146 },
f18b7ddd 147 description => "Get the Ceph configuration database.",
21e413dc
DC
148 parameters => {
149 additionalProperties => 0,
150 properties => {
151 node => get_standard_option('pve-node'),
152 },
153 },
154 returns => {
155 type => 'array',
156 items => {
157 type => 'object',
158 properties => {
159 section => { type => "string", },
160 name => { type => "string", },
161 value => { type => "string", },
162 level => { type => "string", },
163 'can_update_at_runtime' => { type => "boolean", },
164 mask => { type => "string" },
165 },
166 },
167 },
168 code => sub {
169 my ($param) = @_;
170
171 PVE::Ceph::Tools::check_ceph_inited();
172
173 my $rados = PVE::RADOS->new();
174 my $res = $rados->mon_command( { prefix => 'config dump', format => 'json' });
175 foreach my $entry (@$res) {
176 $entry->{can_update_at_runtime} = $entry->{can_update_at_runtime}? 1 : 0; # JSON::true/false -> 1/0
177 }
178
179 return $res;
180 }});
181
f4aae93b 182
7d4fc5ef
DM
183__PACKAGE__->register_method ({
184 name => 'init',
185 path => 'init',
186 method => 'POST',
187 description => "Create initial ceph default configuration and setup symlinks.",
188 proxyto => 'node',
189 protected => 1,
90c75580
TL
190 permissions => {
191 check => ['perm', '/', [ 'Sys.Modify' ]],
192 },
7d4fc5ef 193 parameters => {
be753927 194 additionalProperties => 0,
7d4fc5ef
DM
195 properties => {
196 node => get_standard_option('pve-node'),
197 network => {
be753927 198 description => "Use specific network for all ceph related traffic",
7d4fc5ef
DM
199 type => 'string', format => 'CIDR',
200 optional => 1,
201 maxLength => 128,
202 },
7519b848
TL
203 'cluster-network' => {
204 description => "Declare a separate cluster network, OSDs will route" .
205 "heartbeat, object replication and recovery traffic over it",
206 type => 'string', format => 'CIDR',
207 requires => 'network',
208 optional => 1,
209 maxLength => 128,
210 },
7d4fc5ef 211 size => {
207f4932
FG
212 description => 'Targeted number of replicas per object',
213 type => 'integer',
214 default => 3,
215 optional => 1,
216 minimum => 1,
217 maximum => 7,
218 },
219 min_size => {
220 description => 'Minimum number of available replicas per object to allow I/O',
7d4fc5ef
DM
221 type => 'integer',
222 default => 2,
223 optional => 1,
224 minimum => 1,
83663637 225 maximum => 7,
7d4fc5ef
DM
226 },
227 pg_bits => {
3cba09d5
FG
228 description => "Placement group bits, used to specify the " .
229 "default number of placement groups.\n\nNOTE: 'osd pool " .
230 "default pg num' does not work for default pools.",
7d4fc5ef
DM
231 type => 'integer',
232 default => 6,
233 optional => 1,
234 minimum => 6,
235 maximum => 14,
236 },
4280f25c 237 disable_cephx => {
76189130 238 description => "Disable cephx authentication.\n\n" .
97f050bb
FG
239 "WARNING: cephx is a security feature protecting against " .
240 "man-in-the-middle attacks. Only consider disabling cephx ".
241 "if your network is private!",
77bb90b0
AD
242 type => 'boolean',
243 optional => 1,
244 default => 0,
4280f25c 245 },
7d4fc5ef
DM
246 },
247 },
248 returns => { type => 'null' },
249 code => sub {
250 my ($param) = @_;
251
6fb08cb9 252 my $version = PVE::Ceph::Tools::get_local_version(1);
c64c04dd 253
b3d8b5f5
DC
254 if (!$version || $version < 14) {
255 die "Ceph Nautilus required - please run 'pveceph install'\n";
c64c04dd 256 } else {
6fb08cb9 257 PVE::Ceph::Tools::check_ceph_installed('ceph_bin');
c64c04dd 258 }
7d4fc5ef 259
50d5fd6a
FG
260 my $auth = $param->{disable_cephx} ? 'none' : 'cephx';
261
7d4fc5ef 262 # simply load old config if it already exists
3e4c0f06
DC
263 PVE::Cluster::cfs_lock_file('ceph.conf', undef, sub {
264 my $cfg = cfs_read_file('ceph.conf');
7d4fc5ef 265
3e4c0f06 266 if (!$cfg->{global}) {
7d4fc5ef 267
3e4c0f06
DC
268 my $fsid;
269 my $uuid;
7d4fc5ef 270
3e4c0f06
DC
271 UUID::generate($uuid);
272 UUID::unparse($uuid, $fsid);
7d4fc5ef 273
3e4c0f06
DC
274 $cfg->{global} = {
275 'fsid' => $fsid,
276 'auth cluster required' => $auth,
277 'auth service required' => $auth,
278 'auth client required' => $auth,
279 'osd pool default size' => $param->{size} // 3,
280 'osd pool default min size' => $param->{min_size} // 2,
281 'mon allow pool delete' => 'true',
282 };
7d4fc5ef 283
3e4c0f06
DC
284 # this does not work for default pools
285 #'osd pool default pg num' => $pg_num,
286 #'osd pool default pgp num' => $pg_num,
287 }
be753927 288
d851d63e
DC
289 if ($auth eq 'cephx') {
290 $cfg->{client}->{keyring} = '/etc/pve/priv/$cluster.$name.keyring';
291 }
7d4fc5ef 292
3e4c0f06
DC
293 if ($param->{pg_bits}) {
294 $cfg->{global}->{'osd pg bits'} = $param->{pg_bits};
295 $cfg->{global}->{'osd pgp bits'} = $param->{pg_bits};
296 }
7d4fc5ef 297
3e4c0f06
DC
298 if ($param->{network}) {
299 $cfg->{global}->{'public network'} = $param->{network};
300 $cfg->{global}->{'cluster network'} = $param->{network};
301 }
7d4fc5ef 302
3e4c0f06
DC
303 if ($param->{'cluster-network'}) {
304 $cfg->{global}->{'cluster network'} = $param->{'cluster-network'};
305 }
7519b848 306
3e4c0f06 307 cfs_write_file('ceph.conf', $cfg);
7d4fc5ef 308
d851d63e
DC
309 if ($auth eq 'cephx') {
310 PVE::Ceph::Tools::get_or_create_admin_keyring();
311 }
3e4c0f06
DC
312 PVE::Ceph::Tools::setup_pve_symlinks();
313 });
8e2b5110 314 die $@ if $@;
7d4fc5ef
DM
315
316 return undef;
317 }});
318
38db610a
DM
319__PACKAGE__->register_method ({
320 name => 'stop',
321 path => 'stop',
322 method => 'POST',
323 description => "Stop ceph services.",
324 proxyto => 'node',
325 protected => 1,
90c75580
TL
326 permissions => {
327 check => ['perm', '/', [ 'Sys.Modify' ]],
328 },
38db610a 329 parameters => {
be753927 330 additionalProperties => 0,
38db610a
DM
331 properties => {
332 node => get_standard_option('pve-node'),
68e0c4bd
DM
333 service => {
334 description => 'Ceph service name.',
335 type => 'string',
336 optional => 1,
33a9c70a 337 default => 'ceph.target',
7e98f79e 338 pattern => '(ceph|mon|mds|osd|mgr)(\.'.PVE::Ceph::Services::SERVICE_REGEX.')?',
68e0c4bd 339 },
38db610a
DM
340 },
341 },
68e0c4bd 342 returns => { type => 'string' },
38db610a
DM
343 code => sub {
344 my ($param) = @_;
345
68e0c4bd
DM
346 my $rpcenv = PVE::RPCEnvironment::get();
347
348 my $authuser = $rpcenv->get_user();
349
6fb08cb9 350 PVE::Ceph::Tools::check_ceph_inited();
38db610a 351
c31f487e 352 my $cfg = cfs_read_file('ceph.conf');
38db610a
DM
353 scalar(keys %$cfg) || die "no configuration\n";
354
68e0c4bd
DM
355 my $worker = sub {
356 my $upid = shift;
38db610a 357
68e0c4bd
DM
358 my $cmd = ['stop'];
359 if ($param->{service}) {
360 push @$cmd, $param->{service};
361 }
362
27439be6 363 PVE::Ceph::Services::ceph_service_cmd(@$cmd);
68e0c4bd
DM
364 };
365
366 return $rpcenv->fork_worker('srvstop', $param->{service} || 'ceph',
367 $authuser, $worker);
38db610a
DM
368 }});
369
370__PACKAGE__->register_method ({
371 name => 'start',
372 path => 'start',
373 method => 'POST',
374 description => "Start ceph services.",
375 proxyto => 'node',
376 protected => 1,
90c75580
TL
377 permissions => {
378 check => ['perm', '/', [ 'Sys.Modify' ]],
379 },
38db610a 380 parameters => {
be753927 381 additionalProperties => 0,
38db610a
DM
382 properties => {
383 node => get_standard_option('pve-node'),
68e0c4bd
DM
384 service => {
385 description => 'Ceph service name.',
386 type => 'string',
387 optional => 1,
33a9c70a 388 default => 'ceph.target',
7e98f79e 389 pattern => '(ceph|mon|mds|osd|mgr)(\.'.PVE::Ceph::Services::SERVICE_REGEX.')?',
68e0c4bd 390 },
38db610a
DM
391 },
392 },
68e0c4bd 393 returns => { type => 'string' },
38db610a
DM
394 code => sub {
395 my ($param) = @_;
396
68e0c4bd
DM
397 my $rpcenv = PVE::RPCEnvironment::get();
398
399 my $authuser = $rpcenv->get_user();
400
6fb08cb9 401 PVE::Ceph::Tools::check_ceph_inited();
38db610a 402
c31f487e 403 my $cfg = cfs_read_file('ceph.conf');
38db610a
DM
404 scalar(keys %$cfg) || die "no configuration\n";
405
68e0c4bd
DM
406 my $worker = sub {
407 my $upid = shift;
38db610a 408
68e0c4bd
DM
409 my $cmd = ['start'];
410 if ($param->{service}) {
411 push @$cmd, $param->{service};
412 }
413
27439be6 414 PVE::Ceph::Services::ceph_service_cmd(@$cmd);
68e0c4bd
DM
415 };
416
417 return $rpcenv->fork_worker('srvstart', $param->{service} || 'ceph',
418 $authuser, $worker);
38db610a
DM
419 }});
420
342c0830
DC
421__PACKAGE__->register_method ({
422 name => 'restart',
423 path => 'restart',
424 method => 'POST',
425 description => "Restart ceph services.",
426 proxyto => 'node',
427 protected => 1,
428 permissions => {
429 check => ['perm', '/', [ 'Sys.Modify' ]],
430 },
431 parameters => {
432 additionalProperties => 0,
433 properties => {
434 node => get_standard_option('pve-node'),
435 service => {
436 description => 'Ceph service name.',
437 type => 'string',
438 optional => 1,
33a9c70a 439 default => 'ceph.target',
7e98f79e 440 pattern => '(mon|mds|osd|mgr)(\.'.PVE::Ceph::Services::SERVICE_REGEX.')?',
342c0830
DC
441 },
442 },
443 },
444 returns => { type => 'string' },
445 code => sub {
446 my ($param) = @_;
447
448 my $rpcenv = PVE::RPCEnvironment::get();
449
450 my $authuser = $rpcenv->get_user();
451
6fb08cb9 452 PVE::Ceph::Tools::check_ceph_inited();
342c0830 453
c31f487e 454 my $cfg = cfs_read_file('ceph.conf');
342c0830
DC
455 scalar(keys %$cfg) || die "no configuration\n";
456
457 my $worker = sub {
458 my $upid = shift;
459
460 my $cmd = ['restart'];
461 if ($param->{service}) {
462 push @$cmd, $param->{service};
463 }
464
27439be6 465 PVE::Ceph::Services::ceph_service_cmd(@$cmd);
342c0830
DC
466 };
467
468 return $rpcenv->fork_worker('srvrestart', $param->{service} || 'ceph',
469 $authuser, $worker);
470 }});
471
38db610a
DM
472__PACKAGE__->register_method ({
473 name => 'status',
474 path => 'status',
475 method => 'GET',
476 description => "Get ceph status.",
477 proxyto => 'node',
478 protected => 1,
90c75580
TL
479 permissions => {
480 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
481 },
38db610a 482 parameters => {
be753927 483 additionalProperties => 0,
38db610a
DM
484 properties => {
485 node => get_standard_option('pve-node'),
486 },
487 },
488 returns => { type => 'object' },
489 code => sub {
490 my ($param) = @_;
491
0cfc6856 492 PVE::Ceph::Tools::check_ceph_inited();
38db610a 493
e25dda25 494 return PVE::Ceph::Tools::ceph_cluster_status();
38db610a
DM
495 }});
496
38db610a 497
2f692121
DM
498__PACKAGE__->register_method ({
499 name => 'crush',
500 path => 'crush',
501 method => 'GET',
502 description => "Get OSD crush map",
503 proxyto => 'node',
504 protected => 1,
90c75580
TL
505 permissions => {
506 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
507 },
2f692121 508 parameters => {
be753927 509 additionalProperties => 0,
2f692121
DM
510 properties => {
511 node => get_standard_option('pve-node'),
512 },
513 },
514 returns => { type => 'string' },
515 code => sub {
516 my ($param) = @_;
517
6fb08cb9 518 PVE::Ceph::Tools::check_ceph_inited();
2f692121 519
8b336060
DM
520 # this produces JSON (difficult to read for the user)
521 # my $txt = &$run_ceph_cmd_text(['osd', 'crush', 'dump'], quiet => 1);
2f692121 522
8b336060
DM
523 my $txt = '';
524
525 my $mapfile = "/var/tmp/ceph-crush.map.$$";
526 my $mapdata = "/var/tmp/ceph-crush.txt.$$";
527
36fd0190 528 my $rados = PVE::RADOS->new();
be753927 529
8b336060 530 eval {
970236b3 531 my $bindata = $rados->mon_command({ prefix => 'osd getcrushmap', format => 'plain' });
400742e4 532 file_set_contents($mapfile, $bindata);
8b336060 533 run_command(['crushtool', '-d', $mapfile, '-o', $mapdata]);
400742e4 534 $txt = file_get_contents($mapdata);
8b336060
DM
535 };
536 my $err = $@;
537
538 unlink $mapfile;
539 unlink $mapdata;
540
541 die $err if $err;
be753927 542
2f692121
DM
543 return $txt;
544 }});
545
570278fa 546__PACKAGE__->register_method({
be753927
DC
547 name => 'log',
548 path => 'log',
570278fa
DM
549 method => 'GET',
550 description => "Read ceph log",
551 proxyto => 'node',
552 permissions => {
553 check => ['perm', '/nodes/{node}', [ 'Sys.Syslog' ]],
554 },
555 protected => 1,
556 parameters => {
be753927 557 additionalProperties => 0,
570278fa
DM
558 properties => {
559 node => get_standard_option('pve-node'),
560 start => {
561 type => 'integer',
562 minimum => 0,
563 optional => 1,
564 },
565 limit => {
566 type => 'integer',
567 minimum => 0,
568 optional => 1,
569 },
570 },
571 },
572 returns => {
573 type => 'array',
be753927 574 items => {
570278fa
DM
575 type => "object",
576 properties => {
577 n => {
578 description=> "Line number",
579 type=> 'integer',
580 },
581 t => {
582 description=> "Line text",
583 type => 'string',
584 }
585 }
586 }
587 },
588 code => sub {
589 my ($param) = @_;
c56d75b4 590
6fb08cb9 591 PVE::Ceph::Tools::check_ceph_inited();
570278fa
DM
592
593 my $rpcenv = PVE::RPCEnvironment::get();
594 my $user = $rpcenv->get_user();
595 my $node = $param->{node};
596
597 my $logfile = "/var/log/ceph/ceph.log";
598 my ($count, $lines) = PVE::Tools::dump_logfile($logfile, $param->{start}, $param->{limit});
599
600 $rpcenv->set_result_attrib('total', $count);
be753927
DC
601
602 return $lines;
570278fa
DM
603 }});
604
d2692b86
DC
605__PACKAGE__->register_method ({
606 name => 'rules',
607 path => 'rules',
608 method => 'GET',
609 description => "List ceph rules.",
610 proxyto => 'node',
611 protected => 1,
612 permissions => {
613 check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
614 },
615 parameters => {
616 additionalProperties => 0,
617 properties => {
618 node => get_standard_option('pve-node'),
619 },
620 },
621 returns => {
622 type => 'array',
623 items => {
624 type => "object",
625 properties => {},
626 },
627 links => [ { rel => 'child', href => "{name}" } ],
628 },
629 code => sub {
630 my ($param) = @_;
631
6fb08cb9 632 PVE::Ceph::Tools::check_ceph_inited();
2f692121 633
d2692b86
DC
634 my $rados = PVE::RADOS->new();
635
636 my $rules = $rados->mon_command({ prefix => 'osd crush rule ls' });
637
638 my $res = [];
639
640 foreach my $rule (@$rules) {
641 push @$res, { name => $rule };
642 }
643
644 return $res;
645 }});
79fa41a2 646
ccb281a7
AL
647__PACKAGE__->register_method ({
648 name => 'cmd_safety',
649 path => 'cmd-safety',
650 method => 'GET',
651 description => "Heuristical check if it is safe to perform an action.",
652 proxyto => 'node',
653 protected => 1,
654 permissions => {
655 check => ['perm', '/', [ 'Sys.audit' ]],
656 },
657 parameters => {
658 additionalProperties => 0,
659 properties => {
660 node => get_standard_option('pve-node'),
661 service => {
662 description => 'Service type',
663 type => 'string',
664 enum => ['osd', 'mon', 'mds'],
665 },
666 id => {
667 description => 'ID of the service',
668 type => 'string',
669 },
670 action => {
671 description => 'Action to check',
672 type => 'string',
673 enum => ['stop', 'destroy'],
674 },
675 },
676 },
677 returns => {
678 type => 'object',
679 properties => {
680 safe => {
681 type => 'boolean',
682 description => 'If it is safe to run the command.',
683 },
684 status => {
685 type => 'string',
686 optional => 1,
687 description => 'Status message given by Ceph.'
688 },
689 },
690 },
691 code => sub {
692 my ($param) = @_;
693
694 PVE::Ceph::Tools::check_ceph_inited();
695
696 my $id = $param->{id};
697 my $service = $param->{service};
698 my $action = $param->{action};
699
700 my $rados = PVE::RADOS->new();
701
702 my $supported_actions = {
703 osd => {
704 stop => 'ok-to-stop',
705 destroy => 'safe-to-destroy',
706 },
707 mon => {
708 stop => 'ok-to-stop',
709 destroy => 'ok-to-rm',
710 },
711 mds => {
712 stop => 'ok-to-stop',
713 },
714 };
715
716 die "Service does not support this action: ${service}: ${action}\n"
717 if !$supported_actions->{$service}->{$action};
718
719 my $result = {
720 safe => 0,
721 status => '',
722 };
723
724 my $params = {
725 prefix => "${service} $supported_actions->{$service}->{$action}",
726 format => 'plain',
727 };
728 if ($service eq 'mon' && $action eq 'destroy') {
729 $params->{id} = $id;
730 } else {
731 $params->{ids} = [ $id ];
732 }
733
734 $result = $rados->mon_cmd($params, 1);
735 die $@ if $@;
736
737 $result->{safe} = $result->{return_code} == 0 ? 1 : 0;
738 $result->{status} = $result->{status_message};
739
740 return $result;
741 }});
742
79fa41a2 7431;