Pino Toscano
2015-Jun-11 16:11 UTC
[Libguestfs] [PATCH] (Almost) new tool: virt-get-kernel
Extract the guest kernel/ramdisk extraction from virt-builder into a separate utility, so it can be used and improved without cluttering virt-builder. Currently it does what virt-builder --get-kernel did, adding also the options for remote disks and libvirt access, much like other libguestfs tools. virt-builder --get-kernel now just spawns virt-get-kernel. --- .gitignore | 5 ++ Makefile.am | 3 +- builder/Makefile.am | 2 - builder/builder.ml | 15 +++- builder/get_kernel.ml | 92 -------------------- builder/get_kernel.mli | 19 ----- configure.ac | 1 + get-kernel/Makefile.am | 146 ++++++++++++++++++++++++++++++++ get-kernel/get_kernel.ml | 185 +++++++++++++++++++++++++++++++++++++++++ get-kernel/virt-get-kernel.pod | 148 +++++++++++++++++++++++++++++++++ po/POTFILES-ml | 2 +- run.in | 1 + 12 files changed, 502 insertions(+), 117 deletions(-) delete mode 100644 builder/get_kernel.ml delete mode 100644 builder/get_kernel.mli create mode 100644 get-kernel/Makefile.am create mode 100644 get-kernel/get_kernel.ml create mode 100644 get-kernel/virt-get-kernel.pod diff --git a/.gitignore b/.gitignore index d1292d9..6f14915 100644 --- a/.gitignore +++ b/.gitignore @@ -193,6 +193,10 @@ Makefile.in /generator/generator /generator/.pod2text.data* /generator/stamp-generator +/get-kernel/.depend +/get-kernel/stamp-virt-get-kernel.pod +/get-kernel/virt-get-kernel +/get-kernel/virt-get-kernel.1 /.gitattributes /.git-module-status /gnulib @@ -245,6 +249,7 @@ Makefile.in /html/virt-edit.1.html /html/virt-filesystems.1.html /html/virt-format.1.html +/html/virt-get-kernel.1.html /html/virt-index-validate.1.html /html/virt-inspector.1.html /html/virt-list-filesystems.1.html diff --git a/Makefile.am b/Makefile.am index 331a34e..ad6d9d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,6 +133,7 @@ SUBDIRS += \ mllib \ customize \ builder builder/website \ + get-kernel \ resize \ sparsify \ sysprep \ @@ -353,7 +354,7 @@ all-local: grep -v -E '^python/utils.c$$' | \ LC_ALL=C sort > po/POTFILES cd $(srcdir); \ - find builder customize mllib resize sparsify sysprep v2v -name '*.ml' | \ + find builder customize get-kernel mllib resize sparsify sysprep v2v -name '*.ml' | \ LC_ALL=C sort > po/POTFILES-ml # Try to stop people using 'make install' without 'DESTDIR'. diff --git a/builder/Makefile.am b/builder/Makefile.am index 28b2adf..d69e25f 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -39,7 +39,6 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-builder SOURCES_MLI = \ cache.mli \ downloader.mli \ - get_kernel.mli \ index_parser.mli \ ini_reader.mli \ languages.mli \ @@ -56,7 +55,6 @@ SOURCES_ML = \ ini_reader.ml \ paths.ml \ languages.ml \ - get_kernel.ml \ cache.ml \ sources.ml \ downloader.ml \ diff --git a/builder/builder.ml b/builder/builder.ml index 5ea69c0..1f618ad 100644 --- a/builder/builder.ml +++ b/builder/builder.ml @@ -91,8 +91,19 @@ let main () let mode match mode with | `Get_kernel -> (* --get-kernel is really a different program ... *) - Get_kernel.get_kernel ?format ?output arg; - exit 0 + let cmd + sprintf "virt-get-kernel%s%s%s%s --add %s" + (if verbose () then " --verbose" else "") + (if trace () then " -x" else "") + (match format with + | None -> "" + | Some format -> sprintf " --format %s" (quote format)) + (match output with + | None -> "" + | Some output -> sprintf " --output %s" (quote output)) + (quote arg) in + if verbose () then printf "%s\n%!" cmd; + exit (Sys.command cmd) | `Delete_cache -> (* --delete-cache *) (match cache with diff --git a/builder/get_kernel.ml b/builder/get_kernel.ml deleted file mode 100644 index 5cea647..0000000 --- a/builder/get_kernel.ml +++ /dev/null @@ -1,92 +0,0 @@ -(* virt-builder - * Copyright (C) 2013 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - -open Common_gettext.Gettext -open Common_utils - -open Utils - -module G = Guestfs - -open Printf - -(* Originally: - * http://rwmj.wordpress.com/2013/09/13/get-kernel-and-initramfs-from-a-disk-image/ - *) -let rec get_kernel ?format ?output disk - let g = new G.guestfs () in - if trace () then g#set_trace true; - if verbose () then g#set_verbose true; - g#add_drive_opts ?format ~readonly:true disk; - g#launch (); - - let roots = g#inspect_os () in - if Array.length roots = 0 then - error (f_"get-kernel: no operating system found"); - if Array.length roots > 1 then - error (f_"get-kernel: dual/multi-boot images are not supported by this tool"); - let root = roots.(0) in - - (* Mount up the disks. *) - let mps = g#inspect_get_mountpoints root in - let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in - let mps = List.sort cmp mps in - List.iter ( - fun (mp, dev) -> - try g#mount_ro dev mp - with Guestfs.Error msg -> warning (f_"%s (ignored)") msg - ) mps; - - (* Get all kernels and initramfses. *) - let glob w = Array.to_list (g#glob_expand w) in - let kernels = glob "/boot/vmlinuz-*" in - let initrds = glob "/boot/initramfs-*" in - - (* Old RHEL: *) - let initrds = if initrds <> [] then initrds else glob "/boot/initrd-*" in - - (* Debian/Ubuntu: *) - let initrds = if initrds <> [] then initrds else glob "/boot/initrd.img-*" in - - (* Sort by version to get the latest version as first element. *) - let kernels = List.rev (List.sort compare_version kernels) in - let initrds = List.rev (List.sort compare_version initrds) in - - if kernels = [] then - error (f_"no kernel found"); - - (* Download the latest. *) - let outputdir - match output with - | None -> Filename.current_dir_name - | Some dir -> dir in - let kernel_in = List.hd kernels in - let kernel_out = outputdir // Filename.basename kernel_in in - printf "download: %s -> %s\n%!" kernel_in kernel_out; - g#download kernel_in kernel_out; - - if initrds <> [] then ( - let initrd_in = List.hd initrds in - let initrd_out = outputdir // Filename.basename initrd_in in - printf "download: %s -> %s\n%!" initrd_in initrd_out; - g#download initrd_in initrd_out - ); - - (* Shutdown. *) - g#shutdown (); - g#close () diff --git a/builder/get_kernel.mli b/builder/get_kernel.mli deleted file mode 100644 index 5f47ca1..0000000 --- a/builder/get_kernel.mli +++ /dev/null @@ -1,19 +0,0 @@ -(* virt-builder - * Copyright (C) 2013 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - -val get_kernel : ?format:string -> ?output:string -> string -> unit diff --git a/configure.ac b/configure.ac index 2c82c35..e0da1ad 100644 --- a/configure.ac +++ b/configure.ac @@ -1749,6 +1749,7 @@ AC_CONFIG_FILES([Makefile format/Makefile fuse/Makefile generator/Makefile + get-kernel/Makefile gnulib/lib/Makefile gnulib/tests/Makefile gobject/libguestfs-gobject-1.0.pc diff --git a/get-kernel/Makefile.am b/get-kernel/Makefile.am new file mode 100644 index 0000000..f217128 --- /dev/null +++ b/get-kernel/Makefile.am @@ -0,0 +1,146 @@ +# libguestfs get-kernel tool +# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +include $(top_srcdir)/subdir-rules.mk + +EXTRA_DIST = \ + $(SOURCES_ML) $(SOURCES_C) \ + virt-get-kernel.pod + +CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-get-kernel + +SOURCES_ML = \ + get_kernel.ml + +SOURCES_C = \ + $(top_srcdir)/mllib/uri-c.c \ + $(top_srcdir)/fish/uri.c + +man_MANS +noinst_DATA +bin_PROGRAMS + +if HAVE_OCAML + +bin_PROGRAMS += virt-get-kernel + +virt_get_kernel_SOURCES = $(SOURCES_C) +virt_get_kernel_CPPFLAGS = \ + -I. \ + -I$(top_builddir) \ + -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ + -I$(shell $(OCAMLC) -where) \ + -I$(top_srcdir)/gnulib/lib \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/fish +virt_get_kernel_CFLAGS = \ + -pthread \ + $(WARN_CFLAGS) $(WERROR_CFLAGS) \ + $(LIBXML2_CFLAGS) + +BOBJECTS = \ + $(top_builddir)/mllib/libdir.cmo \ + $(top_builddir)/mllib/config.cmo \ + $(top_builddir)/mllib/common_gettext.cmo \ + $(top_builddir)/mllib/common_utils.cmo \ + $(top_builddir)/mllib/uRI.cmo \ + $(SOURCES_ML:.ml=.cmo) +XOBJECTS = $(BOBJECTS:.cmo=.cmx) + +# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L +# option to be passed to gcc, so we don't try linking against an +# installed copy of libguestfs. +OCAMLPACKAGES = \ + -package str,unix \ + -I $(top_builddir)/src/.libs \ + -I $(top_builddir)/gnulib/lib/.libs \ + -I $(top_builddir)/ocaml \ + -I $(top_builddir)/mllib +if HAVE_OCAML_PKG_GETTEXT +OCAMLPACKAGES += -package gettext-stub +endif + +OCAMLCLIBS = \ + -pthread -lpthread \ + -lutils \ + $(LIBXML2_LIBS) \ + $(LIBINTL) \ + -lgnu + +OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR) + +if !HAVE_OCAMLOPT +OBJECTS = $(BOBJECTS) +BEST = c +OCAMLLINKFLAGS = mlguestfs.cma -custom +else +OBJECTS = $(XOBJECTS) +BEST = opt +OCAMLLINKFLAGS = mlguestfs.cmxa +endif + +virt_get_kernel_DEPENDENCIES = $(OBJECTS) $(top_srcdir)/ocaml-link.sh +virt_get_kernel_LINK = \ + $(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \ + $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLLINKFLAGS) \ + $(OBJECTS) -o $@ + +.mli.cmi: + $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@ +.ml.cmo: + $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@ +if HAVE_OCAMLOPT +.ml.cmx: + $(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@ +endif + +# Manual pages and HTML files for the website. + +man_MANS += virt-get-kernel.1 +noinst_DATA += $(top_builddir)/html/virt-get-kernel.1.html + +virt-get-kernel.1 $(top_builddir)/html/virt-get-kernel.1.html: stamp-virt-get-kernel.pod + +stamp-virt-get-kernel.pod: virt-get-kernel.pod + $(PODWRAPPER) \ + --man virt-get-kernel.1 \ + --html $(top_builddir)/html/virt-get-kernel.1.html \ + --license GPLv2+ \ + $< + touch $@ + +CLEANFILES += stamp-virt-get-kernel.pod + +# Dependencies. +depend: .depend + +.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml) + rm -f $@ $@-t + $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib $^ | \ + $(SED) 's/ *$$//' | \ + $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \ + $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \ + sort > $@-t + mv $@-t $@ + +-include .depend + +endif + +DISTCLEANFILES = .depend + +.PHONY: depend diff --git a/get-kernel/get_kernel.ml b/get-kernel/get_kernel.ml new file mode 100644 index 0000000..646a240 --- /dev/null +++ b/get-kernel/get_kernel.ml @@ -0,0 +1,185 @@ +(* virt-get-kernel + * Copyright (C) 2013-2015 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +open Common_gettext.Gettext +open Common_utils + +module G = Guestfs + +open Printf + +(* Main program. *) +let main () + let add, output + let domain = ref None in + let file = ref None in + let libvirturi = ref "" in + let format = ref "" in + let output = ref "" in + let machine_readable = ref false in + + let set_file arg + if !file <> None then + error (f_"--add option can only be given once"); + let uri + try URI.parse_uri arg + with Invalid_argument "URI.parse_uri" -> + error (f_"error parsing URI '%s'. Look for error messages printed above.") arg in + file := Some uri + and set_domain dom + if !domain <> None then + error (f_"--domain option can only be given once"); + domain := Some dom in + + let ditto = " -\"-" in + let argspec = Arg.align [ + "-a", Arg.String set_file, s_"file" ^ " " ^ s_"Add disk image file"; + "--add", Arg.String set_file, s_"file" ^ " " ^ s_"Add disk image file"; + "-c", Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI"; + "--connect", Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI"; + "-d", Arg.String set_domain, s_"domain" ^ " " ^ s_"Set libvirt guest name"; + "--domain", Arg.String set_domain, s_"domain" ^ " " ^ s_"Set libvirt guest name"; + "--format", Arg.Set_string format, s_"format" ^ " " ^ s_"Format of input disk"; + "--short-options", Arg.Unit display_short_options, " " ^ s_"List short options"; + "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; + "--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable"; + "-o", Arg.Set_string output, s_"directory" ^ " " ^ s_"Output directory"; + "--output", Arg.Set_string output, ditto; + "-v", Arg.Unit set_verbose, " " ^ s_"Enable debugging messages"; + "--verbose", Arg.Unit set_verbose, ditto; + "-V", Arg.Unit print_version_and_exit, + " " ^ s_"Display version and exit"; + "--version", Arg.Unit print_version_and_exit, ditto; + "-x", Arg.Unit set_trace, " " ^ s_"Enable tracing of libguestfs calls"; + ] in + long_options := argspec; + let anon_fun _ = raise (Arg.Bad (s_"extra parameter on the command line")) in + let usage_msg + sprintf (f_"\ +%s: extract kernel and ramdisk from a guest + +A short summary of the options is given below. For detailed help please +read the man page virt-get-kernel(1). +") + prog in + Arg.parse argspec anon_fun usage_msg; + + (* Machine-readable mode? Print out some facts about what + * this binary supports. + *) + if !machine_readable then ( + printf "virt-get-kernel\n"; + exit 0 + ); + + (* Check -a and -d options. *) + let file = !file in + let domain = !domain in + let libvirturi = match !libvirturi with "" -> None | s -> Some s in + let add + match file, domain with + | None, None -> + error (f_"you must give either -a or -d options. Read virt-get-kernel(1) man page for further information.") + | Some _, Some _ -> + error (f_"you cannot give -a and -d options together. Read virt-get-kernel(1) man page for further information.") + | None, Some dom -> + fun (g : Guestfs.guestfs) -> + let readonlydisk = "ignore" (* ignore CDs, data drives *) in + ignore (g#add_domain + ~readonly:true ~allowuuid:true ~readonlydisk + ?libvirturi dom) + | Some uri, None -> + fun g -> + let { URI.path = path; protocol = protocol; + server = server; username = username; + password = password } = uri in + let format = match !format with "" -> None | s -> Some s in + g#add_drive + ~readonly:true ?format ~protocol ?server ?username ?secret:password + path + in + + (* Dereference the rest of the args. *) + let output = match !output with "" -> None | str -> Some str in + + add, output in + + (* Connect to libguestfs. *) + let g = new G.guestfs () in + if trace () then g#set_trace true; + if verbose () then g#set_verbose true; + add g; + g#launch (); + + let roots = g#inspect_os () in + if Array.length roots = 0 then + error (f_"get-kernel: no operating system found"); + if Array.length roots > 1 then + error (f_"get-kernel: dual/multi-boot images are not supported by this tool"); + let root = roots.(0) in + + (* Mount up the disks. *) + let mps = g#inspect_get_mountpoints root in + let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in + let mps = List.sort cmp mps in + List.iter ( + fun (mp, dev) -> + try g#mount_ro dev mp + with Guestfs.Error msg -> warning (f_"%s (ignored)") msg + ) mps; + + (* Get all kernels and initramfses. *) + let glob w = Array.to_list (g#glob_expand w) in + let kernels = glob "/boot/vmlinuz-*" in + let initrds = glob "/boot/initramfs-*" in + + (* Old RHEL: *) + let initrds = if initrds <> [] then initrds else glob "/boot/initrd-*" in + + (* Debian/Ubuntu: *) + let initrds = if initrds <> [] then initrds else glob "/boot/initrd.img-*" in + + (* Sort by version to get the latest version as first element. *) + let kernels = List.rev (List.sort compare_version kernels) in + let initrds = List.rev (List.sort compare_version initrds) in + + if kernels = [] then + error (f_"no kernel found"); + + (* Download the latest. *) + let outputdir + match output with + | None -> Filename.current_dir_name + | Some dir -> dir in + let kernel_in = List.hd kernels in + let kernel_out = outputdir // Filename.basename kernel_in in + printf "download: %s -> %s\n%!" kernel_in kernel_out; + g#download kernel_in kernel_out; + + if initrds <> [] then ( + let initrd_in = List.hd initrds in + let initrd_out = outputdir // Filename.basename initrd_in in + printf "download: %s -> %s\n%!" initrd_in initrd_out; + g#download initrd_in initrd_out + ); + + (* Shutdown. *) + g#shutdown (); + g#close () + +let () = run_main_and_handle_errors main diff --git a/get-kernel/virt-get-kernel.pod b/get-kernel/virt-get-kernel.pod new file mode 100644 index 0000000..e130b4c --- /dev/null +++ b/get-kernel/virt-get-kernel.pod @@ -0,0 +1,148 @@ +=head1 NAME + +virt-get-kernel - Extract kernel and ramdisk from guests + +=head1 SYNOPSIS + + virt-get-kernel [--options] -d domname + + virt-get-kernel [--options] -a disk.img + +=head1 DESCRIPTION + +This option extracts the kernel and initramfs from a guest. + +The format of the disk image is automatically detected unless you +specify it by using the I<--format> option. + +In the case where the guest contains multiple kernels, the one with +the highest version number is chosen. To extract arbitrary kernels +from the disk image, see L<guestfish(1)>. To extract the entire +C</boot> directory of a guest, see L<virt-copy-out(1)>. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Display help. + +=item B<-a> file + +=item B<--add> file + +Add I<file> which should be a disk image from a virtual machine. + +The format of the disk image is auto-detected. To override this and +force a particular format use the I<--format> option. + +=item B<-a> URI + +=item B<--add> URI + +Add a remote disk. The URI format is compatible with guestfish. +See L<guestfish(1)/ADDING REMOTE STORAGE>. + +=item B<-c> URI + +=item B<--connect> 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 (I<-a>), then libvirt is +not used at all. + +=item B<-d> guest + +=item B<--domain> guest + +Add all the disks from the named libvirt guest. Domain UUIDs can be +used instead of names. + +=item B<--format> raw|qcow2|.. + +=item B<--format> auto + +The default for the I<-a> option is to auto-detect the format of the +disk image. Using this forces the disk format for the I<-a> option +on the command line. + +If you have untrusted raw-format guest disk images, you should use +this option to specify the disk format. This avoids a possible +security problem with malicious guests (CVE-2010-3851). + +=item B<--machine-readable> + +This option is used to make the output more machine friendly +when being parsed by other programs. See +L</MACHINE READABLE OUTPUT> below. + +=item B<-o> directory + +=item B<--output> directory + +This option specifies the output directory where kernel and initramfs +from the guest are written. + +If not specified, the default output is the current directory. + +=item B<-v> + +=item B<--verbose> + +Enable verbose messages for debugging. + +=item B<-V> + +=item B<--version> + +Display version number and exit. + +=item B<-x> + +Enable tracing of libguestfs API calls. + +=back + +=head1 MACHINE READABLE OUTPUT + +The I<--machine-readable> option can be used to make the output more +machine friendly, which is useful when calling virt-get-kernel from +other programs, GUIs etc. + +Use the option on its own to query the capabilities of the +virt-get-kernel binary. Typical output looks like this: + + $ virt-get-kernel --machine-readable + virt-get-kernel + +A list of features is printed, one per line, and the program exits +with status 0. + +=head1 ENVIRONMENT VARIABLES + +For other environment variables which affect all libguestfs programs, +see L<guestfs(3)/ENVIRONMENT VARIABLES>. + +=head1 EXIT STATUS + +This program returns 0 if successful, or non-zero if there was an +error. + +=head1 SEE ALSO + +L<guestfs(3)>, +L<guestfish(1)>, +L<guestmount(1)>, +L<virt-copy-out(1)>, +L<http://libguestfs.org/>. + +=head1 AUTHOR + +Richard W.M. Jones L<http://people.redhat.com/~rjones/> + +=head1 COPYRIGHT + +Copyright (C) 2013-2015 Red Hat Inc. diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 3fc60e5..8725385 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -2,7 +2,6 @@ builder/builder.ml builder/cache.ml builder/cmdline.ml builder/downloader.ml -builder/get_kernel.ml builder/index_parser.ml builder/ini_reader.ml builder/languages.ml @@ -26,6 +25,7 @@ customize/random_seed.ml customize/ssh_key.ml customize/timezone.ml customize/urandom.ml +get-kernel/get_kernel.ml mllib/JSON.ml mllib/JSON_tests.ml mllib/common_gettext.ml diff --git a/run.in b/run.in index 8fdf454..6709cdd 100755 --- a/run.in +++ b/run.in @@ -92,6 +92,7 @@ prepend PATH "$b/erlang" prepend PATH "$b/fish" prepend PATH "$b/format" prepend PATH "$b/fuse" +prepend PATH "$b/get-kernel" prepend PATH "$b/inspector" prepend PATH "$b/make-fs" prepend PATH "$b/p2v" -- 2.1.0
Pino Toscano
2015-Jun-12 09:02 UTC
[Libguestfs] [PATCH 2/3] get-kernel: add --unversioned-names
New --unversioned-names option to save extracted files just with their base name (i.e. "vmlinux", "initrd.img"). --- get-kernel/get_kernel.ml | 17 +++++++++++++---- get-kernel/virt-get-kernel.pod | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/get-kernel/get_kernel.ml b/get-kernel/get_kernel.ml index 646a240..1523363 100644 --- a/get-kernel/get_kernel.ml +++ b/get-kernel/get_kernel.ml @@ -25,13 +25,14 @@ open Printf (* Main program. *) let main () - let add, output + let add, output, unversioned let domain = ref None in let file = ref None in let libvirturi = ref "" in let format = ref "" in let output = ref "" in let machine_readable = ref false in + let unversioned = ref false in let set_file arg if !file <> None then @@ -60,6 +61,8 @@ let main () "--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable"; "-o", Arg.Set_string output, s_"directory" ^ " " ^ s_"Output directory"; "--output", Arg.Set_string output, ditto; + "--unversioned-names", Arg.Set unversioned, + " " ^ s_"Use unversioned names for files"; "-v", Arg.Unit set_verbose, " " ^ s_"Enable debugging messages"; "--verbose", Arg.Unit set_verbose, ditto; "-V", Arg.Unit print_version_and_exit, @@ -116,8 +119,9 @@ read the man page virt-get-kernel(1). (* Dereference the rest of the args. *) let output = match !output with "" -> None | str -> Some str in + let unversioned = !unversioned in - add, output in + add, output, unversioned in (* Connect to libguestfs. *) let g = new G.guestfs () in @@ -161,19 +165,24 @@ read the man page virt-get-kernel(1). if kernels = [] then error (f_"no kernel found"); + let dest_filename fn + let fn = Filename.basename fn in + if unversioned then fst (string_split "-" fn) + else fn in + (* Download the latest. *) let outputdir match output with | None -> Filename.current_dir_name | Some dir -> dir in let kernel_in = List.hd kernels in - let kernel_out = outputdir // Filename.basename kernel_in in + let kernel_out = outputdir // dest_filename kernel_in in printf "download: %s -> %s\n%!" kernel_in kernel_out; g#download kernel_in kernel_out; if initrds <> [] then ( let initrd_in = List.hd initrds in - let initrd_out = outputdir // Filename.basename initrd_in in + let initrd_out = outputdir // dest_filename initrd_in in printf "download: %s -> %s\n%!" initrd_in initrd_out; g#download initrd_in initrd_out ); diff --git a/get-kernel/virt-get-kernel.pod b/get-kernel/virt-get-kernel.pod index e130b4c..a369072 100644 --- a/get-kernel/virt-get-kernel.pod +++ b/get-kernel/virt-get-kernel.pod @@ -88,6 +88,15 @@ from the guest are written. If not specified, the default output is the current directory. +=item B<--unversioned-names> + +This option affects the destination file name of extracted files. + +If enabled, files will be saved locally just with the base name; +for example, kernel and ramdisk in the guest like +C<vmlinuz-3.19.0-20-generic> and C<initrd.img-3.19.0-20-generic> +are saved respectively as C<vmlinuz> and C<initrd.img>. + =item B<-v> =item B<--verbose> -- 2.1.0
New --prefix option to specify a prefix for the extracted file names. --- get-kernel/get_kernel.ml | 21 ++++++++++++++++----- get-kernel/virt-get-kernel.pod | 13 +++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/get-kernel/get_kernel.ml b/get-kernel/get_kernel.ml index 1523363..01297f0 100644 --- a/get-kernel/get_kernel.ml +++ b/get-kernel/get_kernel.ml @@ -25,7 +25,7 @@ open Printf (* Main program. *) let main () - let add, output, unversioned + let add, output, unversioned, prefix let domain = ref None in let file = ref None in let libvirturi = ref "" in @@ -33,6 +33,7 @@ let main () let output = ref "" in let machine_readable = ref false in let unversioned = ref false in + let prefix = ref None in let set_file arg if !file <> None then @@ -45,7 +46,11 @@ let main () and set_domain dom if !domain <> None then error (f_"--domain option can only be given once"); - domain := Some dom in + domain := Some dom + and set_prefix p + if !prefix <> None then + error (f_"--prefix option can only be given once"); + prefix := Some p in let ditto = " -\"-" in let argspec = Arg.align [ @@ -63,6 +68,7 @@ let main () "--output", Arg.Set_string output, ditto; "--unversioned-names", Arg.Set unversioned, " " ^ s_"Use unversioned names for files"; + "--prefix", Arg.String set_prefix, "prefix" ^ " " ^ s_"Prefix for files"; "-v", Arg.Unit set_verbose, " " ^ s_"Enable debugging messages"; "--verbose", Arg.Unit set_verbose, ditto; "-V", Arg.Unit print_version_and_exit, @@ -120,8 +126,9 @@ read the man page virt-get-kernel(1). (* Dereference the rest of the args. *) let output = match !output with "" -> None | str -> Some str in let unversioned = !unversioned in + let prefix = !prefix in - add, output, unversioned in + add, output, unversioned, prefix in (* Connect to libguestfs. *) let g = new G.guestfs () in @@ -167,8 +174,12 @@ read the man page virt-get-kernel(1). let dest_filename fn let fn = Filename.basename fn in - if unversioned then fst (string_split "-" fn) - else fn in + let fn + if unversioned then fst (string_split "-" fn) + else fn in + match prefix with + | None -> fn + | Some p -> p ^ "-" ^ fn in (* Download the latest. *) let outputdir diff --git a/get-kernel/virt-get-kernel.pod b/get-kernel/virt-get-kernel.pod index a369072..be0e8bb 100644 --- a/get-kernel/virt-get-kernel.pod +++ b/get-kernel/virt-get-kernel.pod @@ -88,6 +88,17 @@ from the guest are written. If not specified, the default output is the current directory. +=item B<--prefix> prefix + +This option specifies a prefix for the extracted files. + +If a prefix is specified, then there will be a dash (C<->) after the +prefix and before the rest of the file name; for example, a kernel +in the guest like C<vmlinuz-3.19.0-20-generic> is saved as +C<mydistro-vmlinuz-3.19.0-20-generic> when the prefix is C<mydistro>. + +See also I<--unversioned-names>. + =item B<--unversioned-names> This option affects the destination file name of extracted files. @@ -97,6 +108,8 @@ for example, kernel and ramdisk in the guest like C<vmlinuz-3.19.0-20-generic> and C<initrd.img-3.19.0-20-generic> are saved respectively as C<vmlinuz> and C<initrd.img>. +See also I<--prefix>. + =item B<-v> =item B<--verbose> -- 2.1.0