Fix networking in the appliance.
[libguestfs.git] / tools / virt-tar
1 #!/usr/bin/perl -w
2 # virt-tar
3 # Copyright (C) 2009 Red Hat Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 use warnings;
20 use strict;
21
22 use Sys::Guestfs;
23 use Sys::Guestfs::Lib qw(open_guest get_partitions resolve_windows_path
24   inspect_all_partitions inspect_partition
25   inspect_operating_systems mount_operating_system);
26 use Pod::Usage;
27 use Getopt::Long;
28 use Locale::TextDomain 'libguestfs';
29
30 =encoding utf8
31
32 =head1 NAME
33
34 virt-tar - Extract or upload files to a virtual machine
35
36 =head1 SYNOPSIS
37
38  virt-tar [--options] -x domname directory tarball
39
40  virt-tar [--options] -u domname tarball directory
41
42  virt-tar [--options] disk.img [disk.img ...] -x directory tarball
43
44  virt-tar [--options] disk.img [disk.img ...] -u tarball directory
45
46 =head1 EXAMPLES
47
48 Download C</home> from the VM into a local tarball:
49
50  virt-tar -x domname /home home.tar
51
52  virt-tar -zx domname /home home.tar.gz
53
54 Upload a local tarball and unpack it inside C</tmp> in the VM:
55
56  virt-tar -u domname uploadstuff.tar /tmp
57
58  virt-tar -zu domname uploadstuff.tar.gz /tmp
59
60 =head1 WARNING
61
62 You must I<not> use C<virt-tar> with the C<-u> option (upload) on live
63 virtual machines.  If you do this, you risk disk corruption in the VM.
64 C<virt-tar> tries to stop you from doing this, but doesn't catch all
65 cases.
66
67 You can use C<-x> (extract) on live virtual machines, but you might
68 get inconsistent results or errors if there is filesystem activity
69 inside the VM.  If the live VM is synched and quiescent, then
70 C<virt-tar> will usually work, but the only way to guarantee
71 consistent results is if the virtual machine is shut down.
72
73 =head1 DESCRIPTION
74
75 C<virt-tar> is a general purpose archive tool for downloading and
76 uploading parts of a guest filesystem.  There are many possibilities:
77 making backups, uploading data files, snooping on guest activity,
78 fixing or customizing guests, etc.
79
80 If you want to just view a single file, use L<virt-cat(1)>.  If you
81 just want to edit a single file, use L<virt-edit(1)>.  For more
82 complex cases you should look at the L<guestfish(1)> tool.
83
84 There are two modes of operation: C<-x> (eXtract) downloads a
85 directory and its contents (recursively) from the virtual machine into
86 a local tarball.  C<-u> uploads from a local tarball, unpacking it
87 into a directory inside the virtual machine.  You cannot use these two
88 options together.
89
90 In addition, you may need to use the C<-z> (gZip) option to enable
91 compression.  When uploading, you have to specify C<-z> if the upload
92 file is compressed because virt-tar won't detect this on its own.
93
94 C<virt-tar> can only handle tar (optionally gzipped) format tarballs.
95 For example it cannot do PKZip files or bzip2 compression.  If you
96 want that then you'll have to rebuild the tarballs yourself.  (This is
97 a limitation of the L<libguestfs(3)> API).
98
99 =head1 OPTIONS
100
101 =over 4
102
103 =cut
104
105 my $help;
106
107 =item B<--help>
108
109 Display brief help.
110
111 =cut
112
113 my $version;
114
115 =item B<--version>
116
117 Display version number and exit.
118
119 =cut
120
121 my $uri;
122
123 =item B<--connect URI> | B<-c URI>
124
125 If using libvirt, connect to the given I<URI>.  If omitted, then we
126 connect to the default libvirt hypervisor.
127
128 If you specify guest block devices directly, then libvirt is not used
129 at all.
130
131 =cut
132
133 my $format;
134
135 =item B<--format> raw
136
137 Specify the format of disk images given on the command line.  If this
138 is omitted then the format is autodetected from the content of the
139 disk image.
140
141 If disk images are requested from libvirt, then this program asks
142 libvirt for this information.  In this case, the value of the format
143 parameter is ignored.
144
145 If working with untrusted raw-format guest disk images, you should
146 ensure the format is always specified.
147
148 =cut
149
150 my $mode;
151
152 =item B<-x> | B<--extract> | B<--download>
153
154 =item B<-u> | B<--upload>
155
156 Use C<-x> to extract (download) a directory from a virtual machine
157 to a local tarball.
158
159 Use C<-u> to upload and unpack from a local tarball into a virtual
160 machine.  Please read the L</WARNING> section above before using this
161 option.
162
163 You must specify exactly one of these options.
164
165 =cut
166
167 my $gzip;
168
169 =item B<-z> | B<--gzip>
170
171 Specify that the input or output tarball is gzip-compressed.
172
173 =back
174
175 =cut
176
177 sub set_mode_x
178 {
179     die __"virt-tar: extract/upload mode specified twice on the command line\n"
180         if $mode;
181     $mode = "x";
182 }
183
184 sub set_mode_u
185 {
186     die __"virt-tar: extract/upload mode specified twice on the command line\n"
187         if $mode;
188     $mode = "u";
189 }
190
191 Getopt::Long::Configure ("bundling");
192 GetOptions ("help|?" => \$help,
193             "version" => \$version,
194             "connect|c=s" => \$uri,
195             "format=s" => \$format,
196             "extract|download|x" => \&set_mode_x,
197             "upload|u" => \&set_mode_u,
198             "gzip|z" => \$gzip,
199     ) or pod2usage (2);
200 pod2usage (1) if $help;
201 if ($version) {
202     my $g = Sys::Guestfs->new ();
203     my %h = $g->version ();
204     print "$h{major}.$h{minor}.$h{release}$h{extra}\n";
205     exit
206 }
207
208 pod2usage (__"virt-tar: no image, VM names, directory or filename given")
209     if @ARGV <= 2;
210
211 die __"virt-tar: either -x or -u must be specified on the command line\n"
212     unless $mode;
213
214 # Note: 'pop' reads arguments right to left.
215 my ($tarball, $directory);
216 if ($mode eq "x") {
217     $tarball = pop @ARGV;
218     $directory = pop @ARGV;
219 } else { # $mode eq "u"
220     $directory = pop @ARGV;
221     $tarball = pop @ARGV;
222     die __x("virt-tar: {tarball}: file not found\n",
223             tarball => $tarball) unless -f $tarball;
224 }
225 die __x("virt-tar: {dir}: directory name must start with '/' character\n",
226         dir => $directory)
227     unless substr ($directory, 0, 1) eq "/";
228
229 my @args = (\@ARGV);
230 push @args, address => $uri if $uri;
231 push @args, rw => 1 if $mode eq "u";
232 push @args, format => $format if defined $format;
233
234 my $g = open_guest (@args);
235 $g->launch ();
236
237 # List of possible filesystems.
238 my @partitions = get_partitions ($g);
239
240 # Now query each one to build up a picture of what's in it.
241 my %fses =
242     inspect_all_partitions ($g, \@partitions,
243       use_windows_registry => 0);
244
245 my $oses = inspect_operating_systems ($g, \%fses);
246
247 my @roots = keys %$oses;
248 die __"multiboot operating systems are not supported by virt-tar\n" if @roots > 1;
249 my $root_dev = $roots[0];
250
251 my $os = $oses->{$root_dev};
252 mount_operating_system ($g, $os, $mode eq "u" ? 0 : 1);
253
254 # Do the tar command.
255 if ($mode eq "x") {
256     if ($gzip) {
257         $g->tgz_out ($directory, $tarball);
258     } else {
259         $g->tar_out ($directory, $tarball);
260     }
261 } else { # mode eq "u"
262     if ($gzip) {
263         $g->tgz_in ($tarball, $directory);
264     } else {
265         $g->tar_in ($tarball, $directory);
266     }
267 }
268
269 $g->sync ();
270 $g->umount_all ();
271
272 undef $g;
273
274 exit 0;
275
276 =head1 SHELL QUOTING
277
278 Libvirt guest names can contain arbitrary characters, some of which
279 have meaning to the shell such as C<#> and space.  You may need to
280 quote or escape these characters on the command line.  See the shell
281 manual page L<sh(1)> for details.
282
283 =head1 SEE ALSO
284
285 L<guestfs(3)>,
286 L<guestfish(1)>,
287 L<virt-cat(1)>,
288 L<virt-edit(1)>,
289 L<Sys::Guestfs(3)>,
290 L<Sys::Guestfs::Lib(3)>,
291 L<Sys::Virt(3)>,
292 L<http://libguestfs.org/>.
293
294 =head1 AUTHOR
295
296 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
297
298 =head1 COPYRIGHT
299
300 Copyright (C) 2009 Red Hat Inc.
301
302 This program is free software; you can redistribute it and/or modify
303 it under the terms of the GNU General Public License as published by
304 the Free Software Foundation; either version 2 of the License, or
305 (at your option) any later version.
306
307 This program is distributed in the hope that it will be useful,
308 but WITHOUT ANY WARRANTY; without even the implied warranty of
309 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
310 GNU General Public License for more details.
311
312 You should have received a copy of the GNU General Public License
313 along with this program; if not, write to the Free Software
314 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.