all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Max Carrara <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC pve-storage 09/36] plugin: lvm: move LVM helper subroutines into separate common module
Date: Wed, 17 Jul 2024 11:40:07 +0200	[thread overview]
Message-ID: <20240717094034.124857-10-m.carrara@proxmox.com> (raw)
In-Reply-To: <20240717094034.124857-1-m.carrara@proxmox.com>

A plugin should only do "plugin stuff" and not provide helper subs
that other modules also use, so move those helpers into a separate
module and document them.

This new `Common::LVM` module is a submodule of `Common` (as its name
implies) as that logically groups LVM-related subroutines together.

The changes of this commit are backwards-compatible; the old subs act
as mere wrappers and will emit a warning when used.

Signed-off-by: Max Carrara <m.carrara@proxmox.com>
---
 src/PVE/Storage/Common.pm       |   4 +
 src/PVE/Storage/Common/LVM.pm   | 432 ++++++++++++++++++++++++++++++++
 src/PVE/Storage/Common/Makefile |   1 +
 src/PVE/Storage/LVMPlugin.pm    | 254 +++++--------------
 4 files changed, 497 insertions(+), 194 deletions(-)
 create mode 100644 src/PVE/Storage/Common/LVM.pm

diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index a2ae979..0ca0db1 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -32,6 +32,10 @@ be grouped in a submodule can also be found here.
 
 =over
 
+=item C<PVE::Storage::Common::LVM>
+
+Utilities concerned with LVM, such as manipulating logical volumes.
+
 =item C<PVE::Storage::Common::Path>
 
 Utilities concerned with working with paths.
