[pve-devel] [RFC pve-storage 09/36] plugin: lvm: move LVM helper subroutines into separate common module

Max Carrara m.carrara at proxmox.com
Wed Jul 17 11:40:07 CEST 2024


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 at 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





More information about the pve-devel mailing list