diff options
-rw-r--r-- | daemon/lvm.c | 83 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | regressions/Makefile.am | 2 | ||||
-rwxr-xr-x | regressions/test-lvm-mapping.pl | 99 | ||||
-rw-r--r-- | src/MAX_PROC_NR | 2 | ||||
-rwxr-xr-x | src/generator.ml | 42 |
6 files changed, 228 insertions, 1 deletions
diff --git a/daemon/lvm.c b/daemon/lvm.c index b100cd39..82cdf3fb 100644 --- a/daemon/lvm.c +++ b/daemon/lvm.c @@ -512,3 +512,86 @@ do_vgrename (const char *volgroup, const char *newvolgroup) return 0; } + +static char * +get_lvm_field (const char *cmd, const char *field, const char *device) +{ + char *out; + char *err; + int r = command (&out, &err, + "/sbin/lvm", cmd, + "--unbuffered", "--noheadings", "-o", field, + device, NULL); + if (r == -1) { + reply_with_error ("%s: %s", device, err); + free (out); + free (err); + return NULL; + } + + free (err); + + trim (out); + return out; /* Caller frees. */ +} + +char * +do_pvuuid (const char *device) +{ + return get_lvm_field ("pvs", "pv_uuid", device); +} + +char * +do_vguuid (const char *vgname) +{ + return get_lvm_field ("vgs", "vg_uuid", vgname); +} + +char * +do_lvuuid (const char *device) +{ + return get_lvm_field ("lvs", "lv_uuid", device); +} + +static char ** +get_lvm_fields (const char *cmd, const char *field, const char *device) +{ + char *out; + char *err; + int r = command (&out, &err, + "/sbin/lvm", cmd, + "--unbuffered", "--noheadings", "-o", field, + device, NULL); + if (r == -1) { + reply_with_error ("%s: %s", device, err); + free (out); + free (err); + return NULL; + } + + free (err); + + char **ret = split_lines (out); + free (out); + + if (ret == NULL) + return NULL; + + size_t i; + for (i = 0; ret[i] != NULL; ++i) + trim (ret[i]); + + return ret; +} + +char ** +do_vgpvuuids (const char *vgname) +{ + return get_lvm_fields ("vgs", "pv_uuid", vgname); +} + +char ** +do_vglvuuids (const char *vgname) +{ + return get_lvm_fields ("vgs", "lv_uuid", vgname); +} diff --git a/po/POTFILES.in b/po/POTFILES.in index 2caf376c..c88abc57 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -90,6 +90,7 @@ perl/bindtests.pl perl/lib/Sys/Guestfs.pm perl/lib/Sys/Guestfs/Lib.pm python/guestfs-py.c +regressions/test-lvm-mapping.pl regressions/test-noexec-stack.pl ruby/ext/guestfs/_guestfs.c src/guestfs-actions.c diff --git a/regressions/Makefile.am b/regressions/Makefile.am index 4ac0ee0d..2710e824 100644 --- a/regressions/Makefile.am +++ b/regressions/Makefile.am @@ -30,6 +30,7 @@ TESTS = \ test-cancellation-download-librarycancels.sh \ test-cancellation-upload-daemoncancels.sh \ test-find0.sh \ + test-lvm-mapping.pl \ test-noexec-stack.pl \ test-qemudie-killsub.sh \ test-qemudie-midcommand.sh \ @@ -51,6 +52,7 @@ TESTS_ENVIRONMENT = \ MALLOC_PERTURB_=$(random_val) \ LD_LIBRARY_PATH=$(top_builddir)/src/.libs \ LIBGUESTFS_PATH=$(top_builddir)/appliance \ + PERL5LIB=$(top_builddir)/perl/blib/lib:$(top_builddir)/perl/blib/arch \ NOEXEC_CHECK="$(top_builddir)/src/.libs/libguestfs.so $(top_builddir)/daemon/guestfsd" EXTRA_DIST = \ diff --git a/regressions/test-lvm-mapping.pl b/regressions/test-lvm-mapping.pl new file mode 100755 index 00000000..8a38232e --- /dev/null +++ b/regressions/test-lvm-mapping.pl @@ -0,0 +1,99 @@ +#!/usr/bin/perl +# Copyright (C) 2010 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Test the discovery of relationships between LVM PVs, VGs and LVs. + +use strict; +use warnings; + +use Sys::Guestfs; + +my $testimg = "test.img"; + +unlink $testimg; +open FILE, ">$testimg" or die "$testimg: $!"; +truncate FILE, 256*1024*1024 or die "$testimg: truncate: $!"; +close FILE or die "$testimg: $!"; + +my $g = Sys::Guestfs->new (); + +#$g->set_verbose (1); +#$g->set_trace (1); + +$g->add_drive ($testimg); +$g->launch (); + +# Create an arrangement of PVs, VGs and LVs. +$g->sfdiskM ("/dev/sda", [",127", "128,"]); + +$g->pvcreate ("/dev/sda1"); +$g->pvcreate ("/dev/sda2"); +$g->vgcreate ("VG", ["/dev/sda1", "/dev/sda2"]); + +$g->lvcreate ("LV1", "VG", 32); +$g->lvcreate ("LV2", "VG", 32); +$g->lvcreate ("LV3", "VG", 32); + +# Now let's get the arrangement. +my @pvs = $g->pvs (); +my @lvs = $g->lvs (); + +my %pvuuids; +foreach my $pv (@pvs) { + my $uuid = $g->pvuuid ($pv); + $pvuuids{$uuid} = $pv; +} +my %lvuuids; +foreach my $lv (@lvs) { + my $uuid = $g->lvuuid ($lv); + $lvuuids{$uuid} = $lv; +} + +# In this case there is only one VG, called "VG", but in a real +# program you'd want to repeat these steps for each VG that you found. +my @pvuuids_in_VG = $g->vgpvuuids ("VG"); +my @lvuuids_in_VG = $g->vglvuuids ("VG"); + +my @pvs_in_VG; +foreach my $uuid (@pvuuids_in_VG) { + push @pvs_in_VG, $pvuuids{$uuid}; +} +@pvs_in_VG = sort @pvs_in_VG; + +my @lvs_in_VG; +foreach my $uuid (@lvuuids_in_VG) { + push @lvs_in_VG, $lvuuids{$uuid}; +} +@lvs_in_VG = sort @lvs_in_VG; + +unless (@pvs_in_VG == 2 && + $pvs_in_VG[0] eq "/dev/vda1" && $pvs_in_VG[1] eq "/dev/vda2") { + die "unexpected set of PVs for volume group VG: [", + join (", ", @pvs_in_VG), "]\n" +} + +unless (@lvs_in_VG == 3 && + $lvs_in_VG[0] eq "/dev/VG/LV1" && + $lvs_in_VG[1] eq "/dev/VG/LV2" && + $lvs_in_VG[2] eq "/dev/VG/LV3") { + die "unexpected set of LVs for volume group VG: [", + join (", ", @lvs_in_VG), "]\n" +} + +undef $g; + +unlink $testimg or die "$testimg: unlink: $!"; diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 7b473380..f4146713 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -221 +226 diff --git a/src/generator.ml b/src/generator.ml index 83f307b1..fdd228eb 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -4290,6 +4290,48 @@ contained in a Linux initrd or initramfs image: See also C<guestfs_initrd_list>."); + ("pvuuid", (RString "uuid", [Device "device"]), 222, [], + [], + "get the UUID of a physical volume", + "\ +This command returns the UUID of the LVM PV C<device>."); + + ("vguuid", (RString "uuid", [String "vgname"]), 223, [], + [], + "get the UUID of a volume group", + "\ +This command returns the UUID of the LVM VG named C<vgname>."); + + ("lvuuid", (RString "uuid", [Device "device"]), 224, [], + [], + "get the UUID of a logical volume", + "\ +This command returns the UUID of the LVM LV C<device>."); + + ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [], + [], + "get the PV UUIDs containing the volume group", + "\ +Given a VG called C<vgname>, this returns the UUIDs of all +the physical volumes that this volume group resides on. + +You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid> +calls to associate physical volumes and volume groups. + +See also C<guestfs_vglvuuids>."); + + ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [], + [], + "get the LV UUIDs of all LVs in the volume group", + "\ +Given a VG called C<vgname>, this returns the UUIDs of all +the logical volumes created in this volume group. + +You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid> +calls to associate logical volumes and volume groups. + +See also C<guestfs_vgpvuuids>."); + ] let all_functions = non_daemon_functions @ daemon_functions |