1 package PVE
::API2
::Ceph
;
11 use PVE
::Ceph
::Services
;
12 use PVE
::Cluster
qw(cfs_read_file cfs_write_file);
13 use PVE
::JSONSchema
qw(get_standard_option);
17 use PVE
::RPCEnvironment
;
19 use PVE
::Tools
qw(run_command file_get_contents file_set_contents);
21 use PVE
::API2
::Ceph
::OSD
;
22 use PVE
::API2
::Ceph
::FS
;
23 use PVE
::API2
::Ceph
::MDS
;
24 use PVE
::API2
::Ceph
::MGR
;
25 use PVE
::API2
::Ceph
::MON
;
26 use PVE
::API2
::Storage
::Config
;
28 use base
qw(PVE::RESTHandler);
30 my $pve_osd_default_journal_size = 1024*5;
32 __PACKAGE__-
>register_method ({
33 subclass
=> "PVE::API2::Ceph::OSD",
37 __PACKAGE__-
>register_method ({
38 subclass
=> "PVE::API2::Ceph::MDS",
42 __PACKAGE__-
>register_method ({
43 subclass
=> "PVE::API2::Ceph::MGR",
47 __PACKAGE__-
>register_method ({
48 subclass
=> "PVE::API2::Ceph::MON",
52 __PACKAGE__-
>register_method ({
53 subclass
=> "PVE::API2::Ceph::FS",
57 __PACKAGE__-
>register_method ({
61 description
=> "Directory index.",
62 permissions
=> { user
=> 'all' },
64 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
67 additionalProperties
=> 0,
69 node
=> get_standard_option
('pve-node'),
78 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
92 { name
=> 'restart' },
106 __PACKAGE__-
>register_method ({
110 description
=> "List local disks.",
114 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
117 additionalProperties
=> 0,
119 node
=> get_standard_option
('pve-node'),
121 description
=> "Only list specific types of disks.",
123 enum
=> ['unused', 'journal_disks'],
133 dev
=> { type
=> 'string' },
134 used
=> { type
=> 'string', optional
=> 1 },
135 gpt
=> { type
=> 'boolean' },
136 size
=> { type
=> 'integer' },
137 osdid
=> { type
=> 'integer' },
138 vendor
=> { type
=> 'string', optional
=> 1 },
139 model
=> { type
=> 'string', optional
=> 1 },
140 serial
=> { type
=> 'string', optional
=> 1 },
143 # links => [ { rel => 'child', href => "{}" } ],
148 PVE
::Ceph
::Tools
::check_ceph_inited
();
150 my $disks = PVE
::Diskmanage
::get_disks
(undef, 1);
153 foreach my $dev (keys %$disks) {
154 my $d = $disks->{$dev};
155 if ($param->{type
}) {
156 if ($param->{type
} eq 'journal_disks') {
157 next if $d->{osdid
} >= 0;
159 } elsif ($param->{type
} eq 'unused') {
162 die "internal error"; # should not happen
166 $d->{dev
} = "/dev/$dev";
173 __PACKAGE__-
>register_method ({
179 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
181 description
=> "Get Ceph configuration.",
183 additionalProperties
=> 0,
185 node
=> get_standard_option
('pve-node'),
188 returns
=> { type
=> 'string' },
192 PVE
::Ceph
::Tools
::check_ceph_inited
();
194 my $path = PVE
::Ceph
::Tools
::get_config
('pve_ceph_cfgpath');
195 return file_get_contents
($path);
199 __PACKAGE__-
>register_method ({
206 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
208 description
=> "Get Ceph configuration database.",
210 additionalProperties
=> 0,
212 node
=> get_standard_option
('pve-node'),
220 section
=> { type
=> "string", },
221 name
=> { type
=> "string", },
222 value
=> { type
=> "string", },
223 level
=> { type
=> "string", },
224 'can_update_at_runtime' => { type
=> "boolean", },
225 mask
=> { type
=> "string" },
232 PVE
::Ceph
::Tools
::check_ceph_inited
();
234 my $rados = PVE
::RADOS-
>new();
235 my $res = $rados->mon_command( { prefix
=> 'config dump', format
=> 'json' });
236 foreach my $entry (@$res) {
237 $entry->{can_update_at_runtime
} = $entry->{can_update_at_runtime
}?
1 : 0; # JSON::true/false -> 1/0
243 my $add_storage = sub {
244 my ($pool, $storeid) = @_;
246 my $storage_params = {
251 content
=> 'rootdir,images',
254 PVE
::API2
::Storage
::Config-
>create($storage_params);
257 my $get_storages = sub {
260 my $cfg = PVE
::Storage
::config
();
262 my $storages = $cfg->{ids
};
264 foreach my $storeid (keys %$storages) {
265 my $curr = $storages->{$storeid};
266 $res->{$storeid} = $storages->{$storeid}
267 if $curr->{type
} eq 'rbd' && $pool eq $curr->{pool
};
273 __PACKAGE__-
>register_method ({
277 description
=> "Create initial ceph default configuration and setup symlinks.",
281 check
=> ['perm', '/', [ 'Sys.Modify' ]],
284 additionalProperties
=> 0,
286 node
=> get_standard_option
('pve-node'),
288 description
=> "Use specific network for all ceph related traffic",
289 type
=> 'string', format
=> 'CIDR',
293 'cluster-network' => {
294 description
=> "Declare a separate cluster network, OSDs will route" .
295 "heartbeat, object replication and recovery traffic over it",
296 type
=> 'string', format
=> 'CIDR',
297 requires
=> 'network',
302 description
=> 'Targeted number of replicas per object',
310 description
=> 'Minimum number of available replicas per object to allow I/O',
318 description
=> "Placement group bits, used to specify the " .
319 "default number of placement groups.\n\nNOTE: 'osd pool " .
320 "default pg num' does not work for default pools.",
328 description
=> "Disable cephx authentication.\n\n" .
329 "WARNING: cephx is a security feature protecting against " .
330 "man-in-the-middle attacks. Only consider disabling cephx ".
331 "if your network is private!",
338 returns
=> { type
=> 'null' },
342 my $version = PVE
::Ceph
::Tools
::get_local_version
(1);
344 if (!$version || $version < 14) {
345 die "Ceph Nautilus required - please run 'pveceph install'\n";
347 PVE
::Ceph
::Tools
::check_ceph_installed
('ceph_bin');
350 my $auth = $param->{disable_cephx
} ?
'none' : 'cephx';
352 # simply load old config if it already exists
353 PVE
::Cluster
::cfs_lock_file
('ceph.conf', undef, sub {
354 my $cfg = cfs_read_file
('ceph.conf');
356 if (!$cfg->{global
}) {
361 UUID
::generate
($uuid);
362 UUID
::unparse
($uuid, $fsid);
366 'auth cluster required' => $auth,
367 'auth service required' => $auth,
368 'auth client required' => $auth,
369 'osd pool default size' => $param->{size
} // 3,
370 'osd pool default min size' => $param->{min_size
} // 2,
371 'mon allow pool delete' => 'true',
374 # this does not work for default pools
375 #'osd pool default pg num' => $pg_num,
376 #'osd pool default pgp num' => $pg_num,
379 if ($auth eq 'cephx') {
380 $cfg->{client
}->{keyring
} = '/etc/pve/priv/$cluster.$name.keyring';
383 if ($param->{pg_bits
}) {
384 $cfg->{global
}->{'osd pg bits'} = $param->{pg_bits
};
385 $cfg->{global
}->{'osd pgp bits'} = $param->{pg_bits
};
388 if ($param->{network
}) {
389 $cfg->{global
}->{'public network'} = $param->{network
};
390 $cfg->{global
}->{'cluster network'} = $param->{network
};
393 if ($param->{'cluster-network'}) {
394 $cfg->{global
}->{'cluster network'} = $param->{'cluster-network'};
397 cfs_write_file
('ceph.conf', $cfg);
399 if ($auth eq 'cephx') {
400 PVE
::Ceph
::Tools
::get_or_create_admin_keyring
();
402 PVE
::Ceph
::Tools
::setup_pve_symlinks
();
409 __PACKAGE__-
>register_method ({
413 description
=> "Stop ceph services.",
417 check
=> ['perm', '/', [ 'Sys.Modify' ]],
420 additionalProperties
=> 0,
422 node
=> get_standard_option
('pve-node'),
424 description
=> 'Ceph service name.',
427 default => 'ceph.target',
428 pattern
=> '(ceph|mon|mds|osd|mgr)\.[A-Za-z0-9\-]{1,32}',
432 returns
=> { type
=> 'string' },
436 my $rpcenv = PVE
::RPCEnvironment
::get
();
438 my $authuser = $rpcenv->get_user();
440 PVE
::Ceph
::Tools
::check_ceph_inited
();
442 my $cfg = cfs_read_file
('ceph.conf');
443 scalar(keys %$cfg) || die "no configuration\n";
449 if ($param->{service
}) {
450 push @$cmd, $param->{service
};
453 PVE
::Ceph
::Services
::ceph_service_cmd
(@$cmd);
456 return $rpcenv->fork_worker('srvstop', $param->{service
} || 'ceph',
460 __PACKAGE__-
>register_method ({
464 description
=> "Start ceph services.",
468 check
=> ['perm', '/', [ 'Sys.Modify' ]],
471 additionalProperties
=> 0,
473 node
=> get_standard_option
('pve-node'),
475 description
=> 'Ceph service name.',
478 default => 'ceph.target',
479 pattern
=> '(ceph|mon|mds|osd|mgr)\.[A-Za-z0-9\-]{1,32}',
483 returns
=> { type
=> 'string' },
487 my $rpcenv = PVE
::RPCEnvironment
::get
();
489 my $authuser = $rpcenv->get_user();
491 PVE
::Ceph
::Tools
::check_ceph_inited
();
493 my $cfg = cfs_read_file
('ceph.conf');
494 scalar(keys %$cfg) || die "no configuration\n";
500 if ($param->{service
}) {
501 push @$cmd, $param->{service
};
504 PVE
::Ceph
::Services
::ceph_service_cmd
(@$cmd);
507 return $rpcenv->fork_worker('srvstart', $param->{service
} || 'ceph',
511 __PACKAGE__-
>register_method ({
515 description
=> "Restart ceph services.",
519 check
=> ['perm', '/', [ 'Sys.Modify' ]],
522 additionalProperties
=> 0,
524 node
=> get_standard_option
('pve-node'),
526 description
=> 'Ceph service name.',
529 default => 'ceph.target',
530 pattern
=> '(mon|mds|osd|mgr)\.[A-Za-z0-9\-]{1,32}',
534 returns
=> { type
=> 'string' },
538 my $rpcenv = PVE
::RPCEnvironment
::get
();
540 my $authuser = $rpcenv->get_user();
542 PVE
::Ceph
::Tools
::check_ceph_inited
();
544 my $cfg = cfs_read_file
('ceph.conf');
545 scalar(keys %$cfg) || die "no configuration\n";
550 my $cmd = ['restart'];
551 if ($param->{service
}) {
552 push @$cmd, $param->{service
};
555 PVE
::Ceph
::Services
::ceph_service_cmd
(@$cmd);
558 return $rpcenv->fork_worker('srvrestart', $param->{service
} || 'ceph',
562 __PACKAGE__-
>register_method ({
566 description
=> "Get ceph status.",
570 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
573 additionalProperties
=> 0,
575 node
=> get_standard_option
('pve-node'),
578 returns
=> { type
=> 'object' },
582 PVE
::Ceph
::Tools
::check_ceph_inited
();
584 my $rados = PVE
::RADOS-
>new();
585 my $status = $rados->mon_command({ prefix
=> 'status' });
586 $status->{health
} = $rados->mon_command({ prefix
=> 'health', detail
=> 'detail' });
590 __PACKAGE__-
>register_method ({
594 description
=> "List all pools.",
598 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
601 additionalProperties
=> 0,
603 node
=> get_standard_option
('pve-node'),
611 pool
=> { type
=> 'integer' },
612 pool_name
=> { type
=> 'string' },
613 size
=> { type
=> 'integer' },
616 links
=> [ { rel
=> 'child', href
=> "{pool_name}" } ],
621 PVE
::Ceph
::Tools
::check_ceph_inited
();
623 my $rados = PVE
::RADOS-
>new();
626 my $res = $rados->mon_command({ prefix
=> 'df' });
628 foreach my $d (@{$res->{pools
}}) {
629 next if !$d->{stats
};
630 next if !defined($d->{id
});
631 $stats->{$d->{id
}} = $d->{stats
};
634 $res = $rados->mon_command({ prefix
=> 'osd dump' });
635 my $rulestmp = $rados->mon_command({ prefix
=> 'osd crush rule dump'});
638 for my $rule (@$rulestmp) {
639 $rules->{$rule->{rule_id
}} = $rule->{rule_name
};
643 foreach my $e (@{$res->{pools
}}) {
645 foreach my $attr (qw(pool pool_name size min_size pg_num crush_rule)) {
646 $d->{$attr} = $e->{$attr} if defined($e->{$attr});
649 if (defined($d->{crush_rule
}) && defined($rules->{$d->{crush_rule
}})) {
650 $d->{crush_rule_name
} = $rules->{$d->{crush_rule
}};
653 if (my $s = $stats->{$d->{pool
}}) {
654 $d->{bytes_used
} = $s->{bytes_used
};
655 $d->{percent_used
} = $s->{percent_used
};
664 __PACKAGE__-
>register_method ({
665 name
=> 'createpool',
668 description
=> "Create POOL",
672 check
=> ['perm', '/', [ 'Sys.Modify' ]],
675 additionalProperties
=> 0,
677 node
=> get_standard_option
('pve-node'),
679 description
=> "The name of the pool. It must be unique.",
683 description
=> 'Number of replicas per object',
691 description
=> 'Minimum number of replicas per object',
699 description
=> "Number of placement groups.",
707 description
=> "The rule to use for mapping object placement in the cluster.",
712 description
=> "The application of the pool, 'rbd' by default.",
714 enum
=> ['rbd', 'cephfs', 'rgw'],
718 description
=> "Configure VM and CT storage using the new pool.",
724 returns
=> { type
=> 'string' },
728 PVE
::Cluster
::check_cfs_quorum
();
729 PVE
::Ceph
::Tools
::check_ceph_configured
();
731 my $pool = $param->{name
};
732 my $rpcenv = PVE
::RPCEnvironment
::get
();
733 my $user = $rpcenv->get_user();
735 if ($param->{add_storages
}) {
736 $rpcenv->check($user, '/storage', ['Datastore.Allocate']);
737 die "pool name contains characters which are illegal for storage naming\n"
738 if !PVE
::JSONSchema
::parse_storage_id
($pool);
741 my $pg_num = $param->{pg_num
} || 128;
742 my $size = $param->{size
} || 3;
743 my $min_size = $param->{min_size
} || 2;
744 my $application = $param->{application
} // 'rbd';
748 PVE
::Ceph
::Tools
::create_pool
($pool, $param);
750 if ($param->{add_storages
}) {
752 eval { $add_storage->($pool, "${pool}"); };
754 warn "failed to add storage: $@";
757 die "adding storage for pool '$pool' failed, check log and add manually!\n"
762 return $rpcenv->fork_worker('cephcreatepool', $pool, $user, $worker);
765 my $possible_flags = {
767 description
=> 'Pauses read and writes.',
772 description
=> 'OSDs are not allowed to start.',
777 description
=> 'OSD failure reports are being ignored, such that the monitors will not mark OSDs down.',
782 description
=> 'OSDs will not automatically be marked out after the configured interval.',
787 description
=> 'OSDs that were previously marked out will not be marked back in when they start.',
792 description
=> 'Backfilling of PGs is suspended.',
797 description
=> 'Rebalancing of PGs is suspended.',
802 description
=> 'Recovery of PGs is suspended.',
807 description
=> 'Scrubbing is disabled.',
812 description
=> 'Deep Scrubbing is disabled.',
817 description
=> 'Cache tiering activity is suspended.',
823 # the 'pause' flag gets always set to both 'pauserd' and 'pausewr'
824 # so decide that the 'pause' flag is set if we detect 'pauserd'
826 'pause' => 'pauserd',
829 __PACKAGE__-
>register_method ({
833 description
=> "get the status of all ceph flags",
837 check
=> ['perm', '/', [ 'Sys.Audit' ]],
840 additionalProperties
=> 0,
842 node
=> get_standard_option
('pve-node'),
845 returns
=> { type
=> 'array' },
849 PVE
::Ceph
::Tools
::check_ceph_configured
();
851 my $rados = PVE
::RADOS-
>new();
853 my $stat = $rados->mon_command({ prefix
=> 'osd dump' });
855 foreach my $flag (PVE
::Tools
::split_list
($stat->{flags
} // '')) {
856 $setflags->{$flag} = 1;
860 foreach my $flag (sort keys %$possible_flags) {
863 description
=> $possible_flags->{$flag}->{description
},
867 my $realflag = $flagmap->{$flag} // $flag;
868 if ($setflags->{$realflag}) {
878 __PACKAGE__-
>register_method ({
882 description
=> "get all set ceph flags",
886 check
=> ['perm', '/', [ 'Sys.Audit' ]],
889 additionalProperties
=> 0,
891 node
=> get_standard_option
('pve-node'),
894 returns
=> { type
=> 'string' },
898 PVE
::Ceph
::Tools
::check_ceph_configured
();
900 my $rados = PVE
::RADOS-
>new();
902 my $stat = $rados->mon_command({ prefix
=> 'osd dump' });
904 return $stat->{flags
} // '';
907 __PACKAGE__-
>register_method ({
911 description
=> "Set/Unset multiple ceph flags at once.",
915 check
=> ['perm', '/', [ 'Sys.Modify' ]],
918 additionalProperties
=> 0,
920 node
=> get_standard_option
('pve-node'),
924 returns
=> { type
=> 'string' },
928 my $rpcenv = PVE
::RPCEnvironment
::get
();
929 my $user = $rpcenv->get_user();
930 PVE
::Ceph
::Tools
::check_ceph_configured
();
932 my $rados = PVE
::RADOS-
>new();
935 # reopen rados object
936 my $rados = PVE
::RADOS-
>new();
937 my $stat = $rados->mon_command({ prefix
=> 'osd dump' });
938 my $setflags = $stat->{flags
} // '';
939 $setflags = { map { $_ => 1 } PVE
::Tools
::split_list
($setflags) };
941 foreach my $flag (sort keys %$possible_flags) {
942 next if !defined($param->{$flag});
943 my $val = $param->{$flag};
944 my $realflag = $flagmap->{$flag} // $flag;
945 next if !$val == !$setflags->{$realflag}; # we do not set/unset flags to the same state
947 my $prefix = $val ?
'set' : 'unset';
949 print "$prefix $flag\n";
950 $rados->mon_command({ prefix
=> "osd $prefix", key
=> $flag, });
953 warn "error with $flag: '$err'\n";
959 die "could not set/unset $errors flags\n";
963 return $rpcenv->fork_worker('cephsetflags', undef, $user, $worker);
966 __PACKAGE__-
>register_method ({
968 path
=> 'flags/{flag}',
970 description
=> "Set a ceph flag",
974 check
=> ['perm', '/', [ 'Sys.Modify' ]],
977 additionalProperties
=> 0,
979 node
=> get_standard_option
('pve-node'),
981 description
=> 'The ceph flag to set',
983 enum
=> [sort keys %$possible_flags],
987 returns
=> { type
=> 'null' },
991 PVE
::Ceph
::Tools
::check_ceph_configured
();
993 my $set = $param->{set
} // !$param->{unset
};
994 my $rados = PVE
::RADOS-
>new();
996 $rados->mon_command({
998 key
=> $param->{flag
},
1004 __PACKAGE__-
>register_method ({
1005 name
=> 'unset_flag',
1006 path
=> 'flags/{flag}',
1008 description
=> "Unset a ceph flag",
1012 check
=> ['perm', '/', [ 'Sys.Modify' ]],
1015 additionalProperties
=> 0,
1017 node
=> get_standard_option
('pve-node'),
1019 description
=> 'The ceph flag to unset',
1021 enum
=> [sort keys %$possible_flags],
1025 returns
=> { type
=> 'null' },
1029 PVE
::Ceph
::Tools
::check_ceph_configured
();
1031 my $set = $param->{set
} // !$param->{unset
};
1032 my $rados = PVE
::RADOS-
>new();
1034 $rados->mon_command({
1035 prefix
=> "osd unset",
1036 key
=> $param->{flag
},
1042 __PACKAGE__-
>register_method ({
1043 name
=> 'destroypool',
1044 path
=> 'pools/{name}',
1046 description
=> "Destroy pool",
1050 check
=> ['perm', '/', [ 'Sys.Modify' ]],
1053 additionalProperties
=> 0,
1055 node
=> get_standard_option
('pve-node'),
1057 description
=> "The name of the pool. It must be unique.",
1061 description
=> "If true, destroys pool even if in use",
1066 remove_storages
=> {
1067 description
=> "Remove all pveceph-managed storages configured for this pool",
1074 returns
=> { type
=> 'string' },
1078 PVE
::Ceph
::Tools
::check_ceph_inited
();
1080 my $rpcenv = PVE
::RPCEnvironment
::get
();
1081 my $user = $rpcenv->get_user();
1082 $rpcenv->check($user, '/storage', ['Datastore.Allocate'])
1083 if $param->{remove_storages
};
1085 my $pool = $param->{name
};
1088 my $storages = $get_storages->($pool);
1090 # if not forced, destroy ceph pool only when no
1091 # vm disks are on it anymore
1092 if (!$param->{force
}) {
1093 my $storagecfg = PVE
::Storage
::config
();
1094 foreach my $storeid (keys %$storages) {
1095 my $storage = $storages->{$storeid};
1097 # check if any vm disks are on the pool
1098 print "checking storage '$storeid' for RBD images..\n";
1099 my $res = PVE
::Storage
::vdisk_list
($storagecfg, $storeid);
1100 die "ceph pool '$pool' still in use by storage '$storeid'\n"
1101 if @{$res->{$storeid}} != 0;
1105 PVE
::Ceph
::Tools
::destroy_pool
($pool);
1107 if ($param->{remove_storages
}) {
1109 foreach my $storeid (keys %$storages) {
1110 # skip external clusters, not managed by pveceph
1111 next if $storages->{$storeid}->{monhost
};
1112 eval { PVE
::API2
::Storage
::Config-
>delete({storage
=> $storeid}) };
1114 warn "failed to remove storage '$storeid': $@\n";
1118 die "failed to remove (some) storages - check log and remove manually!\n"
1122 return $rpcenv->fork_worker('cephdestroypool', $pool, $user, $worker);
1126 __PACKAGE__-
>register_method ({
1130 description
=> "Get OSD crush map",
1134 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
1137 additionalProperties
=> 0,
1139 node
=> get_standard_option
('pve-node'),
1142 returns
=> { type
=> 'string' },
1146 PVE
::Ceph
::Tools
::check_ceph_inited
();
1148 # this produces JSON (difficult to read for the user)
1149 # my $txt = &$run_ceph_cmd_text(['osd', 'crush', 'dump'], quiet => 1);
1153 my $mapfile = "/var/tmp/ceph-crush.map.$$";
1154 my $mapdata = "/var/tmp/ceph-crush.txt.$$";
1156 my $rados = PVE
::RADOS-
>new();
1159 my $bindata = $rados->mon_command({ prefix
=> 'osd getcrushmap', format
=> 'plain' });
1160 file_set_contents
($mapfile, $bindata);
1161 run_command
(['crushtool', '-d', $mapfile, '-o', $mapdata]);
1162 $txt = file_get_contents
($mapdata);
1174 __PACKAGE__-
>register_method({
1178 description
=> "Read ceph log",
1181 check
=> ['perm', '/nodes/{node}', [ 'Sys.Syslog' ]],
1185 additionalProperties
=> 0,
1187 node
=> get_standard_option
('pve-node'),
1206 description
=> "Line number",
1210 description
=> "Line text",
1219 PVE
::Ceph
::Tools
::check_ceph_inited
();
1221 my $rpcenv = PVE
::RPCEnvironment
::get
();
1222 my $user = $rpcenv->get_user();
1223 my $node = $param->{node
};
1225 my $logfile = "/var/log/ceph/ceph.log";
1226 my ($count, $lines) = PVE
::Tools
::dump_logfile
($logfile, $param->{start
}, $param->{limit
});
1228 $rpcenv->set_result_attrib('total', $count);
1233 __PACKAGE__-
>register_method ({
1237 description
=> "List ceph rules.",
1241 check
=> ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any
=> 1],
1244 additionalProperties
=> 0,
1246 node
=> get_standard_option
('pve-node'),
1255 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
1260 PVE
::Ceph
::Tools
::check_ceph_inited
();
1262 my $rados = PVE
::RADOS-
>new();
1264 my $rules = $rados->mon_command({ prefix
=> 'osd crush rule ls' });
1268 foreach my $rule (@$rules) {
1269 push @$res, { name
=> $rule };