Richard W.M. Jones
2009-Oct-19 11:21 UTC
[Libguestfs] [PATCH 0/5] Add new tools virt-tar and virt-ls and tidy up the tools code
This patch series starts by tidying up the code for the virt-cat, virt-df, virt-edit, etc tools, moving them into a single directory and making the build system much simpler as a consequence. Then we add two new tools, virt-tar (a general purpose archive and upload tool) and virt-ls (for listing directories). No new functionality is enabled by these tools -- that is to say, you can do everything that these tools do using guestfish -- but having separate programs and manual pages for them should make them more accessible for simple tasks to some users. Rich. .gitignore | 7 +- HACKING | 18 +-- Makefile.am | 24 ++-- cat/Makefile.am | 45 ------ cat/run-cat-locally | 52 ------- cat/virt-cat | 194 ------------------------ configure.ac | 25 +--- df/Makefile.am | 45 ------ df/run-df-locally | 52 ------- df/virt-df | 366 --------------------------------------------- edit/Makefile.am | 45 ------ edit/run-edit-locally | 52 ------- edit/virt-edit | 210 -------------------------- guestfish.pod | 4 +- po/POTFILES.in | 10 +- rescue/Makefile.am | 45 ------ rescue/run-rescue-locally | 53 ------- rescue/virt-rescue | 169 --------------------- tools/Makefile.am | 50 ++++++ tools/run-locally | 56 +++++++ tools/virt-cat | 194 ++++++++++++++++++++++++ tools/virt-df | 366 +++++++++++++++++++++++++++++++++++++++++++++ tools/virt-edit | 213 ++++++++++++++++++++++++++ tools/virt-ls | 242 ++++++++++++++++++++++++++++++ tools/virt-rescue | 173 +++++++++++++++++++++ tools/virt-tar | 275 ++++++++++++++++++++++++++++++++++ 26 files changed, 1603 insertions(+), 1382 deletions(-) -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html
Richard W.M. Jones
2009-Oct-19 11:22 UTC
[Libguestfs] [PATCH 1/5] Comment: Describe the build order requirements for toplevel directories.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top -------------- next part -------------->From 854f8e0d5643e55d045f5816a520d49a057990ef Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Mon, 19 Oct 2009 09:10:15 +0100 Subject: [PATCH 1/5] Comment: Describe the build order requirements for toplevel directories. --- Makefile.am | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Makefile.am b/Makefile.am index a7197d4..c4a84f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,6 +20,9 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = gnulib/lib src daemon appliance fish po examples images \ gnulib/tests capitests regressions test-tool +# NB: Must build inspector directory after perl and before ocaml. +# We could relax this if we combined the inspector_generator with +# the ordinary generator, but that brings other problems. if HAVE_PERL SUBDIRS += perl endif -- 1.6.5.rc2
Richard W.M. Jones
2009-Oct-19 11:23 UTC
[Libguestfs] [PATCH 2/5] Move virt tools (virt-cat, virt-edit etc) into tools/ subdirectory.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v -------------- next part -------------->From 945b6e0a085611b45b2ab0752a66e6e60b21666c Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Mon, 19 Oct 2009 10:18:46 +0100 Subject: [PATCH 2/5] Move virt tools (virt-cat, virt-edit etc) into tools/ subdirectory. This moves the tool programs into a single directory: cat/* -> tools/virt-cat df/* -> tools/virt-df edit/* -> tools/virt-edit rescue/* -> tools/virt-rescue This in itself simplifies the build process because we only need one Makefile and one copy of 'run-locally'. 'run-*-locally' has become just 'run-locally' and takes an extra parameter which is the name of the tool, eg: run-locally cat [virt-cat params...] virt-inspector stays in its own directory, because this contains more than just a single Perl script. --- .gitignore | 5 +- HACKING | 18 +-- Makefile.am | 17 +-- cat/Makefile.am | 45 ------ cat/run-cat-locally | 52 ------- cat/virt-cat | 194 ------------------------ configure.ac | 25 +--- df/Makefile.am | 45 ------ df/run-df-locally | 52 ------- df/virt-df | 366 --------------------------------------------- edit/Makefile.am | 45 ------ edit/run-edit-locally | 52 ------- edit/virt-edit | 210 -------------------------- po/POTFILES.in | 8 +- rescue/Makefile.am | 45 ------ rescue/run-rescue-locally | 53 ------- rescue/virt-rescue | 169 --------------------- tools/Makefile.am | 50 ++++++ tools/run-locally | 56 +++++++ tools/virt-cat | 194 ++++++++++++++++++++++++ tools/virt-df | 366 +++++++++++++++++++++++++++++++++++++++++++++ tools/virt-edit | 210 ++++++++++++++++++++++++++ tools/virt-rescue | 169 +++++++++++++++++++++ 23 files changed, 1066 insertions(+), 1380 deletions(-) delete mode 100644 cat/Makefile.am delete mode 100755 cat/run-cat-locally delete mode 100755 cat/virt-cat delete mode 100644 df/Makefile.am delete mode 100755 df/run-df-locally delete mode 100755 df/virt-df delete mode 100644 edit/Makefile.am delete mode 100755 edit/run-edit-locally delete mode 100755 edit/virt-edit delete mode 100644 rescue/Makefile.am delete mode 100755 rescue/run-rescue-locally delete mode 100755 rescue/virt-rescue create mode 100644 tools/Makefile.am create mode 100755 tools/run-locally create mode 100755 tools/virt-cat create mode 100755 tools/virt-df create mode 100755 tools/virt-edit create mode 100755 tools/virt-rescue diff --git a/.gitignore b/.gitignore index 508f13a..4467a63 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,6 @@ capitests/test*.img capitests/tests capitests/tests.c capitests/test*.tmp -cat/virt-cat.1 ChangeLog *.class *.cma @@ -47,8 +46,6 @@ daemon/names.c daemon/stubs.c depcomp .deps -df/virt-df.1 -edit/virt-edit.1 emptydisk examples/hello examples/to-xml @@ -179,7 +176,6 @@ python/guestfs.py python/guestfs-py.c python/guestfs.pyc regressions/test1.img -rescue/virt-rescue.1 ruby/bindtests.rb ruby/ext/guestfs/extconf.h ruby/ext/guestfs/_guestfs.c @@ -201,6 +197,7 @@ stamp-h1 test-tool/libguestfs-test-tool.1 test-tool/libguestfs-test-tool test-tool/libguestfs-test-tool-helper +tools/virt-*.1 /GNUmakefile /maint.mk /build-aux diff --git a/HACKING b/HACKING index bdb8287..ca5b9a9 100644 --- a/HACKING +++ b/HACKING @@ -68,9 +68,6 @@ Directories appliance/ The qemu appliance, build scripts and so on. -cat/ - The virt-cat tool. - capitests/ Automated tests of the C API. @@ -80,12 +77,6 @@ contrib/ daemon/ The daemon that runs inside the guest and carries out actions. -df/ - The virt-df tool. - -edit/ - The virt-edit tool. - examples/ The examples. @@ -125,12 +116,15 @@ python/ regressions/ Regression tests. -rescue/ - The virt-rescue tool. - ruby/ Ruby bindings. +tools/ + Command line tools like virt-cat, virt-df, virt-edit and more. + In versions <= 1.0.73 these were all in separate directories + like cat/, df/, edit/, but since then we moved them all into + one directory to simplify builds. + src/ Source code to the C library. Also contains the crucial generator program. diff --git a/Makefile.am b/Makefile.am index c4a84f7..73d4f63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,9 +26,14 @@ SUBDIRS = gnulib/lib src daemon appliance fish po examples images \ if HAVE_PERL SUBDIRS += perl endif + if HAVE_INSPECTOR SUBDIRS += inspector endif +if HAVE_TOOLS +SUBDIRS += tools +endif + if HAVE_OCAML SUBDIRS += ocaml ocaml/examples endif @@ -44,18 +49,6 @@ endif if HAVE_HASKELL SUBDIRS += haskell endif -if HAVE_DF -SUBDIRS += df -endif -if HAVE_CAT -SUBDIRS += cat -endif -if HAVE_RESCUE -SUBDIRS += rescue -endif -if HAVE_EDIT -SUBDIRS += edit -endif EXTRA_DIST = \ guestfs.pod guestfs-actions.pod guestfs-structs.pod \ diff --git a/cat/Makefile.am b/cat/Makefile.am deleted file mode 100644 index 6b9a1bb..0000000 --- a/cat/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# libguestfs virt-cat -# Copyright (C) 2009 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. - -EXTRA_DIST = \ - run-cat-locally \ - virt-cat - -if HAVE_CAT - -bin_SCRIPTS = virt-cat -man_MANS = virt-cat.1 - -noinst_DATA = $(top_builddir)/html/virt-cat.1.html - -virt-cat.1: virt-cat - $(POD2MAN) \ - --section 1 \ - -c "Virtualization Support" \ - --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - $< > $@-t && mv $@-t $@ - -$(top_builddir)/html/virt-cat.1.html: virt-cat - mkdir -p $(top_builddir)/html - cd $(top_builddir) && pod2html \ - --css 'pod.css' \ - --title 'virt-cat, display a file in a virtual machine' \ - --htmldir html \ - --outfile html/virt-cat.1.html \ - cat/$< - -endif diff --git a/cat/run-cat-locally b/cat/run-cat-locally deleted file mode 100755 index 7c31aaf..0000000 --- a/cat/run-cat-locally +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/perl -# virt-cat -# Copyright (C) 2009 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. - -# This script sets up the environment so you can run virt-cat in place -# without needing to do 'make install' first. You can also run virt-cat -# by creating a symlink to this script and putting it in your path. -# -# Use it like this: -# ./run-cat-locally [usual virt-cat args ...] - -use strict; -use warnings; - -use File::Basename qw(dirname); -use File::Spec; -use Cwd qw(abs_path); - -my $path = $0; - -# Follow symlinks until we get to the real file -while(-l $path) { - my $link = readlink($path) or die "readlink: $path: $!"; - if(File::Spec->file_name_is_absolute($link)) { - $path = $link; - } else { - $path = File::Spec->catfile(dirname($path), $link); - } -} - -# Get the absolute path of the parent directory -$path = abs_path(dirname($path).'/..'); - -$ENV{LD_LIBRARY_PATH} = $path.'/src/.libs'; -$ENV{LIBGUESTFS_PATH} = $path.'/appliance'; -$ENV{PERL5LIB} = $path.'/perl/blib/lib:'.$path.'/perl/blib/arch'; - -exec('perl', $path.'/cat/virt-cat', @ARGV); diff --git a/cat/virt-cat b/cat/virt-cat deleted file mode 100755 index 329ba6e..0000000 --- a/cat/virt-cat +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/perl -w -# virt-cat -# Copyright (C) 2009 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. - -use warnings; -use strict; - -use Sys::Guestfs; -use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path - inspect_all_partitions inspect_partition - inspect_operating_systems mount_operating_system); -use Pod::Usage; -use Getopt::Long; -use Locale::TextDomain 'libguestfs'; - -=encoding utf8 - -=head1 NAME - -virt-cat - Display a file in a virtual machine - -=head1 SYNOPSIS - - virt-cat [--options] domname file - - virt-cat [--options] disk.img [disk.img ...] file - -=head1 DESCRIPTION - -C<virt-cat> is a command line tool to display the contents of C<file> -where C<file> exists in the named virtual machine (or disk image). - -C<virt-cat> can be used to quickly view a single file. To edit a -file, use C<virt-edit>. For more complex cases you should look at the -L<guestfish(1)> tool. - -=head1 EXAMPLES - -Display C</etc/fstab> file from inside the libvirt VM called -C<mydomain>: - - virt-cat mydomain /etc/fstab - -List syslog messages from a VM: - - virt-cat mydomain /var/log/messages | tail - -Find out what DHCP IP address a VM acquired: - - virt-cat mydomain /var/log/messages | grep 'dhclient: bound to' | tail - -Find out what packages were recently installed: - - virt-cat mydomain /var/log/yum.log | tail - -Find out who is logged on inside a virtual machine: - - virt-cat mydomain /var/run/utmp > /tmp/utmp - who /tmp/utmp - -or who was logged on: - - virt-cat mydomain /var/log/wtmp > /tmp/wtmp - last -f /tmp/wtmp - -=head1 OPTIONS - -=over 4 - -=cut - -my $help; - -=item B<--help> - -Display brief help. - -=cut - -my $version; - -=item B<--version> - -Display version number and exit. - -=cut - -my $uri; - -=item B<--connect URI> | B<-c URI> - -If using libvirt, connect to the given I<URI>. If omitted, then we -connect to the default libvirt hypervisor. - -If you specify guest block devices directly, then libvirt is not used -at all. - -=back - -=cut - -GetOptions ("help|?" => \$help, - "version" => \$version, - "connect|c=s" => \$uri, - ) or pod2usage (2); -pod2usage (1) if $help; -if ($version) { - my $g = Sys::Guestfs->new (); - my %h = $g->version (); - print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; - exit -} - -pod2usage (__"virt-cat: no image, VM names or filenames to cat given") - if @ARGV <= 1; - -my $filename = pop @ARGV; - -my $g; -if ($uri) { - $g = open_guest (\@ARGV, address => $uri); -} else { - $g = open_guest (\@ARGV); -} - -$g->launch (); - -# List of possible filesystems. -my @partitions = get_partitions ($g); - -# Now query each one to build up a picture of what's in it. -my %fses - inspect_all_partitions ($g, \@partitions, - use_windows_registry => 0); - -my $oses = inspect_operating_systems ($g, \%fses); - -my @roots = keys %$oses; -die __"no root device found in this operating system image" if @roots == 0; -die __"multiboot operating systems are not supported by virt-cat" if @roots > 1; -my $root_dev = $roots[0]; - -my $os = $oses->{$root_dev}; -mount_operating_system ($g, $os); - -# Allow this to fail in case eg. the file does not exist. -# NB: https://bugzilla.redhat.com/show_bug.cgi?id=501888 -print $g->download($filename, "/dev/stdout"); - -=head1 SEE ALSO - -L<guestfs(3)>, -L<guestfish(1)>, -L<virt-edit(1)>, -L<Sys::Guestfs(3)>, -L<Sys::Guestfs::Lib(3)>, -L<Sys::Virt(3)>, -L<http://libguestfs.org/>. - -=head1 AUTHOR - -Richard W.M. Jones L<http://et.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009 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. diff --git a/configure.ac b/configure.ac index 2d4cd33..ab42561 100644 --- a/configure.ac +++ b/configure.ac @@ -675,18 +675,12 @@ for pm in Pod::Usage Getopt::Long Sys::Virt Data::Dumper XML::Writer Locale::Tex fi done if test "x$missing_perl_modules" = "xyes"; then - AC_MSG_WARN([some Perl modules required to compile virt-cat, virt-df, virt-edit, virt-inspector and virt-rescue are missing]) + AC_MSG_WARN([some Perl modules required to compile virt-inspector and the other virt-* tools are missing]) fi -AM_CONDITIONAL([HAVE_CAT], - [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"]) -AM_CONDITIONAL([HAVE_DF], - [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"]) -AM_CONDITIONAL([HAVE_EDIT], - [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"]) AM_CONDITIONAL([HAVE_INSPECTOR], [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"]) -AM_CONDITIONAL([HAVE_RESCUE], +AM_CONDITIONAL([HAVE_TOOLS], [test "x$PERL" != "xno" -a "x$missing_perl_modules" != "xyes"]) dnl Library versioning. @@ -723,11 +717,8 @@ AC_CONFIG_FILES([Makefile ruby/Makefile ruby/Rakefile java/Makefile haskell/Makefile - cat/Makefile - df/Makefile - edit/Makefile inspector/Makefile - rescue/Makefile + tools/Makefile libguestfs.pc gnulib/lib/Makefile gnulib/tests/Makefile @@ -755,16 +746,10 @@ echo -n "Java bindings ....................... " if test "x$HAVE_JAVA_TRUE" = "x"; then echo "yes"; else echo "no"; fi echo -n "Haskell bindings .................... " if test "x$HAVE_HASKELL" = "x"; then echo "yes"; else echo "no"; fi -echo -n "virt-cat ............................ " -if test "x$HAVE_CAT" = "x"; then echo "yes"; else echo "no"; fi -echo -n "virt-df ............................. " -if test "x$HAVE_DF" = "x"; then echo "yes"; else echo "no"; fi -echo -n "virt-edit ........................... " -if test "x$HAVE_EDIT" = "x"; then echo "yes"; else echo "no"; fi echo -n "virt-inspector ...................... " if test "x$HAVE_INSPECTOR" = "x"; then echo "yes"; else echo "no"; fi -echo -n "virt-rescue ......................... " -if test "x$HAVE_RESCUE" = "x"; then echo "yes"; else echo "no"; fi +echo -n "virt-* tools ........................ " +if test "x$HAVE_TOOLS" = "x"; then echo "yes"; else echo "no"; fi echo "supermin appliance .................. $enable_supermin" echo echo "If any optional component is configured 'no' when you expected 'yes'" diff --git a/df/Makefile.am b/df/Makefile.am deleted file mode 100644 index f333f97..0000000 --- a/df/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# libguestfs virt-df -# Copyright (C) 2009 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. - -EXTRA_DIST = \ - run-df-locally \ - virt-df - -if HAVE_DF - -bin_SCRIPTS = virt-df -man_MANS = virt-df.1 - -noinst_DATA = $(top_builddir)/html/virt-df.1.html - -virt-df.1: virt-df - $(POD2MAN) \ - --section 1 \ - -c "Virtualization Support" \ - --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - $< > $@-t && mv $@-t $@ - -$(top_builddir)/html/virt-df.1.html: virt-df - mkdir -p $(top_builddir)/html - cd $(top_builddir) && pod2html \ - --css 'pod.css' \ - --title 'virt-df, display free space on virtual filesystems' \ - --htmldir html \ - --outfile html/virt-df.1.html \ - df/$< - -endif diff --git a/df/run-df-locally b/df/run-df-locally deleted file mode 100755 index 94697b0..0000000 --- a/df/run-df-locally +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/perl -# virt-df -# Copyright (C) 2009 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. - -# This script sets up the environment so you can run virt-df in place -# without needing to do 'make install' first. You can also run virt-df -# by creating a symlink to this script and putting it in your path. -# -# Use it like this: -# ./run-df-locally [usual virt-df args ...] - -use strict; -use warnings; - -use File::Basename qw(dirname); -use File::Spec; -use Cwd qw(abs_path); - -my $path = $0; - -# Follow symlinks until we get to the real file -while(-l $path) { - my $link = readlink($path) or die "readlink: $path: $!"; - if(File::Spec->file_name_is_absolute($link)) { - $path = $link; - } else { - $path = File::Spec->catfile(dirname($path), $link); - } -} - -# Get the absolute path of the parent directory -$path = abs_path(dirname($path).'/..'); - -$ENV{LD_LIBRARY_PATH} = $path.'/src/.libs'; -$ENV{LIBGUESTFS_PATH} = $path.'/appliance'; -$ENV{PERL5LIB} = $path.'/perl/blib/lib:'.$path.'/perl/blib/arch'; - -exec('perl', $path.'/df/virt-df', @ARGV); diff --git a/df/virt-df b/df/virt-df deleted file mode 100755 index 78eb25c..0000000 --- a/df/virt-df +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/perl -w -# virt-df -# Copyright (C) 2009 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. - -use warnings; -use strict; - -use Sys::Guestfs; -use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path - inspect_all_partitions inspect_partition - inspect_operating_systems mount_operating_system inspect_in_detail); -use Pod::Usage; -use Getopt::Long; -use Data::Dumper; -use File::Temp qw/tempdir/; -use XML::Writer; -use Locale::TextDomain 'libguestfs'; - -=encoding utf8 - -=head1 NAME - -virt-df - Display free space on virtual filesystems - -=head1 SYNOPSIS - - virt-df [--options] - - virt-df [--options] domname - - virt-df [--options] disk.img [disk.img ...] - -=head1 DESCRIPTION - -C<virt-df> is a command line tool to display free space on virtual -machine filesystems. Unlike other tools, it doesn't just display the -amount of space allocated to a virtual machine, but can look inside -the virtual machine to see how much space is really being used. - -It is like the L<df(1)> command, but for virtual machines, except that -it also works for Windows virtual machines. - -If used without any arguments, C<virt-df> checks with libvirt to get a -list of all active and inactive guests, and performs a C<df>-type -operation on each one in turn, printing out the results. - -If used with any argument(s), C<virt-df> performs a C<df>-type -operation on either the single named libvirt domain, or on the disk -image(s) listed on the command line (which must all belong to a single -VM). In this mode (with arguments), C<virt-df> will I<only work for a -single guest>. If you want to run on multiple guests, then you have -to invoke C<virt-df> multiple times. - -Use the C<--csv> option to get a format which can be easily parsed by -other programs. Other options are mostly similar to standard C<df> -options. See below for the complete list. - -=head1 OPTIONS - -=over 4 - -=cut - -my $help; - -=item B<--help> - -Display brief help. - -=cut - -my $version; - -=item B<--version> - -Display version number and exit. - -=cut - -my $uri; - -=item B<--connect URI> | B<-c URI> - -If using libvirt, connect to the given I<URI>. If omitted, then we -connect to the default libvirt hypervisor. - -If you specify guest block devices directly, then libvirt is not used -at all. - -=cut - -my $csv; - -=item B<--csv> - -Write out the results in CSV format (comma-separated values). This -format can be imported easily into databases and spreadsheets, but -read L</NOTE ABOUT CSV FORMAT> below. - -=cut - -my $human; - -=item B<--human-readable> | B<-h> - -Print sizes in human-readable format. - -=cut - -my $inodes; - -=item B<--inodes> | B<-i> - -Print inodes instead of blocks. - -=back - -=cut - -GetOptions ("help|?" => \$help, - "version" => \$version, - "connect|c=s" => \$uri, - "csv" => \$csv, - "human-readable|human|h" => \$human, - "inodes|i" => \$inodes, - ) or pod2usage (2); -pod2usage (1) if $help; -if ($version) { - my $g = Sys::Guestfs->new (); - my %h = $g->version (); - print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; - exit -} - -# Open the guest handle. - -if (@ARGV == 0) { - my $conn; - - if ($uri) { - $conn = Sys::Virt->new (readonly => 1, address => $uri); - } else { - $conn = Sys::Virt->new (readonly => 1); - } - - my @doms = $conn->list_defined_domains (); - push @doms, $conn->list_domains (); - - my @domnames = map { $_->get_name () } @doms; - - if (@domnames) { - print_title (); - foreach (@domnames) { - do_df ($_); - } - } -} else { - print_title (); - do_df (@ARGV); -} - -sub do_df -{ - my $g; - - if ($uri) { - $g = open_guest (\@_, address => $uri); - } else { - $g = open_guest (\@_); - } - - $g->launch (); - - my @partitions = get_partitions ($g); - - # Think of a printable name for this domain. Just choose the - # first parameter passed to this function, which will work for - # most cases (it'll either be the domain name or the first disk - # image name). - my $domname = $_[0]; - - # Mount each partition in turn, and if mountable, do a statvfs on it. - foreach my $partition (@partitions) { - my %stat; - eval { - $g->mount_ro ($partition, "/"); - %stat = $g->statvfs ("/"); - }; - if (!$@) { - print_stat ($domname, $partition, \%stat); - } - $g->umount_all (); - } -} - -sub print_stat -{ - my $domname = shift; - my $partition = shift; - my $stat = shift; - - my @cols = ($domname, $partition); - - if (!$inodes) { - my $bsize = $stat->{bsize}; # block size - my $blocks = $stat->{blocks}; # total number of blocks - my $bfree = $stat->{bfree}; # blocks free (total) - my $bavail = $stat->{bavail}; # blocks free (for non-root users) - - my $factor = $bsize / 1024; - - push @cols, $blocks*$factor; # total 1K blocks - push @cols, ($blocks-$bfree)*$factor; # total 1K blocks used - push @cols, $bavail*$factor; # total 1K blocks available - - # XXX %used column comes out different from the native 'df' - # program. Need to check how 'df' calculates this. - push @cols, 100.0 - 100.0 * $bavail / $blocks; - - if ($human) { - $cols[2] = human_size ($cols[2]); - $cols[3] = human_size ($cols[3]); - $cols[4] = human_size ($cols[4]); - } - } else { - my $files = $stat->{files}; # total number of inodes - my $ffree = $stat->{ffree}; # inodes free (total) - my $favail = $stat->{favail}; # inodes free (for non-root users) - - push @cols, $files; - push @cols, $files-$ffree; - push @cols, $ffree; - - # XXX %used column comes out different from the native 'df' - # program. Need to check how 'df' calculates this. - push @cols, 100.0 - 100.0 * $favail / $files; - } - - print_cols (@cols); -} - -sub print_title -{ - my @cols = (__"Virtual Machine", __"Filesystem"); - if (!$inodes) { - if (!$human) { - push @cols, __"1K-blocks"; - } else { - push @cols, __"Size"; - } - push @cols, __"Used"; - push @cols, __"Available"; - push @cols, __"Use%"; - } else { - push @cols, __"Inodes"; - push @cols, __"IUsed"; - push @cols, __"IFree"; - push @cols, __"IUse%"; - } - - if (!$csv) { - # ignore $cols[0] in this mode - printf "%-36s%10s %10s %10s %5s\n", - $cols[1], $cols[2], $cols[3], $cols[4], $cols[5]; - } else { - print (join (",", @cols), "\n"); - } -} - -sub print_cols -{ - if (!$csv) { - my $label = sprintf "%s:%s", $_[0], $_[1]; - - printf ("%-36s", $label); - print "\n"," "x36 if length ($label) > 36; - - my $percent = sprintf "%3.1f%%", $_[5]; - printf ("%10s %10s %10s %5s\n", $_[2], $_[3], $_[4], $percent); - } else { - printf ("\"%s\",\"%s\",%d,%d,%d,%.1f%%\n", @_); - } -} - -# Convert a number of 1K blocks to a human-readable number. -sub human_size -{ - local $_ = shift; - - if ($_ < 1024) { - sprintf "%dK", $_; - } elsif ($_ < 1024 * 1024) { - sprintf "%.1fM", ($_ / 1024); - } else { - sprintf "%.1fG", ($_ / 1024 / 1024); - } -} - -=head1 NOTE ABOUT CSV FORMAT - -Comma-separated values (CSV) is a deceptive format. It I<seems> like -it should be easy to parse, but it is definitely not easy to parse. - -Myth: Just split fields at commas. Reality: This does I<not> work -reliably. This example has two columns: - - "foo,bar",baz - -Myth: Read the file one line at a time. Reality: This does I<not> -work reliably. This example has one row: - - "foo - bar",baz - -For shell scripts, use C<csvtool> (L<http://merjis.com/developers/csv> -also packaged in major Linux distributions). - -For other languages, use a CSV processing library (eg. C<Text::CSV> -for Perl or Python's built-in csv library). - -Most spreadsheets and databases can import CSV directly. - -=head1 SEE ALSO - -L<guestfs(3)>, -L<guestfish(1)>, -L<Sys::Guestfs(3)>, -L<Sys::Guestfs::Lib(3)>, -L<Sys::Virt(3)>, -L<http://libguestfs.org/>. - -=head1 AUTHOR - -Richard W.M. Jones L<http://et.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009 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. diff --git a/edit/Makefile.am b/edit/Makefile.am deleted file mode 100644 index 6afdd62..0000000 --- a/edit/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# libguestfs virt-edit -# Copyright (C) 2009 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. - -EXTRA_DIST = \ - run-edit-locally \ - virt-edit - -if HAVE_EDIT - -bin_SCRIPTS = virt-edit -man_MANS = virt-edit.1 - -noinst_DATA = $(top_builddir)/html/virt-edit.1.html - -virt-edit.1: virt-edit - $(POD2MAN) \ - --section 1 \ - -c "Virtualization Support" \ - --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - $< > $@-t && mv $@-t $@ - -$(top_builddir)/html/virt-edit.1.html: virt-edit - mkdir -p $(top_builddir)/html - cd $(top_builddir) && pod2html \ - --css 'pod.css' \ - --title 'virt-edit, edit a file in a virtual machine' \ - --htmldir html \ - --outfile html/virt-edit.1.html \ - edit/$< - -endif diff --git a/edit/run-edit-locally b/edit/run-edit-locally deleted file mode 100755 index 127463f..0000000 --- a/edit/run-edit-locally +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/perl -# virt-edit -# Copyright (C) 2009 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. - -# This script sets up the environment so you can run virt-edit in place -# without needing to do 'make install' first. You can also run virt-edit -# by creating a symlink to this script and putting it in your path. -# -# Use it like this: -# ./run-edit-locally [usual virt-edit args ...] - -use strict; -use warnings; - -use File::Basename qw(dirname); -use File::Spec; -use Cwd qw(abs_path); - -my $path = $0; - -# Follow symlinks until we get to the real file -while(-l $path) { - my $link = readlink($path) or die "readlink: $path: $!"; - if(File::Spec->file_name_is_absolute($link)) { - $path = $link; - } else { - $path = File::Spec->catfile(dirname($path), $link); - } -} - -# Get the absolute path of the parent directory -$path = abs_path(dirname($path).'/..'); - -$ENV{LD_LIBRARY_PATH} = $path.'/src/.libs'; -$ENV{LIBGUESTFS_PATH} = $path.'/appliance'; -$ENV{PERL5LIB} = $path.'/perl/blib/lib:'.$path.'/perl/blib/arch'; - -exec('perl', $path.'/edit/virt-edit', @ARGV); diff --git a/edit/virt-edit b/edit/virt-edit deleted file mode 100755 index 46e86a1..0000000 --- a/edit/virt-edit +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/perl -w -# virt-edit -# Copyright (C) 2009 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. - -use warnings; -use strict; - -use Sys::Guestfs; -use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path - inspect_all_partitions inspect_partition - inspect_operating_systems mount_operating_system); -use Pod::Usage; -use Getopt::Long; -use File::Temp qw/tempfile/; -use Locale::TextDomain 'libguestfs'; - -=encoding utf8 - -=head1 NAME - -virt-edit - Edit a file in a virtual machine - -=head1 SYNOPSIS - - virt-edit [--options] domname file - - virt-edit [--options] disk.img [disk.img ...] file - -=head1 DESCRIPTION - -C<virt-edit> is a command line tool to edit C<file> where C<file> -exists in the named virtual machine (or disk image). - -B<Note> you must I<not> use virt-edit on live virtual machines. If -you do this, you risk disk corruption in the VM. - -If you want to just view a file, use L<virt-cat(1)>. For more complex -cases you should look at the L<guestfish(1)> tool. - -=head1 EXAMPLES - - virt-edit mydomain /boot/grub/grub.conf - - virt-edit mydomain /etc/passwd - -=head1 OPTIONS - -=over 4 - -=cut - -my $help; - -=item B<--help> - -Display brief help. - -=cut - -my $version; - -=item B<--version> - -Display version number and exit. - -=cut - -my $uri; - -=item B<--connect URI> | B<-c URI> - -If using libvirt, connect to the given I<URI>. If omitted, then we -connect to the default libvirt hypervisor. - -If you specify guest block devices directly, then libvirt is not used -at all. - -=back - -=cut - -GetOptions ("help|?" => \$help, - "version" => \$version, - "connect|c=s" => \$uri, - ) or pod2usage (2); -pod2usage (1) if $help; -if ($version) { - my $g = Sys::Guestfs->new (); - my %h = $g->version (); - print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; - exit -} - -pod2usage (__"virt-edit: no image, VM names or filenames to edit given") - if @ARGV <= 1; - -my $filename = pop @ARGV; - -my $g; -if ($uri) { - $g = open_guest (\@ARGV, address => $uri, rw => 1); -} else { - $g = open_guest (\@ARGV, rw => 1); -} - -$g->launch (); - -# List of possible filesystems. -my @partitions = get_partitions ($g); - -# Now query each one to build up a picture of what's in it. -my %fses - inspect_all_partitions ($g, \@partitions, - use_windows_registry => 0); - -my $oses = inspect_operating_systems ($g, \%fses); - -my @roots = keys %$oses; -die __"no root device found in this operating system image" if @roots == 0; -die __"multiboot operating systems are not supported by virt-edit" if @roots > 1; -my $root_dev = $roots[0]; - -my $os = $oses->{$root_dev}; -mount_operating_system ($g, $os, 0); - -my ($fh, $tempname) = tempfile (); - -# Allow this to fail in case eg. the file does not exist. -$g->download($filename, $tempname); - -my $oldctime = (stat ($tempname))[10]; - -my $editor = $ENV{EDITOR}; -$editor ||= "vi"; -system ("$editor $tempname") == 0 - or die "edit failed: $editor: $?"; - -my $newctime = (stat ($tempname))[10]; - -if ($oldctime != $newctime) { - $g->upload ($tempname, $filename) -} else { - print __"File not changed.\n"; -} - -$g->sync (); -$g->umount_all (); - -undef $g; - -exit 0; - -=head1 ENVIRONMENT VARIABLES - -=over 4 - -=item C<EDITOR> - -If set, this string is used as the editor. It may contain arguments, -eg. C<"emacs -nw"> - -If not set, C<vi> is used. - -=back - -=head1 SEE ALSO - -L<guestfs(3)>, -L<guestfish(1)>, -L<virt-cat(1)>, -L<Sys::Guestfs(3)>, -L<Sys::Guestfs::Lib(3)>, -L<Sys::Virt(3)>, -L<http://libguestfs.org/>. - -=head1 AUTHOR - -Richard W.M. Jones L<http://et.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009 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. diff --git a/po/POTFILES.in b/po/POTFILES.in index 7ccadcf..b99493b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,3 @@ -cat/virt-cat daemon/augeas.c daemon/blockdev.c daemon/checksum.c @@ -55,8 +54,6 @@ daemon/wc.c daemon/xattr.c daemon/zero.c daemon/zerofree.c -df/virt-df -edit/virt-edit fish/alloc.c fish/cmds.c fish/completion.c @@ -81,10 +78,13 @@ perl/lib/Sys/Guestfs.pm perl/lib/Sys/Guestfs/Lib.pm python/guestfs-py.c regressions/test-noexec-stack.pl -rescue/virt-rescue ruby/ext/guestfs/_guestfs.c src/guestfs-actions.c src/guestfs-bindtests.c src/guestfs.c test-tool/helper.c test-tool/test-tool.c +tools/virt-cat +tools/virt-df +tools/virt-edit +tools/virt-rescue diff --git a/rescue/Makefile.am b/rescue/Makefile.am deleted file mode 100644 index b532e25..0000000 --- a/rescue/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# libguestfs virt-rescue -# Copyright (C) 2009 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. - -EXTRA_DIST = \ - run-rescue-locally \ - virt-rescue - -if HAVE_RESCUE - -bin_SCRIPTS = virt-rescue -man_MANS = virt-rescue.1 - -noinst_DATA = $(top_builddir)/html/virt-rescue.1.html - -virt-rescue.1: virt-rescue - $(POD2MAN) \ - --section 1 \ - -c "Virtualization Support" \ - --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - $< > $@-t && mv $@-t $@ - -$(top_builddir)/html/virt-rescue.1.html: virt-rescue - mkdir -p $(top_builddir)/html - cd $(top_builddir) && pod2html \ - --css 'pod.css' \ - --title 'virt-rescue, run a rescue shell on a virtual machine' \ - --htmldir html \ - --outfile html/virt-rescue.1.html \ - rescue/$< - -endif diff --git a/rescue/run-rescue-locally b/rescue/run-rescue-locally deleted file mode 100755 index 18097cf..0000000 --- a/rescue/run-rescue-locally +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -# virt-rescue -# Copyright (C) 2009 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. - -# This script sets up the environment so you can run virt-rescue in -# place without needing to do 'make install' first. You can also run -# virt-rescue by creating a symlink to this script and putting it in -# your path. -# -# Use it like this: -# ./run-rescue-locally [usual virt-rescue args ...] - -use strict; -use warnings; - -use File::Basename qw(dirname); -use File::Spec; -use Cwd qw(abs_path); - -my $path = $0; - -# Follow symlinks until we get to the real file -while(-l $path) { - my $link = readlink($path) or die "readlink: $path: $!"; - if(File::Spec->file_name_is_absolute($link)) { - $path = $link; - } else { - $path = File::Spec->catfile(dirname($path), $link); - } -} - -# Get the absolute path of the parent directory -$path = abs_path(dirname($path).'/..'); - -$ENV{LD_LIBRARY_PATH} = $path.'/src/.libs'; -$ENV{LIBGUESTFS_PATH} = $path.'/appliance'; -$ENV{PERL5LIB} = $path.'/perl/blib/lib:'.$path.'/perl/blib/arch'; - -exec('perl', $path.'/rescue/virt-rescue', @ARGV); diff --git a/rescue/virt-rescue b/rescue/virt-rescue deleted file mode 100755 index 9ad2fa4..0000000 --- a/rescue/virt-rescue +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/perl -w -# virt-rescue -# Copyright (C) 2009 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. - -use warnings; -use strict; - -use Sys::Guestfs; -use Sys::Guestfs::Lib qw(open_guest); -use Pod::Usage; -use Getopt::Long; -use Locale::TextDomain 'libguestfs'; - -=encoding utf8 - -=head1 NAME - -virt-rescue - Run a rescue shell on a virtual machine - -=head1 SYNOPSIS - - virt-rescue [--options] domname - - virt-rescue [--options] disk.img [disk.img ...] - -=head1 DESCRIPTION - -virt-rescue gives you a rescue shell and some simple recovery tools -which you can use on a virtual machine disk image. - -After running virt-rescue, what you see under C</> is the recovery -appliance. You must mount the virtual machine's filesystems by hand, -eg: - - # lvs - LV VG Attr LSize Origin Snap% Move Log Copy% Convert - lv_root vg_f11x64 -wi-a- 8.83G - lv_swap vg_f11x64 -wi-a- 992.00M - # mount /dev/vg_f11x64/lv_root /sysroot - # ls /sysroot - -B<Note> that the virtual machine must not be powered on when you use -this tool. Doing so will probably result in disk corruption in the -VM. However if you use the I<--ro> (read only) option, then you can -attach a shell to a running machine, but the results might be strange -or inconsistent. - -This tool is just designed for quick interactive hacking on a virtual -machine. For more structured access to a virtual machine disk image, -you should use L<guestfs(3)>. To get a structured shell, use -L<guestfish(1)>. - -=head1 OPTIONS - -=over 4 - -=cut - -my $help; - -=item B<--help> - -Display brief help. - -=cut - -my $version; - -=item B<--version> - -Display version number and exit. - -=cut - -my $uri; - -=item B<--connect URI> | B<-c URI> - -If using libvirt, connect to the given I<URI>. If omitted, then we -connect to the default libvirt hypervisor. - -If you specify guest block devices directly, then libvirt is not used -at all. - -=cut - -my $readonly; - -=item B<--ro> | B<-r> - -Open the image read-only. - -=back - -=cut - -GetOptions ("help|?" => \$help, - "version" => \$version, - "connect|c=s" => \$uri, - "ro|r" => \$readonly, - ) or pod2usage (2); -pod2usage (1) if $help; -if ($version) { - my $g = Sys::Guestfs->new (); - my %h = $g->version (); - print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; - exit -} - -pod2usage (__"virt-rescue: no image or VM names rescue given") - if @ARGV == 0; - -my @args = (\@ARGV); -push @args, address => $uri if $uri; -push @args, rw => 1 unless $readonly; -my $g = open_guest (@args); - -$g->set_direct (1); -$g->set_append ("guestfs_rescue=1"); - -$g->launch (); - -exit 0; - -=head1 SEE ALSO - -L<guestfs(3)>, -L<guestfish(1)>, -L<virt-cat(1)>, -L<Sys::Guestfs(3)>, -L<Sys::Guestfs::Lib(3)>, -L<Sys::Virt(3)>, -L<http://libguestfs.org/>. - -=head1 AUTHOR - -Richard W.M. Jones L<http://et.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009 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. diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..d5fc23c --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,50 @@ +# libguestfs virt-* tools +# Copyright (C) 2009 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. + +tools = cat df edit rescue + +EXTRA_DIST = \ + run-locally \ + $(tools:%=virt-%) + +if HAVE_TOOLS + +bin_SCRIPTS = $(tools:%=virt-%) + +# XXX Bug in automake? If you list virt-cat.1 explicitly, then it +# builds and installs the man pages. However if this is removed, +# then the man pages are neither built nor installed. +man_MANS = virt-cat.1 $(patsubst %,virt-%.1,$(filter-out cat,$(tools))) + +noinst_DATA = $(tools:%=$(top_builddir)/html/virt-%.1.html) + +virt-%.1: virt-% + $(POD2MAN) \ + --section 1 \ + -c "Virtualization Support" \ + --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ + $< > $@-t && mv $@-t $@ + +$(top_builddir)/html/virt-%.1.html: virt-% + mkdir -p $(top_builddir)/html + cd $(top_builddir) && pod2html \ + --css 'pod.css' \ + --htmldir html \ + --outfile html/$<.1.html \ + tools/$< + +endif diff --git a/tools/run-locally b/tools/run-locally new file mode 100755 index 0000000..0bf1c0a --- /dev/null +++ b/tools/run-locally @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# Copyright (C) 2009 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. + +# This script sets up the environment so you can run virt-* tools in +# place without needing to do 'make install' first. You can also run +# the tools by creating a symlink to this script and putting it in +# your path. +# +# Use it like this: +# ./run-locally tool [usual virt-tool args ...] +# eg: +# ./run-locally cat domname /etc/passwd + +use strict; +use warnings; + +use File::Basename qw(dirname); +use File::Spec; +use Cwd qw(abs_path); + +my $path = $0; +my $tool = shift @ARGV; + +# Follow symlinks until we get to the real file +while(-l $path) { + my $link = readlink($path) or die "readlink: $path: $!"; + if(File::Spec->file_name_is_absolute($link)) { + $path = $link; + } else { + $path = File::Spec->catfile(dirname($path), $link); + } +} + +# Get the absolute path of the parent directory +$path = abs_path(dirname($path).'/..'); + +$ENV{LD_LIBRARY_PATH} = $path.'/src/.libs'; +$ENV{LIBGUESTFS_PATH} = $path.'/appliance'; +$ENV{PERL5LIB} = $path.'/perl/blib/lib:'.$path.'/perl/blib/arch'; + +print (join " ", ("$path/tools/virt-$tool", @ARGV), "\n"); +exec('perl', "$path/tools/virt-$tool", @ARGV); diff --git a/tools/virt-cat b/tools/virt-cat new file mode 100755 index 0000000..329ba6e --- /dev/null +++ b/tools/virt-cat @@ -0,0 +1,194 @@ +#!/usr/bin/perl -w +# virt-cat +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path + inspect_all_partitions inspect_partition + inspect_operating_systems mount_operating_system); +use Pod::Usage; +use Getopt::Long; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-cat - Display a file in a virtual machine + +=head1 SYNOPSIS + + virt-cat [--options] domname file + + virt-cat [--options] disk.img [disk.img ...] file + +=head1 DESCRIPTION + +C<virt-cat> is a command line tool to display the contents of C<file> +where C<file> exists in the named virtual machine (or disk image). + +C<virt-cat> can be used to quickly view a single file. To edit a +file, use C<virt-edit>. For more complex cases you should look at the +L<guestfish(1)> tool. + +=head1 EXAMPLES + +Display C</etc/fstab> file from inside the libvirt VM called +C<mydomain>: + + virt-cat mydomain /etc/fstab + +List syslog messages from a VM: + + virt-cat mydomain /var/log/messages | tail + +Find out what DHCP IP address a VM acquired: + + virt-cat mydomain /var/log/messages | grep 'dhclient: bound to' | tail + +Find out what packages were recently installed: + + virt-cat mydomain /var/log/yum.log | tail + +Find out who is logged on inside a virtual machine: + + virt-cat mydomain /var/run/utmp > /tmp/utmp + who /tmp/utmp + +or who was logged on: + + virt-cat mydomain /var/log/wtmp > /tmp/wtmp + last -f /tmp/wtmp + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=back + +=cut + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +pod2usage (__"virt-cat: no image, VM names or filenames to cat given") + if @ARGV <= 1; + +my $filename = pop @ARGV; + +my $g; +if ($uri) { + $g = open_guest (\@ARGV, address => $uri); +} else { + $g = open_guest (\@ARGV); +} + +$g->launch (); + +# List of possible filesystems. +my @partitions = get_partitions ($g); + +# Now query each one to build up a picture of what's in it. +my %fses + inspect_all_partitions ($g, \@partitions, + use_windows_registry => 0); + +my $oses = inspect_operating_systems ($g, \%fses); + +my @roots = keys %$oses; +die __"no root device found in this operating system image" if @roots == 0; +die __"multiboot operating systems are not supported by virt-cat" if @roots > 1; +my $root_dev = $roots[0]; + +my $os = $oses->{$root_dev}; +mount_operating_system ($g, $os); + +# Allow this to fail in case eg. the file does not exist. +# NB: https://bugzilla.redhat.com/show_bug.cgi?id=501888 +print $g->download($filename, "/dev/stdout"); + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<virt-edit(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. diff --git a/tools/virt-df b/tools/virt-df new file mode 100755 index 0000000..78eb25c --- /dev/null +++ b/tools/virt-df @@ -0,0 +1,366 @@ +#!/usr/bin/perl -w +# virt-df +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path + inspect_all_partitions inspect_partition + inspect_operating_systems mount_operating_system inspect_in_detail); +use Pod::Usage; +use Getopt::Long; +use Data::Dumper; +use File::Temp qw/tempdir/; +use XML::Writer; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-df - Display free space on virtual filesystems + +=head1 SYNOPSIS + + virt-df [--options] + + virt-df [--options] domname + + virt-df [--options] disk.img [disk.img ...] + +=head1 DESCRIPTION + +C<virt-df> is a command line tool to display free space on virtual +machine filesystems. Unlike other tools, it doesn't just display the +amount of space allocated to a virtual machine, but can look inside +the virtual machine to see how much space is really being used. + +It is like the L<df(1)> command, but for virtual machines, except that +it also works for Windows virtual machines. + +If used without any arguments, C<virt-df> checks with libvirt to get a +list of all active and inactive guests, and performs a C<df>-type +operation on each one in turn, printing out the results. + +If used with any argument(s), C<virt-df> performs a C<df>-type +operation on either the single named libvirt domain, or on the disk +image(s) listed on the command line (which must all belong to a single +VM). In this mode (with arguments), C<virt-df> will I<only work for a +single guest>. If you want to run on multiple guests, then you have +to invoke C<virt-df> multiple times. + +Use the C<--csv> option to get a format which can be easily parsed by +other programs. Other options are mostly similar to standard C<df> +options. See below for the complete list. + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=cut + +my $csv; + +=item B<--csv> + +Write out the results in CSV format (comma-separated values). This +format can be imported easily into databases and spreadsheets, but +read L</NOTE ABOUT CSV FORMAT> below. + +=cut + +my $human; + +=item B<--human-readable> | B<-h> + +Print sizes in human-readable format. + +=cut + +my $inodes; + +=item B<--inodes> | B<-i> + +Print inodes instead of blocks. + +=back + +=cut + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + "csv" => \$csv, + "human-readable|human|h" => \$human, + "inodes|i" => \$inodes, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +# Open the guest handle. + +if (@ARGV == 0) { + my $conn; + + if ($uri) { + $conn = Sys::Virt->new (readonly => 1, address => $uri); + } else { + $conn = Sys::Virt->new (readonly => 1); + } + + my @doms = $conn->list_defined_domains (); + push @doms, $conn->list_domains (); + + my @domnames = map { $_->get_name () } @doms; + + if (@domnames) { + print_title (); + foreach (@domnames) { + do_df ($_); + } + } +} else { + print_title (); + do_df (@ARGV); +} + +sub do_df +{ + my $g; + + if ($uri) { + $g = open_guest (\@_, address => $uri); + } else { + $g = open_guest (\@_); + } + + $g->launch (); + + my @partitions = get_partitions ($g); + + # Think of a printable name for this domain. Just choose the + # first parameter passed to this function, which will work for + # most cases (it'll either be the domain name or the first disk + # image name). + my $domname = $_[0]; + + # Mount each partition in turn, and if mountable, do a statvfs on it. + foreach my $partition (@partitions) { + my %stat; + eval { + $g->mount_ro ($partition, "/"); + %stat = $g->statvfs ("/"); + }; + if (!$@) { + print_stat ($domname, $partition, \%stat); + } + $g->umount_all (); + } +} + +sub print_stat +{ + my $domname = shift; + my $partition = shift; + my $stat = shift; + + my @cols = ($domname, $partition); + + if (!$inodes) { + my $bsize = $stat->{bsize}; # block size + my $blocks = $stat->{blocks}; # total number of blocks + my $bfree = $stat->{bfree}; # blocks free (total) + my $bavail = $stat->{bavail}; # blocks free (for non-root users) + + my $factor = $bsize / 1024; + + push @cols, $blocks*$factor; # total 1K blocks + push @cols, ($blocks-$bfree)*$factor; # total 1K blocks used + push @cols, $bavail*$factor; # total 1K blocks available + + # XXX %used column comes out different from the native 'df' + # program. Need to check how 'df' calculates this. + push @cols, 100.0 - 100.0 * $bavail / $blocks; + + if ($human) { + $cols[2] = human_size ($cols[2]); + $cols[3] = human_size ($cols[3]); + $cols[4] = human_size ($cols[4]); + } + } else { + my $files = $stat->{files}; # total number of inodes + my $ffree = $stat->{ffree}; # inodes free (total) + my $favail = $stat->{favail}; # inodes free (for non-root users) + + push @cols, $files; + push @cols, $files-$ffree; + push @cols, $ffree; + + # XXX %used column comes out different from the native 'df' + # program. Need to check how 'df' calculates this. + push @cols, 100.0 - 100.0 * $favail / $files; + } + + print_cols (@cols); +} + +sub print_title +{ + my @cols = (__"Virtual Machine", __"Filesystem"); + if (!$inodes) { + if (!$human) { + push @cols, __"1K-blocks"; + } else { + push @cols, __"Size"; + } + push @cols, __"Used"; + push @cols, __"Available"; + push @cols, __"Use%"; + } else { + push @cols, __"Inodes"; + push @cols, __"IUsed"; + push @cols, __"IFree"; + push @cols, __"IUse%"; + } + + if (!$csv) { + # ignore $cols[0] in this mode + printf "%-36s%10s %10s %10s %5s\n", + $cols[1], $cols[2], $cols[3], $cols[4], $cols[5]; + } else { + print (join (",", @cols), "\n"); + } +} + +sub print_cols +{ + if (!$csv) { + my $label = sprintf "%s:%s", $_[0], $_[1]; + + printf ("%-36s", $label); + print "\n"," "x36 if length ($label) > 36; + + my $percent = sprintf "%3.1f%%", $_[5]; + printf ("%10s %10s %10s %5s\n", $_[2], $_[3], $_[4], $percent); + } else { + printf ("\"%s\",\"%s\",%d,%d,%d,%.1f%%\n", @_); + } +} + +# Convert a number of 1K blocks to a human-readable number. +sub human_size +{ + local $_ = shift; + + if ($_ < 1024) { + sprintf "%dK", $_; + } elsif ($_ < 1024 * 1024) { + sprintf "%.1fM", ($_ / 1024); + } else { + sprintf "%.1fG", ($_ / 1024 / 1024); + } +} + +=head1 NOTE ABOUT CSV FORMAT + +Comma-separated values (CSV) is a deceptive format. It I<seems> like +it should be easy to parse, but it is definitely not easy to parse. + +Myth: Just split fields at commas. Reality: This does I<not> work +reliably. This example has two columns: + + "foo,bar",baz + +Myth: Read the file one line at a time. Reality: This does I<not> +work reliably. This example has one row: + + "foo + bar",baz + +For shell scripts, use C<csvtool> (L<http://merjis.com/developers/csv> +also packaged in major Linux distributions). + +For other languages, use a CSV processing library (eg. C<Text::CSV> +for Perl or Python's built-in csv library). + +Most spreadsheets and databases can import CSV directly. + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. diff --git a/tools/virt-edit b/tools/virt-edit new file mode 100755 index 0000000..46e86a1 --- /dev/null +++ b/tools/virt-edit @@ -0,0 +1,210 @@ +#!/usr/bin/perl -w +# virt-edit +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path + inspect_all_partitions inspect_partition + inspect_operating_systems mount_operating_system); +use Pod::Usage; +use Getopt::Long; +use File::Temp qw/tempfile/; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-edit - Edit a file in a virtual machine + +=head1 SYNOPSIS + + virt-edit [--options] domname file + + virt-edit [--options] disk.img [disk.img ...] file + +=head1 DESCRIPTION + +C<virt-edit> is a command line tool to edit C<file> where C<file> +exists in the named virtual machine (or disk image). + +B<Note> you must I<not> use virt-edit on live virtual machines. If +you do this, you risk disk corruption in the VM. + +If you want to just view a file, use L<virt-cat(1)>. For more complex +cases you should look at the L<guestfish(1)> tool. + +=head1 EXAMPLES + + virt-edit mydomain /boot/grub/grub.conf + + virt-edit mydomain /etc/passwd + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=back + +=cut + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +pod2usage (__"virt-edit: no image, VM names or filenames to edit given") + if @ARGV <= 1; + +my $filename = pop @ARGV; + +my $g; +if ($uri) { + $g = open_guest (\@ARGV, address => $uri, rw => 1); +} else { + $g = open_guest (\@ARGV, rw => 1); +} + +$g->launch (); + +# List of possible filesystems. +my @partitions = get_partitions ($g); + +# Now query each one to build up a picture of what's in it. +my %fses + inspect_all_partitions ($g, \@partitions, + use_windows_registry => 0); + +my $oses = inspect_operating_systems ($g, \%fses); + +my @roots = keys %$oses; +die __"no root device found in this operating system image" if @roots == 0; +die __"multiboot operating systems are not supported by virt-edit" if @roots > 1; +my $root_dev = $roots[0]; + +my $os = $oses->{$root_dev}; +mount_operating_system ($g, $os, 0); + +my ($fh, $tempname) = tempfile (); + +# Allow this to fail in case eg. the file does not exist. +$g->download($filename, $tempname); + +my $oldctime = (stat ($tempname))[10]; + +my $editor = $ENV{EDITOR}; +$editor ||= "vi"; +system ("$editor $tempname") == 0 + or die "edit failed: $editor: $?"; + +my $newctime = (stat ($tempname))[10]; + +if ($oldctime != $newctime) { + $g->upload ($tempname, $filename) +} else { + print __"File not changed.\n"; +} + +$g->sync (); +$g->umount_all (); + +undef $g; + +exit 0; + +=head1 ENVIRONMENT VARIABLES + +=over 4 + +=item C<EDITOR> + +If set, this string is used as the editor. It may contain arguments, +eg. C<"emacs -nw"> + +If not set, C<vi> is used. + +=back + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<virt-cat(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. diff --git a/tools/virt-rescue b/tools/virt-rescue new file mode 100755 index 0000000..9ad2fa4 --- /dev/null +++ b/tools/virt-rescue @@ -0,0 +1,169 @@ +#!/usr/bin/perl -w +# virt-rescue +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest); +use Pod::Usage; +use Getopt::Long; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-rescue - Run a rescue shell on a virtual machine + +=head1 SYNOPSIS + + virt-rescue [--options] domname + + virt-rescue [--options] disk.img [disk.img ...] + +=head1 DESCRIPTION + +virt-rescue gives you a rescue shell and some simple recovery tools +which you can use on a virtual machine disk image. + +After running virt-rescue, what you see under C</> is the recovery +appliance. You must mount the virtual machine's filesystems by hand, +eg: + + # lvs + LV VG Attr LSize Origin Snap% Move Log Copy% Convert + lv_root vg_f11x64 -wi-a- 8.83G + lv_swap vg_f11x64 -wi-a- 992.00M + # mount /dev/vg_f11x64/lv_root /sysroot + # ls /sysroot + +B<Note> that the virtual machine must not be powered on when you use +this tool. Doing so will probably result in disk corruption in the +VM. However if you use the I<--ro> (read only) option, then you can +attach a shell to a running machine, but the results might be strange +or inconsistent. + +This tool is just designed for quick interactive hacking on a virtual +machine. For more structured access to a virtual machine disk image, +you should use L<guestfs(3)>. To get a structured shell, use +L<guestfish(1)>. + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=cut + +my $readonly; + +=item B<--ro> | B<-r> + +Open the image read-only. + +=back + +=cut + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + "ro|r" => \$readonly, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +pod2usage (__"virt-rescue: no image or VM names rescue given") + if @ARGV == 0; + +my @args = (\@ARGV); +push @args, address => $uri if $uri; +push @args, rw => 1 unless $readonly; +my $g = open_guest (@args); + +$g->set_direct (1); +$g->set_append ("guestfs_rescue=1"); + +$g->launch (); + +exit 0; + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<virt-cat(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. -- 1.6.5.rc2
Richard W.M. Jones
2009-Oct-19 11:24 UTC
[Libguestfs] [PATCH 3/5] tools: Make warnings about running on live guests more prominent.
A timely warning not to try running certain tools on live VMs. Sys::Guestfs::Lib detects this some of the time, but can't do it always. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v -------------- next part -------------->From 5c4bf92bc298e078ceccdde603313282d038544c Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Mon, 19 Oct 2009 10:45:44 +0100 Subject: [PATCH 3/5] tools: Make warnings about running on live guests more prominent. Add prominent warnings to the man pages about how it is dangerous to run these tools against live guests. --- tools/virt-edit | 9 ++++++--- tools/virt-rescue | 16 ++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tools/virt-edit b/tools/virt-edit index 46e86a1..9196a66 100755 --- a/tools/virt-edit +++ b/tools/virt-edit @@ -40,14 +40,17 @@ virt-edit - Edit a file in a virtual machine virt-edit [--options] disk.img [disk.img ...] file +=head1 WARNING + +You must I<not> use C<virt-edit> on live virtual machines. If you do +this, you risk disk corruption in the VM. C<virt-edit> tries to stop +you from doing this, but doesn't catch all cases. + =head1 DESCRIPTION C<virt-edit> is a command line tool to edit C<file> where C<file> exists in the named virtual machine (or disk image). -B<Note> you must I<not> use virt-edit on live virtual machines. If -you do this, you risk disk corruption in the VM. - If you want to just view a file, use L<virt-cat(1)>. For more complex cases you should look at the L<guestfish(1)> tool. diff --git a/tools/virt-rescue b/tools/virt-rescue index 9ad2fa4..4f90ab1 100755 --- a/tools/virt-rescue +++ b/tools/virt-rescue @@ -37,6 +37,16 @@ virt-rescue - Run a rescue shell on a virtual machine virt-rescue [--options] disk.img [disk.img ...] +=head1 WARNING + +You must I<not> use C<virt-rescue> on live virtual machines. Doing so +will probably result in disk corruption in the VM. C<virt-rescue> +tries to stop you from doing this, but doesn't catch all cases. + +However if you use the I<--ro> (read only) option, then you can attach +a shell to a live virtual machine, but the results might be strange or +inconsistent at times (but you won't get disk corruption). + =head1 DESCRIPTION virt-rescue gives you a rescue shell and some simple recovery tools @@ -53,12 +63,6 @@ eg: # mount /dev/vg_f11x64/lv_root /sysroot # ls /sysroot -B<Note> that the virtual machine must not be powered on when you use -this tool. Doing so will probably result in disk corruption in the -VM. However if you use the I<--ro> (read only) option, then you can -attach a shell to a running machine, but the results might be strange -or inconsistent. - This tool is just designed for quick interactive hacking on a virtual machine. For more structured access to a virtual machine disk image, you should use L<guestfs(3)>. To get a structured shell, use -- 1.6.5.rc2
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora -------------- next part -------------->From 7172960b56b1636c53f23192c0aae48f6463bdc5 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Mon, 19 Oct 2009 11:49:20 +0100 Subject: [PATCH 4/5] New tool: virt-tar This adds a new tool call virt-tar which is a general purpose archive and uploading tool. It doesn't add any functionality which wasn't previously possible using guestfish, but makes it simpler to access for some users. Examples: virt-tar -zx myguest /home home.tar.gz virt-tar -zu myguest /tmp uploadstuff.tar.gz --- .gitignore | 1 + Makefile.am | 3 +- guestfish.pod | 3 +- po/POTFILES.in | 1 + tools/Makefile.am | 2 +- tools/virt-tar | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 282 insertions(+), 3 deletions(-) create mode 100755 tools/virt-tar diff --git a/.gitignore b/.gitignore index 4467a63..507f9f1 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ html/virt-df.1.html html/virt-edit.1.html html/virt-inspector.1.html html/virt-rescue.1.html +html/virt-tar.1.html images/100kallnewlines images/100kallspaces images/100kallzeroes diff --git a/Makefile.am b/Makefile.am index 73d4f63..f4d4dd1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,7 +168,8 @@ all-local: -name 'virt-df' -o \ -name 'virt-edit' -o \ -name 'virt-inspector' -o \ - -name 'virt-rescue' | \ + -name 'virt-rescue' -o \ + -name 'virt-tar' | \ grep -v '^perl/blib/' | \ grep -v '^capitests/' | \ grep -v '^daemon/lib/' | \ diff --git a/guestfish.pod b/guestfish.pod index cf45c6e..66d9914 100644 --- a/guestfish.pod +++ b/guestfish.pod @@ -604,7 +604,8 @@ L<guestfs(3)>, L<http://libguestfs.org/>, L<virt-cat(1)>, L<virt-edit(1)>, -L<virt-rescue(1)>. +L<virt-rescue(1)>, +L<virt-tar(1)>. =head1 AUTHORS diff --git a/po/POTFILES.in b/po/POTFILES.in index b99493b..2017c5f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -88,3 +88,4 @@ tools/virt-cat tools/virt-df tools/virt-edit tools/virt-rescue +tools/virt-tar diff --git a/tools/Makefile.am b/tools/Makefile.am index d5fc23c..b6f95d2 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -tools = cat df edit rescue +tools = cat df edit rescue tar EXTRA_DIST = \ run-locally \ diff --git a/tools/virt-tar b/tools/virt-tar new file mode 100755 index 0000000..508d467 --- /dev/null +++ b/tools/virt-tar @@ -0,0 +1,275 @@ +#!/usr/bin/perl -w +# virt-tar +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path + inspect_all_partitions inspect_partition + inspect_operating_systems mount_operating_system); +use Pod::Usage; +use Getopt::Long; +use File::Temp qw/tempfile/; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-tar - Extract or upload files to a virtual machine + +=head1 SYNOPSIS + + virt-tar [--options] domname directory file + + virt-tar [--options] disk.img [disk.img ...] directory file + +=head1 EXAMPLES + +Download C</home> from the VM into a local tarball: + + virt-tar -x domname /home home.tar + + virt-tar -zx domname /home home.tar.gz + +Upload a local tarball and unpack it inside C</tmp> in the VM: + + virt-tar -u domname /tmp uploadstuff.tar + + virt-tar -zu domname /tmp uploadstuff.tar.gz + +=head1 WARNING + +You must I<not> use C<virt-tar> with the C<-u> option (upload) on live +virtual machines. If you do this, you risk disk corruption in the VM. +C<virt-tar> tries to stop you from doing this, but doesn't catch all +cases. + +You can use C<-x> (extract) on live virtual machines, but you might +get inconsistent results or errors if there is filesystem activity +inside the VM. If the live VM is synched and quiescent, then +C<virt-tar> will usually work, but the only way to guarantee +consistent results is if the virtual machine is shut down. + +=head1 DESCRIPTION + +C<virt-tar> is a general purpose archive tool for downloading and +uploading parts of a guest filesystem. There are many possibilities: +making backups, uploading data files, snooping on guest activity, +fixing or customizing guests, etc. + +If you want to just view a single file, use L<virt-cat(1)>. If you +just want to edit a single file, use L<virt-edit(1)>. For more +complex cases you should look at the L<guestfish(1)> tool. + +There are two modes of operation: C<-x> (eXtract) downloads a +directory and its contents (recursively) from the virtual machine into +a local tarball. C<-u> uploads from a local tarball, unpacking it +into a directory inside the virtual machine. You cannot use these two +options together. + +In addition, you may need to use the C<-z> (gZip) option to enable +compression. When uploading, you have to specify C<-z> if the upload +file is compressed because virt-tar won't detect this on its own. + +C<virt-tar> can only handle tar (optionally gzipped) format tarballs. +For example it cannot do PKZip files or bzip2 compression. If you +want that then you'll have to rebuild the tarballs yourself. (This is +a limitation of the L<libguestfs(3)> API). + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=cut + +my $mode; + +=item B<-x> | B<--extract> | B<--download> + +=item B<-u> | B<--upload> + +Use C<-x> to extract (download) a directory from a virtual machine +to a local tarball. + +Use C<-u> to upload and unpack from a local tarball into a virtual +machine. Please read the L</WARNING> section above before using this +option. + +You must specify exactly one of these options. + +=cut + +my $gzip; + +=item B<-z> | B<--gzip> + +Specify that the input or output tarball is gzip-compressed. + +=back + +=cut + +sub set_mode_x +{ + die __"virt-tar: extract/upload mode specified twice on the command line" + if $mode; + $mode = "x"; +} + +sub set_mode_u +{ + die __"virt-tar: extract/upload mode specified twice on the command line" + if $mode; + $mode = "u"; +} + +Getopt::Long::Configure ("bundling"); +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + "extract|download|x" => \&set_mode_x, + "upload|u" => \&set_mode_u, + "gzip|z" => \$gzip, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +pod2usage (__"virt-tar: no image, VM names, directory or filename given") + if @ARGV <= 2; + +# 'pop' reads arguments right to left. +my $tarball = pop @ARGV; +my $directory = pop @ARGV; + +die __"virt-tar: either -x or -u must be specified on the command line" + unless $mode; + +my @args = (\@ARGV); +push @args, address => $uri if $uri; +push @args, rw => 1 if $mode eq "u"; + +my $g = open_guest (@args); +$g->launch (); + +# List of possible filesystems. +my @partitions = get_partitions ($g); + +# Now query each one to build up a picture of what's in it. +my %fses + inspect_all_partitions ($g, \@partitions, + use_windows_registry => 0); + +my $oses = inspect_operating_systems ($g, \%fses); + +my @roots = keys %$oses; +die __"no root device found in this operating system image" if @roots == 0; +die __"multiboot operating systems are not supported by virt-edit" if @roots > 1; +my $root_dev = $roots[0]; + +my $os = $oses->{$root_dev}; +mount_operating_system ($g, $os, $mode eq "u" ? 0 : 1); + +# Do the tar command. +if ($mode eq "x") { + if ($gzip) { + $g->tgz_out ($directory, $tarball); + } else { + $g->tar_out ($directory, $tarball); + } +} else { # mode eq "u" + if ($gzip) { + $g->tgz_in ($tarball, $directory); + } else { + $g->tar_in ($tarball, $directory); + } +} + +$g->sync (); +$g->umount_all (); + +undef $g; + +exit 0; + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<virt-cat(1)>, +L<virt-edit(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. -- 1.6.5.rc2
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html -------------- next part -------------->From f4b9f87106d1d4525d78b02a89dfea69aeccc1f1 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at redhat.com> Date: Mon, 19 Oct 2009 12:16:00 +0100 Subject: [PATCH 5/5] New tool: virt-ls This tool makes available the functionality of "ls", "ll", and "find" in a slightly simpler to use form. Examples: virt-ls -l myguest /tmp --- .gitignore | 1 + Makefile.am | 1 + guestfish.pod | 1 + po/POTFILES.in | 1 + tools/Makefile.am | 2 +- tools/virt-ls | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 247 insertions(+), 1 deletions(-) create mode 100755 tools/virt-ls diff --git a/.gitignore b/.gitignore index 507f9f1..3c3b956 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ html/virt-cat.1.html html/virt-df.1.html html/virt-edit.1.html html/virt-inspector.1.html +html/virt-ls.1.html html/virt-rescue.1.html html/virt-tar.1.html images/100kallnewlines diff --git a/Makefile.am b/Makefile.am index f4d4dd1..9663449 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,6 +168,7 @@ all-local: -name 'virt-df' -o \ -name 'virt-edit' -o \ -name 'virt-inspector' -o \ + -name 'virt-ls' -o \ -name 'virt-rescue' -o \ -name 'virt-tar' | \ grep -v '^perl/blib/' | \ diff --git a/guestfish.pod b/guestfish.pod index 66d9914..e4b2333 100644 --- a/guestfish.pod +++ b/guestfish.pod @@ -604,6 +604,7 @@ L<guestfs(3)>, L<http://libguestfs.org/>, L<virt-cat(1)>, L<virt-edit(1)>, +L<virt-ls(1)>, L<virt-rescue(1)>, L<virt-tar(1)>. diff --git a/po/POTFILES.in b/po/POTFILES.in index 2017c5f..57cce91 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -87,5 +87,6 @@ test-tool/test-tool.c tools/virt-cat tools/virt-df tools/virt-edit +tools/virt-ls tools/virt-rescue tools/virt-tar diff --git a/tools/Makefile.am b/tools/Makefile.am index b6f95d2..f593d46 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -tools = cat df edit rescue tar +tools = cat df edit ls rescue tar EXTRA_DIST = \ run-locally \ diff --git a/tools/virt-ls b/tools/virt-ls new file mode 100755 index 0000000..e900389 --- /dev/null +++ b/tools/virt-ls @@ -0,0 +1,242 @@ +#!/usr/bin/perl -w +# virt-ls +# Copyright (C) 2009 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. + +use warnings; +use strict; + +use Sys::Guestfs; +use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path + inspect_all_partitions inspect_partition + inspect_operating_systems mount_operating_system); +use Pod::Usage; +use Getopt::Long; +use Locale::TextDomain 'libguestfs'; + +=encoding utf8 + +=head1 NAME + +virt-ls - List files in a virtual machine + +=head1 SYNOPSIS + + virt-ls [--options] domname directory + + virt-ls [--options] disk.img [disk.img ...] directory + +=head1 DESCRIPTION + +C<virt-ls> is a command line tool to list the names of files in a +directory inside a virtual machine or disk image. + +C<virt-ls> is just a simple wrapper around L<libguestfs(3)> +functionality. For more complex cases you should look at the +L<guestfish(1)> tool. + +C<virt-ls> can be used in one of three modes: simple, long and +recursive. A simple listing is like the ordinary L<ls(1)> command: + + $ virt-ls myguest / + bin + boot + [etc.] + +With the C<-l> (C<--long>) option, C<virt-ls> shows more detail: + + $ virt-ls -l myguest / + total 204 + dr-xr-xr-x. 2 root root 4096 2009-08-25 19:06 bin + dr-xr-xr-x. 5 root root 3072 2009-08-25 19:06 boot + [etc.] + +With the C<-R> (C<--recursive>) option, C<virt-ls> lists the +names of files and directories recursively: + + $ virt-ls -R myguest /tmp + foo + foo/bar + [etc.] + +You I<cannot> combine these options. To do more complicated things, +use L<guestfish(1)>. + +=head1 OPTIONS + +=over 4 + +=cut + +my $help; + +=item B<--help> + +Display brief help. + +=cut + +my $version; + +=item B<--version> + +Display version number and exit. + +=cut + +my $uri; + +=item B<--connect URI> | B<-c URI> + +If using libvirt, connect to the given I<URI>. If omitted, then we +connect to the default libvirt hypervisor. + +If you specify guest block devices directly, then libvirt is not used +at all. + +=cut + +my $mode; + +=item B<-l> | B<--long> + +=item B<-R> | B<--recursive> + +Select the mode. With neither of these options, C<virt-ls> +produces a simple, flat list of the files in the named directory. + +C<virt-ls -l> produces a "long listing", which shows more detail (just +like the plain C<ls -l> command). + +C<virt-ls -R> produces a recursive list of files starting at the named +directory. See the documentation for the C<guestfs_find> command +L<guestfs(3)> for precise details. + +You cannot combine these options. + +=back + +=cut + +sub set_mode_l +{ + die __"virt-ls: cannot combine -l and -R options" if $mode; + $mode = "l"; +} + +sub set_mode_R +{ + die __"virt-ls: cannot combine -l and -R options" if $mode; + $mode = "R"; +} + +GetOptions ("help|?" => \$help, + "version" => \$version, + "connect|c=s" => \$uri, + "long|l" => \&set_mode_l, + "recursive|R" => \&set_mode_R, + ) or pod2usage (2); +pod2usage (1) if $help; +if ($version) { + my $g = Sys::Guestfs->new (); + my %h = $g->version (); + print "$h{major}.$h{minor}.$h{release}$h{extra}\n"; + exit +} + +pod2usage (__"virt-ls: no image, VM names or directory to list given") + if @ARGV <= 1; + +my $directory = pop @ARGV; + +my $g; +if ($uri) { + $g = open_guest (\@ARGV, address => $uri); +} else { + $g = open_guest (\@ARGV); +} + +$g->launch (); + +# List of possible filesystems. +my @partitions = get_partitions ($g); + +# Now query each one to build up a picture of what's in it. +my %fses + inspect_all_partitions ($g, \@partitions, + use_windows_registry => 0); + +my $oses = inspect_operating_systems ($g, \%fses); + +my @roots = keys %$oses; +die __"no root device found in this operating system image" if @roots == 0; +die __"multiboot operating systems are not supported by virt-cat" if @roots > 1; +my $root_dev = $roots[0]; + +my $os = $oses->{$root_dev}; +mount_operating_system ($g, $os); + +my @r; +unless ($mode) { + @r = $g->ls ($directory); + print "$_\n" foreach @r; +} elsif ($mode eq "l") { + print ($g->ll ($directory)); +} else { # $mode eq "R" + @r = $g->find ($directory); + print "$_\n" foreach @r; +} + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<virt-cat(1)>, +L<virt-tar(1)>, +L<Sys::Guestfs(3)>, +L<Sys::Guestfs::Lib(3)>, +L<Sys::Virt(3)>, +L<http://libguestfs.org/>. + +=head1 BUGS + +C<virt-ls -R myguest /> may fail with an error if there are lots of +files. The reason is a limitation of the L<libguestfs(3)> API: the +complete list of file names must be able to fit in a single RPC +message, and there is a message size limit of (currently) around 2-4 +MB. + +=head1 AUTHOR + +Richard W.M. Jones L<http://et.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2009 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. -- 1.6.5.rc2