diff --git a/src/PVE/Storage/Common/LVM.pm b/src/PVE/Storage/Common/LVM.pm
new file mode 100644
index 0000000..e0e3263
--- /dev/null
+++ b/src/PVE/Storage/Common/LVM.pm
@@ -0,0 +1,432 @@
+package PVE::Storage::Common::LVM;
+
+use strict;
+use warnings;
+
+use IO::File;
+
+use PVE::Tools qw(run_command trim);
+
+use parent qw(Exporter);
+
+our @EXPORT_OK = qw(
+    lvm_pv_info
+    lvm_clear_first_sector
+    lvm_create_volume_group
+    lvm_destroy_volume_group
+    lvm_vgs
+    lvm_list_volumes
+    lvm_lvcreate
+    lvm_lvrename
+);
+
+=pod
+
+=head1 NAME
+
+Common::LVM - Provides helper subroutines that wrap commonly used LVM commands
+
+=head1 FUNCTIONS
+
+=cut
+
+my $ignore_no_medium_warnings = sub {
+    my $line = shift;
+    # ignore those, most of the time they're from (virtual) IPMI/iKVM devices
+    # and just spam the log..
+    if ($line !~ /open failed: No medium found/) {
+	print STDERR "$line\n";
+    }
+};
+
+=pod
+
+=head3 lvm_pv_info
+
+    $pvinfo = lvm_pv_info($device)
+
+Returns a hash containing information for a I<physical volume> specified
+by C<$device>, which must be a valid device path under C</dev>.
+
+The returned hash has the following structure:
+
+    {
+	pvname => "some-pv-name",
+	size => 15728640,  # size in kibibytes!
+	vgname => "some-vg-name",
+	uuid => "1ba3cb42-5407-4cd5-9754-7060dc36ce6d",
+    }
+
+This function will die if no C<$device> is specified of if multiple PV entries
+exist for C<$device>.
+
+Should the C<$device> not have an C<LVM2> label, this function will return
+C<undef> instead.
+
+=cut
+
+sub lvm_pv_info : prototype($) {
+    my ($device) = @_;
+
+    die "no device specified" if !$device;
+
+    my $has_label = 0;
+
+    my $cmd = ['/usr/bin/file', '-L', '-s', $device];
+    run_command($cmd, outfunc => sub {
+	my $line = shift;
+	$has_label = 1 if $line =~ m/LVM2/;
+    });
+
+    return undef if !$has_label;
+
+    $cmd = ['/sbin/pvs', '--separator', ':', '--noheadings', '--units', 'k',
+	    '--unbuffered', '--nosuffix', '--options',
+	    'pv_name,pv_size,vg_name,pv_uuid', $device];
+
+    my $pvinfo;
+    run_command($cmd, outfunc => sub {
+	my $line = shift;
+
+	$line = trim($line);
+
+	my ($pvname, $size, $vgname, $uuid) = split(':', $line);
+
+	die "found multiple pvs entries for device '$device'\n"
+	    if $pvinfo;
+
+	$pvinfo = {
+	    pvname => $pvname,
+	    size => int($size),
+	    vgname => $vgname,
+	    uuid => $uuid,
+	};
+    });
+
+    return $pvinfo;
+}
+
+=pod
+
+=head3 lvm_clear_first_sector
+
+    lvm_clear_first_sector($device)
+
+Clears the first sector (first 512 bits) of the given block device C<$device>.
+
+B<WARNING:> Use with caution. This function does not actually check whether
+a valid device is passed or not.
+
+=cut
+
+sub lvm_clear_first_sector : prototype($) {
+    my ($dev) = shift;
+
+    if (my $fh = IO::File->new($dev, "w")) {
+	my $buf = 0 x 512;
+	syswrite $fh, $buf;
+	$fh->close();
+    }
+}
+
+=pod
+
+=head3 lvm_create_volume_group
+
+    lvm_create_volume_group($device, $vgname, $shared)
+
+Creates a I<volume group> for the block device C<$device> with the name
+C<$vgname>. The C<$shared> parameter is currently unused.
+
+Dies if C<$device> is already part of a volume group.
+
+If C<$device> is already part of a volume group with the exact same name as in
+C<$vgname>, nothing will be done and the function returns early.
+
+=cut
+
+sub lvm_create_volume_group : prototype($$$) {
+    my ($device, $vgname, $shared) = @_;
+
+    my $res = lvm_pv_info($device);
+
+    if ($res->{vgname}) {
+	return if $res->{vgname} eq $vgname; # already created
+	die "device '$device' is already used by volume group '$res->{vgname}'\n";
+    }
+
+    lvm_clear_first_sector($device); # else pvcreate fails
+
+    # we use --metadatasize 250k, which reseults in "pe_start = 512"
+    # so pe_start is aligned on a 128k boundary (advantage for SSDs)
+    my $cmd = ['/sbin/pvcreate', '--metadatasize', '250k', $device];
+
+    run_command($cmd, errmsg => "pvcreate '$device' error");
+
+    $cmd = ['/sbin/vgcreate', $vgname, $device];
+    # push @$cmd, '-c', 'y' if $shared; # we do not use this yet
+
+    run_command($cmd, errmsg => "vgcreate $vgname $device error", errfunc => $ignore_no_medium_warnings, outfunc => $ignore_no_medium_warnings);
+}
+
+=pod
+
+=head3 lvm_destroy_volume_group
+
+    lvm_destroy_volume_group($vgname)
+
+Destroys the I<volume group> with the name C<$vgname>.
+
+=cut
+
+sub lvm_destroy_volume_group : prototype($) {
+    my ($vgname) = @_;
+
+    run_command(
+	['vgremove', '-y', $vgname],
+	errmsg => "unable to remove volume group $vgname",
+	errfunc => $ignore_no_medium_warnings,
+	outfunc => $ignore_no_medium_warnings,
+    );
+}
+
+=pod
+
+=head3 lvm_vgs
+
+    $vgs = lvm_vgs()
+    $vgs = lvm_vgs($includepvs)
+    $vgs = lvm_vgs(1)
+
+Returns a hash containing information of the host's I<volume groups>. If the
+optional C<$includepvs> parameter is truthy or C<1>, the hash will also contain
+extra data for the I<physical volumes> in each volume group.
+
+The returned hash has the following structure:
+
+    {
+	'vg-name-00' => {
+	    size => 16106127360,  # sizes in bytes!
+	    free => 10737418240,
+	    lvcount => 2,
+	    pvs => [
+		{
+		    name => 'vg-name-00--pv-00',
+		    size => ...,
+		    free => ...,
+		},
+		{
+		    name => 'vg-name-00--pv-01',
+		    size => ...,
+		    free => ...,
+		},
+	    ]
+	},
+	'vg-name-01' => {
+	    size => 16106127360,
+	    free => 10737418240,
+	    lvcount => 1,
+	    pvs => [
+		{
+		    name => 'vg-name-01--pv-00',
+		    size => ...,
+		    free => ...,
+		},
+	    ]
+	},
+    }
+
+=cut
+
+sub lvm_vgs : prototype(;$) {
+    my ($includepvs) = @_;
+
+    my $cmd = ['/sbin/vgs', '--separator', ':', '--noheadings', '--units', 'b',
+	       '--unbuffered', '--nosuffix', '--options'];
+
+    my $cols = [qw(vg_name vg_size vg_free lv_count)];
+
+    if ($includepvs) {
+	push @$cols, qw(pv_name pv_size pv_free);
+    }
+
+    push @$cmd, join(',', @$cols);
+
+    my $vgs = {};
+    eval {
+	run_command($cmd, outfunc => sub {
+	    my $line = shift;
+	    $line = trim($line);
+
+	    my ($name, $size, $free, $lvcount, $pvname, $pvsize, $pvfree) = split (':', $line);
+
+	    $vgs->{$name} //= {
+		size => int ($size),
+		free => int ($free),
+		lvcount => int($lvcount)
+	    };
+
+	    if (defined($pvname) && defined($pvsize) && defined($pvfree)) {
+		push @{$vgs->{$name}->{pvs}}, {
+		    name => $pvname,
+		    size => int($pvsize),
+		    free => int($pvfree),
+		};
+	    }
+	},
+	errfunc => $ignore_no_medium_warnings,
+	);
+    };
+    my $err = $@;
+
+    # just warn (vgs return error code 5 if clvmd does not run)
+    # but output is still OK (list without clustered VGs)
+    warn $err if $err;
+
+    return $vgs;
+}
+
+=pod
+
+=head3 lvm_list_volumes
+
+    $lvs = lvm_list_volumes()
+    $lvs = lvm_list_volumes($vgname)
+
+Returns a hash with information of all I<logical volumes> on the host. May
+optionally be limited to a single I<volume group> by providing its name
+C<$vgname>.
+
+The returned hash has the following structure:
+
+    {
+	'vg-name-00' => {
+	    'lv-name-00' => {
+		lv_size => 10737418240,  # sizes in bytes!
+		lv_state => '...',
+		lv_type => '...',
+		pool_lv => '...',   # optional
+		tags => '...',	    # optional
+		ctime => '...',
+	    },
+	    'lv-name-01' => {
+		lv_size => 10737418240,
+		lv_state => '...',
+		lv_type => 't',
+		pool_lv => '...',   # optional
+		tags => '...',	    # optional
+		ctime => '...',
+		# thinpool specific data
+		metadata_size => 29381237,  # sizes in bytes!
+		metadata_used => 12917,
+		used => 3543348019,
+	    },
+	},
+	'vg-name-00' => {
+	    ...
+	}
+    }
+
+=cut
+
+sub lvm_list_volumes : prototype(;$) {
+    my ($vgname) = @_;
+
+    my $option_list = 'vg_name,lv_name,lv_size,lv_attr,pool_lv,data_percent,metadata_percent,snap_percent,uuid,tags,metadata_size,time';
+
+    my $cmd = [
+	'/sbin/lvs', '--separator', ':', '--noheadings', '--units', 'b',
+	'--unbuffered', '--nosuffix',
+	'--config', 'report/time_format="%s"',
+	'--options', $option_list,
+    ];
+
+    push @$cmd, $vgname if $vgname;
+
+    my $lvs = {};
+    run_command($cmd, outfunc => sub {
+	my $line = shift;
+
+	$line = trim($line);
+
+	my ($vg_name, $lv_name, $lv_size, $lv_attr, $pool_lv, $data_percent, $meta_percent, $snap_percent, $uuid, $tags, $meta_size, $ctime) = split(':', $line);
+	return if !$vg_name;
+	return if !$lv_name;
+
+	my $lv_type = substr($lv_attr, 0, 1);
+
+	my $d = {
+	    lv_size => int($lv_size),
+	    lv_state => substr($lv_attr, 4, 1),
+	    lv_type => $lv_type,
+	};
+	$d->{pool_lv} = $pool_lv if $pool_lv;
+	$d->{tags} = $tags if $tags;
+	$d->{ctime} = $ctime;
+
+	if ($lv_type eq 't') {
+	    $data_percent ||= 0;
+	    $meta_percent ||= 0;
+	    $snap_percent ||= 0;
+	    $d->{metadata_size} = int($meta_size);
+	    $d->{metadata_used} = int(($meta_percent * $meta_size)/100);
+	    $d->{used} = int(($data_percent * $lv_size)/100);
+	}
+	$lvs->{$vg_name}->{$lv_name} = $d;
+    },
+    errfunc => $ignore_no_medium_warnings,
+    );
+
+    return $lvs;
+}
+
+=head3 lvm_lvcreate
+
+    lvm_lvcreate($vgname, $name, $size, $tags)
+
+Creates a new I<logical volume> named C<$name> for the I<volume group>
+C<$vgname>, with a size of C<$size> B<kibibytes> per default. Optionally,
+a list of tags for the new LV may be provided via C<$tags>.
+
+Alternatively, C<$size> may optionally also be expressed with a unit, e.g.
+C<"50g"> (50 gibibytes), C<"1T"> (1 terabyte), etc.
+
+=cut
+
+sub lvm_lvcreate : prototype($$$;$) {
+    my ($vg, $name, $size, $tags) = @_;
+
+    if ($size =~ m/\d$/) { # no unit is given
+	$size .= "k"; # default to kilobytes
+    }
+
+    my $cmd = ['/sbin/lvcreate', '-aly', '-Wy', '--yes', '--size', $size, '--name', $name];
+    for my $tag (@$tags) {
+	push @$cmd, '--addtag', $tag;
+    }
+    push @$cmd, $vg;
+
+    run_command($cmd, errmsg => "lvcreate '$vg/$name' error");
+}
+
+=pod
+
+=head3 lvm_lvrename
+
+    lvm_lvrename($vgname, $oldname, $newname)
+
+Renames a I<logical volume> of a I<volume group> C<$vgname> from C<$oldname>
+to C<$newname>.
+
+=cut
+
+sub lvm_lvrename : prototype($$$) {
+    my ($vg, $oldname, $newname) = @_;
+
+    run_command(
+	['/sbin/lvrename', $vg, $oldname, $newname],
+	errmsg => "lvrename '${vg}/${oldname}' to '${newname}' error",
+    );
+}
+
+1;
diff --git a/src/PVE/Storage/Common/Makefile b/src/PVE/Storage/Common/Makefile
index 9455b81..863f7c7 100644
--- a/src/PVE/Storage/Common/Makefile
+++ b/src/PVE/Storage/Common/Makefile
@@ -1,4 +1,5 @@
 SOURCES = \
