mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
(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.
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -193,6 +193,10 @@ Makefile.in
|
|||||||
/generator/generator
|
/generator/generator
|
||||||
/generator/.pod2text.data*
|
/generator/.pod2text.data*
|
||||||
/generator/stamp-generator
|
/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
|
/.gitattributes
|
||||||
/.git-module-status
|
/.git-module-status
|
||||||
/gnulib
|
/gnulib
|
||||||
@@ -245,6 +249,7 @@ Makefile.in
|
|||||||
/html/virt-edit.1.html
|
/html/virt-edit.1.html
|
||||||
/html/virt-filesystems.1.html
|
/html/virt-filesystems.1.html
|
||||||
/html/virt-format.1.html
|
/html/virt-format.1.html
|
||||||
|
/html/virt-get-kernel.1.html
|
||||||
/html/virt-index-validate.1.html
|
/html/virt-index-validate.1.html
|
||||||
/html/virt-inspector.1.html
|
/html/virt-inspector.1.html
|
||||||
/html/virt-list-filesystems.1.html
|
/html/virt-list-filesystems.1.html
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ SUBDIRS += \
|
|||||||
mllib \
|
mllib \
|
||||||
customize \
|
customize \
|
||||||
builder builder/website \
|
builder builder/website \
|
||||||
|
get-kernel \
|
||||||
resize \
|
resize \
|
||||||
sparsify \
|
sparsify \
|
||||||
sysprep \
|
sysprep \
|
||||||
@@ -353,7 +354,7 @@ all-local:
|
|||||||
grep -v -E '^python/utils.c$$' | \
|
grep -v -E '^python/utils.c$$' | \
|
||||||
LC_ALL=C sort > po/POTFILES
|
LC_ALL=C sort > po/POTFILES
|
||||||
cd $(srcdir); \
|
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
|
LC_ALL=C sort > po/POTFILES-ml
|
||||||
|
|
||||||
# Try to stop people using 'make install' without 'DESTDIR'.
|
# Try to stop people using 'make install' without 'DESTDIR'.
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-builder
|
|||||||
SOURCES_MLI = \
|
SOURCES_MLI = \
|
||||||
cache.mli \
|
cache.mli \
|
||||||
downloader.mli \
|
downloader.mli \
|
||||||
get_kernel.mli \
|
|
||||||
index_parser.mli \
|
index_parser.mli \
|
||||||
ini_reader.mli \
|
ini_reader.mli \
|
||||||
languages.mli \
|
languages.mli \
|
||||||
@@ -56,7 +55,6 @@ SOURCES_ML = \
|
|||||||
ini_reader.ml \
|
ini_reader.ml \
|
||||||
paths.ml \
|
paths.ml \
|
||||||
languages.ml \
|
languages.ml \
|
||||||
get_kernel.ml \
|
|
||||||
cache.ml \
|
cache.ml \
|
||||||
sources.ml \
|
sources.ml \
|
||||||
downloader.ml \
|
downloader.ml \
|
||||||
|
|||||||
@@ -91,8 +91,19 @@ let main () =
|
|||||||
let mode =
|
let mode =
|
||||||
match mode with
|
match mode with
|
||||||
| `Get_kernel -> (* --get-kernel is really a different program ... *)
|
| `Get_kernel -> (* --get-kernel is really a different program ... *)
|
||||||
Get_kernel.get_kernel ?format ?output arg;
|
let cmd =
|
||||||
exit 0
|
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 *)
|
| `Delete_cache -> (* --delete-cache *)
|
||||||
(match cache with
|
(match cache with
|
||||||
|
|||||||
@@ -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 ()
|
|
||||||
@@ -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
|
|
||||||
@@ -1749,6 +1749,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
format/Makefile
|
format/Makefile
|
||||||
fuse/Makefile
|
fuse/Makefile
|
||||||
generator/Makefile
|
generator/Makefile
|
||||||
|
get-kernel/Makefile
|
||||||
gnulib/lib/Makefile
|
gnulib/lib/Makefile
|
||||||
gnulib/tests/Makefile
|
gnulib/tests/Makefile
|
||||||
gobject/libguestfs-gobject-1.0.pc
|
gobject/libguestfs-gobject-1.0.pc
|
||||||
|
|||||||
146
get-kernel/Makefile.am
Normal file
146
get-kernel/Makefile.am
Normal file
@@ -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
|
||||||
185
get-kernel/get_kernel.ml
Normal file
185
get-kernel/get_kernel.ml
Normal file
@@ -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
|
||||||
148
get-kernel/virt-get-kernel.pod
Normal file
148
get-kernel/virt-get-kernel.pod
Normal file
@@ -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.
|
||||||
@@ -2,7 +2,6 @@ builder/builder.ml
|
|||||||
builder/cache.ml
|
builder/cache.ml
|
||||||
builder/cmdline.ml
|
builder/cmdline.ml
|
||||||
builder/downloader.ml
|
builder/downloader.ml
|
||||||
builder/get_kernel.ml
|
|
||||||
builder/index_parser.ml
|
builder/index_parser.ml
|
||||||
builder/ini_reader.ml
|
builder/ini_reader.ml
|
||||||
builder/languages.ml
|
builder/languages.ml
|
||||||
@@ -26,6 +25,7 @@ customize/random_seed.ml
|
|||||||
customize/ssh_key.ml
|
customize/ssh_key.ml
|
||||||
customize/timezone.ml
|
customize/timezone.ml
|
||||||
customize/urandom.ml
|
customize/urandom.ml
|
||||||
|
get-kernel/get_kernel.ml
|
||||||
mllib/JSON.ml
|
mllib/JSON.ml
|
||||||
mllib/JSON_tests.ml
|
mllib/JSON_tests.ml
|
||||||
mllib/common_gettext.ml
|
mllib/common_gettext.ml
|
||||||
|
|||||||
1
run.in
1
run.in
@@ -92,6 +92,7 @@ prepend PATH "$b/erlang"
|
|||||||
prepend PATH "$b/fish"
|
prepend PATH "$b/fish"
|
||||||
prepend PATH "$b/format"
|
prepend PATH "$b/format"
|
||||||
prepend PATH "$b/fuse"
|
prepend PATH "$b/fuse"
|
||||||
|
prepend PATH "$b/get-kernel"
|
||||||
prepend PATH "$b/inspector"
|
prepend PATH "$b/inspector"
|
||||||
prepend PATH "$b/make-fs"
|
prepend PATH "$b/make-fs"
|
||||||
prepend PATH "$b/p2v"
|
prepend PATH "$b/p2v"
|
||||||
|
|||||||
@@ -4384,6 +4384,10 @@ L<guestmount(1)>, FUSE (userspace filesystem) built on top of libguestfs.
|
|||||||
The crucially important generator, used to automatically generate
|
The crucially important generator, used to automatically generate
|
||||||
large amounts of boilerplate C code for things like RPC and bindings.
|
large amounts of boilerplate C code for things like RPC and bindings.
|
||||||
|
|
||||||
|
=item F<get-kernel>
|
||||||
|
|
||||||
|
L<virt-get-kernel(1)> command and documentation.
|
||||||
|
|
||||||
=item F<gnulib>
|
=item F<gnulib>
|
||||||
|
|
||||||
Gnulib is used as a portability library. A copy of gnulib is included
|
Gnulib is used as a portability library. A copy of gnulib is included
|
||||||
|
|||||||
Reference in New Issue
Block a user