[pve-devel] [PATCH manager 3/5] api ceph osd: add volume details endpoint
Aaron Lauterer
a.lauterer at proxmox.com
Fri Jul 1 16:16:40 CEST 2022
This endpoint returns the following infos for an volume:
* creation time
* lv name
* lv path
* lv size
* lv uuid
* vg name
Possible volumes are:
* block (default value if not provided)
* db
* wal
'ceph-volume' is used to gather the infos, except for the creation time
of the LV which is retrieved via 'lvs'.
Signed-off-by: Aaron Lauterer <a.lauterer at proxmox.com>
---
While Ceph itself does not store any information about the creation time
of an OSD, I think we can get close to it by using the information
stored in the LVs.
PVE/API2/Ceph/OSD.pm | 109 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/PVE/API2/Ceph/OSD.pm b/PVE/API2/Ceph/OSD.pm
index 078a8c81..c9ec3222 100644
--- a/PVE/API2/Ceph/OSD.pm
+++ b/PVE/API2/Ceph/OSD.pm
@@ -5,6 +5,7 @@ use warnings;
use Cwd qw(abs_path);
use IO::File;
+use JSON;
use UUID;
use PVE::Ceph::Tools;
@@ -697,6 +698,114 @@ __PACKAGE__->register_method ({
return $data;
}});
+__PACKAGE__->register_method ({
+ name => 'osdvolume',
+ path => '{osdid}/volume',
+ method => 'GET',
+ description => "Get OSD volume details",
+ proxyto => 'node',
+ protected => 1,
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ osdid => {
+ description => 'OSD ID',
+ type => 'integer',
+ },
+ type => {
+ description => 'OSD device type',
+ type => 'string',
+ enum => ['block', 'db', 'wal'],
+ default => 'block',
+ optional => 1,
+ },
+ },
+ },
+ returns => {
+ type => 'object',
+ properties => {
+ creation_time => {
+ type => 'string',
+ description => "Creation time as reported by 'lvs'.",
+ },
+ lv_name => {
+ type => 'string',
+ description => 'Name of the logical volume (LV).',
+ },
+ lv_path => {
+ type => 'string',
+ description => 'Path to the logical volume (LV).',
+ },
+ lv_size => {
+ type => 'integer',
+ description => 'Size of the logical volume (LV).',
+ },
+ lv_uuid => {
+ type => 'string',
+ description => 'UUID of the logical volume (LV).',
+ },
+ vg_name => {
+ type => 'string',
+ description => 'Name of the volume group (VG).',
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ PVE::Ceph::Tools::check_ceph_inited();
+
+ my $osdid = $param->{osdid};
+ my $type = $param->{type} // 'block';
+
+ my $raw = '';
+ my $parser = sub { $raw .= shift };
+ my $cmd = ['/usr/sbin/ceph-volume', 'lvm', 'list', '--format', 'json'];
+ eval { run_command($cmd, errmsg => 'ceph volume error', outfunc => $parser) };
+ die $@ if $@;
+
+ my $result;
+ if ($raw =~ m/^(\{.*\})$/s) { #untaint
+ $result = JSON::decode_json($1);
+ } else {
+ die "got unexpected data from ceph-volume: '${raw}'\n";
+ }
+ die "OSD '${osdid}' not found in 'ceph-volume lvm list' on node '${nodename}'\n"
+ if !$result->{$osdid};
+
+ my $volume_data = {};
+ %{$volume_data} = map { $_->{type} => $_ } @{$result->{$osdid}};
+ die "volume type '${type}' not found for OSD ${osdid}\n" if !$volume_data->{$type};
+
+ my $volume = $volume_data->{$type};
+
+ $raw = '';
+ $cmd = ['/sbin/lvs', $volume->{lv_path}, '--reportformat', 'json', '-o', 'lv_time'];
+ eval { run_command($cmd, errmsg => 'lvs error', outfunc => $parser) };
+ die $@ if $@;
+
+ if ($raw =~ m/(\{.*\})$/s) { #untaint, lvs has whitespace at beginning
+ $result = JSON::decode_json($1);
+ } else {
+ die "got unexpected data from lvs: '${raw}'\n";
+ }
+ my $data = {};
+
+ my $keys = [ 'lv_name', 'lv_path', 'lv_uuid', 'vg_name' ];
+ for my $key (@$keys) {
+ $data->{$key} = $volume->{$key};
+ }
+ $data->{lv_size} = int($volume->{lv_size});
+
+ $data->{creation_time} = @{$result->{report}}[0]->{lv}[0]->{lv_time};
+
+ return $data;
+ }});
+
# Check if $osdid belongs to $nodename
# $tree ... rados osd tree (passing the tree makes it easy to test)
sub osd_belongs_to_node {
--
2.30.2
More information about the pve-devel
mailing list