+	  LVM.pm \
 	  Path.pm \
 
 
diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm
index 4b951e7..a9bc178 100644
--- a/src/PVE/Storage/LVMPlugin.pm
+++ b/src/PVE/Storage/LVMPlugin.pm
@@ -6,207 +6,98 @@ use warnings;
 use IO::File;
 
 use PVE::Tools qw(run_command trim);
+use PVE::Storage::Common qw(get_deprecation_warning);
 use PVE::Storage::Plugin;
+use PVE::Storage::Common::LVM;
 use PVE::JSONSchema qw(get_standard_option);
 
 use base qw(PVE::Storage::Plugin);
 
 # lvm helper functions
 
-my $ignore_no_medium_warnings = sub {
-    my $line = shift;
-    # ignore those, most of the time they're from (virtual) IPMI/iKVM devices
-    # and just spam the log..
-    if ($line !~ /open failed: No medium found/) {
-	print STDERR "$line\n";
-    }
-};
-
 sub lvm_pv_info {
-    my ($device) = @_;
-
-    die "no device specified" if !$device;
-
-    my $has_label = 0;
-
-    my $cmd = ['/usr/bin/file', '-L', '-s', $device];
-    run_command($cmd, outfunc => sub {
-	my $line = shift;
-	$has_label = 1 if $line =~ m/LVM2/;
-    });
-
-    return undef if !$has_label;
-
-    $cmd = ['/sbin/pvs', '--separator', ':', '--noheadings', '--units', 'k',
-	    '--unbuffered', '--nosuffix', '--options',
-	    'pv_name,pv_size,vg_name,pv_uuid', $device];
-
-    my $pvinfo;
-    run_command($cmd, outfunc => sub {
-	my $line = shift;
-
-	$line = trim($line);
-
-	my ($pvname, $size, $vgname, $uuid) = split(':', $line);
-
-	die "found multiple pvs entries for device '$device'\n"
-	    if $pvinfo;
+    warn get_deprecation_warning(
+	'PVE::Storage::Common::LVM::lvm_pv_info'
+    );
 
-	$pvinfo = {
-	    pvname => $pvname,
-	    size => int($size),
-	    vgname => $vgname,
-	    uuid => $uuid,
-	};
-    });
+    my ($device) = @_;
 
-    return $pvinfo;
+    return PVE::Storage::Common::LVM::lvm_pv_info($device);
 }
 
 sub clear_first_sector {
-    my ($dev) = shift;
+    warn get_depreciation_warning(
+	'PVE::Storage::Common::LVM::lvm_clear_first_sector'
+    );
 
-    if (my $fh = IO::File->new($dev, "w")) {
-	my $buf = 0 x 512;
-	syswrite $fh, $buf;
-	$fh->close();
-    }
+    my ($dev) = @_;
+
+    PVE::Storage::Common::LVM::lvm_clear_first_sector($dev);
 }
 
 sub lvm_create_volume_group {
-    my ($device, $vgname, $shared) = @_;
-
-    my $res = lvm_pv_info($device);
-
-    if ($res->{vgname}) {
-	return if $res->{vgname} eq $vgname; # already created
-	die "device '$device' is already used by volume group '$res->{vgname}'\n";
-    }
-
-    clear_first_sector($device); # else pvcreate fails
-
-    # we use --metadatasize 250k, which reseults in "pe_start = 512"
-    # so pe_start is aligned on a 128k boundary (advantage for SSDs)
-    my $cmd = ['/sbin/pvcreate', '--metadatasize', '250k', $device];
-
-    run_command($cmd, errmsg => "pvcreate '$device' error");
+    warn get_depreciation_warning(
+	'PVE::Storage::Common::LVM::lvm_create_volume_group'
+    );
 
-    $cmd = ['/sbin/vgcreate', $vgname, $device];
-    # push @$cmd, '-c', 'y' if $shared; # we do not use this yet
+    my ($device, $vgname, $shared) = @_;
 
-    run_command($cmd, errmsg => "vgcreate $vgname $device error", errfunc => $ignore_no_medium_warnings, outfunc => $ignore_no_medium_warnings);
+    PVE::Storage::Common::LVM::lvm_create_volume_group(
+	$device, $vgname, $shared
+    );
 }
 
 sub lvm_destroy_volume_group {
+    warn get_depreciation_warning(
+	'PVE::Storage::Common::LVM::lvm_destroy_volume_group'
+    );
+
     my ($vgname) = @_;
 
-    run_command(
-	['vgremove', '-y', $vgname],
-	errmsg => "unable to remove volume group $vgname",
-	errfunc => $ignore_no_medium_warnings,
-	outfunc => $ignore_no_medium_warnings,
-    );
+    PVE::Storage::Common::LVM::lvm_destroy_volume_group($vgname);
 }
 
 sub lvm_vgs {
-    my ($includepvs) = @_;
-
-    my $cmd = ['/sbin/vgs', '--separator', ':', '--noheadings', '--units', 'b',
-	       '--unbuffered', '--nosuffix', '--options'];
-
-    my $cols = [qw(vg_name vg_size vg_free lv_count)];
+    warn get_depreciation_warning(
+	'PVE::Storage::Common::LVM::lvm_vgs'
+    );
 
-    if ($includepvs) {
-	push @$cols, qw(pv_name pv_size pv_free);
-    }
+    my ($includepvs) = @_;
 
-    push @$cmd, join(',', @$cols);
+    return PVE::Storage::Common::LVM::lvm_vgs($includepvs);
+}
 
-    my $vgs = {};
-    eval {
-	run_command($cmd, outfunc => sub {
-	    my $line = shift;
-	    $line = trim($line);
+sub lvm_list_volumes {
+    warn get_depreciation_warning(
+	'PVE::Storage::Common::LVM::lvm_list_volumes'
+    );
 
-	    my ($name, $size, $free, $lvcount, $pvname, $pvsize, $pvfree) = split (':', $line);
+    my ($vgname) = @_;
 
-	    $vgs->{$name} //= {
-		size => int ($size),
-		free => int ($free),
-		lvcount => int($lvcount)
-	    };
+    return PVE::Storage::Common::LVM::lvm_list_volumes($vgname);
+}
 
-	    if (defined($pvname) && defined($pvsize) && defined($pvfree)) {
-		push @{$vgs->{$name}->{pvs}}, {
-		    name => $pvname,
-		    size => int($pvsize),
-		    free => int($pvfree),
-		};
-	    }
-	},
-	errfunc => $ignore_no_medium_warnings,
-	);
-    };
-    my $err = $@;
+sub lvcreate {
+    warn get_deprecation_warning(
+	'PVE::Storage::Common::LVM::lvm_lvcreate'
+    );
 
-    # just warn (vgs return error code 5 if clvmd does not run)
-    # but output is still OK (list without clustered VGs)
-    warn $err if $err;
+    my ($vgname, $name, $size, $tags) = @_;
 
-    return $vgs;
+    PVE::Storage::Common::LVM::lvm_lvcreate($vgname, $name, $size, $tags);
 }
 
-sub lvm_list_volumes {
-    my ($vgname) = @_;
-
-    my $option_list = 'vg_name,lv_name,lv_size,lv_attr,pool_lv,data_percent,metadata_percent,snap_percent,uuid,tags,metadata_size,time';
-
-    my $cmd = [
-	'/sbin/lvs', '--separator', ':', '--noheadings', '--units', 'b',
-	'--unbuffered', '--nosuffix',
-	'--config', 'report/time_format="%s"',
-	'--options', $option_list,
-    ];
-
-    push @$cmd, $vgname if $vgname;
-
-    my $lvs = {};
-    run_command($cmd, outfunc => sub {
-	my $line = shift;
-
-	$line = trim($line);
-
-	my ($vg_name, $lv_name, $lv_size, $lv_attr, $pool_lv, $data_percent, $meta_percent, $snap_percent, $uuid, $tags, $meta_size, $ctime) = split(':', $line);
-	return if !$vg_name;
-	return if !$lv_name;
-
-	my $lv_type = substr($lv_attr, 0, 1);
-
-	my $d = {
-	    lv_size => int($lv_size),
-	    lv_state => substr($lv_attr, 4, 1),
-	    lv_type => $lv_type,
-	};
-	$d->{pool_lv} = $pool_lv if $pool_lv;
-	$d->{tags} = $tags if $tags;
-	$d->{ctime} = $ctime;
-
-	if ($lv_type eq 't') {
-	    $data_percent ||= 0;
-	    $meta_percent ||= 0;
-	    $snap_percent ||= 0;
-	    $d->{metadata_size} = int($meta_size);
-	    $d->{metadata_used} = int(($meta_percent * $meta_size)/100);
-	    $d->{used} = int(($data_percent * $lv_size)/100);
-	}
-	$lvs->{$vg_name}->{$lv_name} = $d;
-    },
-    errfunc => $ignore_no_medium_warnings,
+sub lvrename {
+    warn get_deprecation_warning(
+	'PVE::Storage::Common::LVM::lvm_lvrename'
     );
 
-    return $lvs;
+    my ($vgname, $oldname, $newname) = @_;
+
+    PVE::Storage::Common::LVM::lvm_lvrename($vgname, $oldname, $newname);
 }
 
+
 # Configuration
 
 sub type {
@@ -279,7 +170,7 @@ sub on_add_hook {
 
 	PVE::Storage::activate_storage($cfg, $baseid);
 
-	lvm_create_volume_group($path, $scfg->{vgname}, $scfg->{shared});
+	PVE::Storage::Common::LVM::lvm_create_volume_group($path, $scfg->{vgname}, $scfg->{shared});
     }
 
     return;
@@ -328,38 +219,13 @@ sub find_free_diskname {
 
     my $vg = $scfg->{vgname};
 
-    my $lvs = lvm_list_volumes($vg);
+    my $lvs = PVE::Storage::Common::LVM::lvm_list_volumes($vg);
 
     my $disk_list = [ keys %{$lvs->{$vg}} ];
 
     return PVE::Storage::Plugin::get_next_vm_diskname($disk_list, $storeid, $vmid, undef, $scfg);
 }
 
-sub lvcreate {
-    my ($vg, $name, $size, $tags) = @_;
-
-    if ($size =~ m/\d$/) { # no unit is given
-	$size .= "k"; # default to kilobytes
-    }
-
-    my $cmd = ['/sbin/lvcreate', '-aly', '-Wy', '--yes', '--size', $size, '--name', $name];
-    for my $tag (@$tags) {
-	push @$cmd, '--addtag', $tag;
-    }
-    push @$cmd, $vg;
-
-    run_command($cmd, errmsg => "lvcreate '$vg/$name' error");
-}
-
-sub lvrename {
-    my ($vg, $oldname, $newname) = @_;
-
-    run_command(
-	['/sbin/lvrename', $vg, $oldname, $newname],
-	errmsg => "lvrename '${vg}/${oldname}' to '${newname}' error",
-    );
-}
-
 sub alloc_image {
     my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
 
@@ -368,7 +234,7 @@ sub alloc_image {
     die "illegal name '$name' - should be 'vm-$vmid-*'\n"
 	if  $name && $name !~ m/^vm-$vmid-/;
 
-    my $vgs = lvm_vgs();
+    my $vgs = PVE::Storage::Common::LVM::lvm_vgs();
 
     my $vg = $scfg->{vgname};
 
@@ -381,7 +247,7 @@ sub alloc_image {
     $name = $class->find_free_diskname($storeid, $scfg, $vmid)
 	if !$name;
 
-    lvcreate($vg, $name, $size, ["pve-vm-$vmid"]);
+    PVE::Storage::Common::LVM::lvcreate($vg, $name, $size, ["pve-vm-$vmid"]);
 
     return $name;
 }
@@ -452,7 +318,7 @@ sub list_images {
 
     my $vgname = $scfg->{vgname};
 
-    $cache->{lvs} = lvm_list_volumes() if !$cache->{lvs};
+    $cache->{lvs} = PVE::Storage::Common::LVM::lvm_list_volumes() if !$cache->{lvs};
 
     my $res = [];
 
@@ -492,7 +358,7 @@ sub list_images {
 sub status {
     my ($class, $storeid, $scfg, $cache) = @_;
 
-    $cache->{vgs} = lvm_vgs() if !$cache->{vgs};
+    $cache->{vgs} = PVE::Storage::Common::LVM::lvm_vgs() if !$cache->{vgs};
 
     my $vgname = $scfg->{vgname};
 
@@ -506,7 +372,7 @@ sub status {
 sub activate_storage {
     my ($class, $storeid, $scfg, $cache) = @_;
 
-    $cache->{vgs} = lvm_vgs() if !$cache->{vgs};
+    $cache->{vgs} = PVE::Storage::Common::LVM::lvm_vgs() if !$cache->{vgs};
 
     # In LVM2, vgscans take place automatically;
     # this is just to be sure
@@ -669,7 +535,7 @@ sub volume_import {
 	if $file_format ne 'raw';
 
     my $vg = $scfg->{vgname};
-    my $lvs = lvm_list_volumes($vg);
+    my $lvs = PVE::Storage::Common::LVM::lvm_list_volumes($vg);
     if ($lvs->{$vg}->{$volname}) {
 	die "volume $vg/$volname already exists\n" if !$allow_rename;
 	warn "volume $vg/$volname already exists - importing with a different name\n";
@@ -730,7 +596,7 @@ sub rename_volume {
 	if !$target_volname;
 
     my $vg = $scfg->{vgname};
-    my $lvs = lvm_list_volumes($vg);
+    my $lvs = PVE::Storage::Common::LVM::lvm_list_volumes($vg);
     die "target volume '${target_volname}' already exists\n"
 	if ($lvs->{$vg}->{$target_volname});
 
-- 
2.39.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2024-07-17  9:41 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-17  9:39 [pve-devel] [RFC pve-storage 00/36] Refactor / Cleanup of Storage Plugins Max Carrara
2024-07-17  9:39 ` [pve-devel] [RFC pve-storage 01/36] plugin: base: remove old fixme comments Max Carrara
2024-07-17 16:02   ` Thomas Lamprecht
2024-07-18  7:43     ` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 02/36] plugin: btrfs: make plugin-specific helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 03/36] plugin: cephfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 04/36] api: remove unused import of CIFS storage plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 05/36] plugin: cifs: make plugin-specific helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 06/36] api: remove unused import of LVM storage plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 07/36] common: introduce common module Max Carrara
2024-12-13 15:40   ` Fiona Ebner
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 08/36] plugin: dir: move helper subs of directory plugin to common modules Max Carrara
2024-07-17  9:40 ` Max Carrara [this message]
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 10/36] api: replace usages of deprecated LVM helper subs with new ones Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 11/36] plugin: lvmthin: replace usages of deprecated LVM helpers " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 12/36] plugin: lvmthin: move helper that lists thinpools to common LVM module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 13/36] common: lvm: update code style Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 14/36] api: replace usages of deprecated LVM thin pool helper sub Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 15/36] plugin: btrfs: replace deprecated helpers from directory plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 16/36] plugin: dir: factor storage methods into separate common subs Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 17/36] plugin: dir: factor path validity check into helper methods Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 18/36] plugin: btrfs: remove dependency on directory plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 19/36] plugin: cifs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 20/36] plugin: cephfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 21/36] plugin: nfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 22/36] plugin: btrfs: make helper methods private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 23/36] plugin: esxi: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 24/36] plugin: esxi: remove unused helper subroutine `query_vmdk_size` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 25/36] plugin: esxi: make helper methods private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 26/36] plugin: gluster: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 27/36] plugin: iscsi-direct: make helper subroutine `iscsi_ls` private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 28/36] plugin: iscsi: factor helper functions into common module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 29/36] plugin: iscsi: make helper subroutine `iscsi_session` private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 30/36] plugin: lvm: update definition of subroutine `check_tags` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 31/36] plugin: lvmthin: update definition of subroutine `activate_lv` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 32/36] plugin: nfs: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 33/36] plugin: rbd: update private sub signatures and make helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 34/36] common: zfs: introduce module for common ZFS helpers Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 35/36] plugin: zfspool: move helper `zfs_parse_zvol_list` to common module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 36/36] plugin: zfspool: refactor method `zfs_request` into helper subroutine Max Carrara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240717094034.124857-10-m.carrara@proxmox.com \
    --to=m.carrara@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal