Quantifying libvirt errors in launching the libguestfs appliance
by Richard W.M. Jones
As people may know, we frequently encounter errors caused by libvirt
when running the libguestfs appliance.
I wanted to find out exactly how frequently these happen and classify
the errors, so I ran the 'virt-df' tool overnight 1700 times. This
tool runs several parallel qemu:///session libvirt connections both
creating a short-lived appliance guest.
Note that I have added Cole's patch to fix https://bugzilla.redhat.com/1271183
"XML-RPC error : Cannot write data: Transport endpoint is not connected"
Results:
The test failed 538 times (32% of the time), which is pretty dismal.
To be fair, virt-df is aggressive about how it launches parallel
libvirt connections. Most other virt-* tools use only a single
libvirt connection and are consequently more reliable.
Of the failures, 518 (96%) were of the form:
process exited while connecting to monitor: qemu: could not load kernel '/home/rjones/d/libguestfs/tmp/.guestfs-1000/appliance.d/kernel': Permission denied
which is https://bugzilla.redhat.com/921135 or maybe
https://bugzilla.redhat.com/1269975. It's not clear to me if these
bugs have different causes, but if they do then potentially we're
seeing a mix of both since my test has no way to distinguish them.
19 of the failures (4%) were of the form:
process exited while connecting to monitor: fread() failed
which I believe is a previously unknown bug. I have filed it as
https://bugzilla.redhat.com/1298122
Finally there was 1 failure:
Unable to read from monitor: Connection reset by peer
which I believe is also a new bug. I have filed it as
https://bugzilla.redhat.com/1298124
I would be good if libvirt could routinely test the case of multiple
parallel launches of qemu:///session, since it still contains bugs
even after Cole's fixes.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top
8 years, 10 months
Re: [Libguestfs] [libguestfs] RFE: virt-builder ability to print definition for single template (new option or expand --notes) (#20)
by Richard W.M. Jones
On Mon, Dec 28, 2015 at 03:51:51PM -0800, Ryan Sawhill Aroha wrote:
> The `virt-builder --notes <TEMPLATE>` command is nice, but I really wish it printed the full template definition, eg, something like this:
>
> ```
> $ virt-builder --notes centos-70
>
> [centos-70]
> name=CentOS 70
> osinfo=centos70
> arch=x86_64
> file=centos-70xz
> checksum=cf9ae295f633fbd04e575eeca16f372e933c70c3107c44eb06864760d04354aa94b4f356bfc9a598c138e687304a52e96777e4467e7db1ec0cb5b2d2ec61affc
> format=raw
> size=6442450944
> compressed_size=213203844
> expand=/dev/sda3
> notes=CentOS 70
>
> This CentOS image contains only unmodified @Core group packages
>
> It is thus very minimal The kickstart and install script can be
> found in the libguestfs source tree:
>
> builder/website/centossh
> ```
One problem with this is that the 'index' format isn't the only
metadata format we now support. (SimpleStreams is another).
However there is an intermediate format we use internally, and those
fields could be printed by --notes or some other mechanism.
https://github.com/libguestfs/libguestfs/blob/master/builder/index.mli
This would be suitable for an RFE in Bugzilla.
> Or maybe it could be like `virt-builder --list-format long --list`
> (all prettified), but only for a particular template
>
> I think normal users need this option to be able to check the
> `osinfo=` value for use with `virt-install` without having to
> scroll/grep through all their templates
We definitely need a way to get at the osinfo information more easily.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v
8 years, 10 months
[PATCH 1/2] builder: move os-version search in own function
by Pino Toscano
Simple code motion, no behaviour changes.
---
builder/builder.ml | 46 ++++++++++++++++++++++++++--------------------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/builder/builder.ml b/builder/builder.ml
index 9c26573..ec9919f 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -75,6 +75,30 @@ let remove_duplicates index =
false
) index
+(* Look for the specified os-version, resolving it as alias first. *)
+let selected_cli_item cmdline index =
+ let arg =
+ (* Try to resolve the alias. *)
+ try
+ let item =
+ List.find (
+ fun (name, { Index.aliases = aliases }) ->
+ match aliases with
+ | None -> false
+ | Some l -> List.mem cmdline.arg l
+ ) index in
+ fst item
+ with Not_found -> cmdline.arg in
+ let item =
+ try List.find (
+ fun (name, { Index.arch = a }) ->
+ name = arg && cmdline.arch = normalize_arch a
+ ) index
+ with Not_found ->
+ error (f_"cannot find os-version '%s' with architecture '%s'.\nUse --list to list available guest types.")
+ arg cmdline.arch in
+ item
+
let main () =
(* Command line argument parsing - see cmdline.ml. *)
let cmdline = parse_cmdline () in
@@ -229,26 +253,8 @@ let main () =
| (`Install|`Notes) as mode -> mode in
(* Which os-version (ie. index entry)? *)
- let arg =
- (* Try to resolve the alias. *)
- try
- let item =
- List.find (
- fun (name, { Index.aliases = aliases }) ->
- match aliases with
- | None -> false
- | Some l -> List.mem cmdline.arg l
- ) index in
- fst item
- with Not_found -> cmdline.arg in
- let item =
- try List.find (
- fun (name, { Index.arch = a }) ->
- name = arg && cmdline.arch = normalize_arch a
- ) index
- with Not_found ->
- error (f_"cannot find os-version '%s' with architecture '%s'.\nUse --list to list available guest types.")
- arg cmdline.arch in
+ let item = selected_cli_item cmdline index in
+ let arg = fst item in
let entry = snd item in
let sigchecker = entry.Index.sigchecker in
--
2.5.0
8 years, 10 months
v2v: error while killing ssh-agent after importing VM via xen+ssh
by Shahar Havivi
Hi,
I am successfully importing VM from Xen server at oVirt project via virt-v2v.
I am setting ssh-agent and running ssh-add before the import process,
after the import done I am trying to kill the agent via:
ssh-agent -k (and setting the SSH_AGENT_PID environment), but I get the
following error:
kill: No such process
Can you please explain why there is no agent?
Do I need to delete the agent?
btw I am also running 'ssh-add -d' after the import process with no problems.
Thank you,
Shahar.
8 years, 10 months
What are the advantages and disadvantages of running with or without libvirt?
by Yaniv Kaul
I didn't see what are the main differences in
http://libguestfs.org/guestfs.3.html#backend
Specifically, I'm interested in what is faster (direct sounds faster to
me), and if there are any major restrictions (networking?)
Here's an example command we are running (sorry, Python'ish, but you'll get
it):
['virt-sysprep', '--connect', 'qemu:///system', '-a',
u'/zram/3.6/images/lago_basic_suite_3_6_engine_root.qcow2',
'--selinux-relabel', '--hostname', 'lago_basic_suite_3_6_engine',
'--root-password', 'password:123456', '--mkdir', '/root/.ssh', '--chmod',
'0700:/root/.ssh', '--upload',
'/zram/3.6/id_rsa.pub:/root/.ssh/authorized_keys', '--run-command', 'chown
root.root /root/.ssh/authorized_keys', '--mkdir', '/etc/iscsi', '--chmod',
'0755:/etc/iscsi', '--write',
'/etc/iscsi/initiatorname.iscsi:InitiatorName=iqn.2014-07.org.lago:lago_basic_suite_3_6_engine',
'--mkdir', '/etc/selinux', '--chmod', '0755:/etc/selinux', '--write',
'/etc/selinux/config:SELINUX=enforcing\nSELINUXTYPE=targeted\n', '--mkdir',
'/etc/sysconfig/network-scripts', '--chmod',
'0755:/etc/sysconfig/network-scripts', '--write',
'/etc/sysconfig/network-scripts/ifcfg-eth0:HWADDR="54:52:c0:a8:c8:03"\nBOOTPROTO="dhcp"\nTYPE="Ethernet"\nONBOOT="yes"\nNAME="eth0"']
TIA,
Y.
8 years, 10 months
Re: [Libguestfs] Note regarding bin2s.pl
by Richard W.M. Jones
On Tue, Jan 12, 2016 at 07:57:03AM +0100, Hilko Bengen wrote:
> Helge,
>
> I have applied all the architecture-specific bits but not the bin2s
> script yet. TBH, so far I don't see what is wrong about export and use
> of the "_binary_init_size" constant.
[https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809185]
I see it as a reasonable simplification - it allows us to get rid of
that conditional code for HP-UX in bin2s.pl.
However looking at the patch, I don't like the casts in:
- size_t n = (size_t) &_binary_init_size;
+ size_t n = ((size_t) &_binary_init_end) - ((size_t) &_binary_init_start);
Since those are pointers, it seems better to simply subtract them.
(Though it would be better if we'd declared the type of
_binary_init_start/_end as uint8_t instead of char.)
If we must cast them then the correct integer to use is 'intptr_t', an
int type that's guaranteed by C99 to be long enough to store a
pointer.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top
8 years, 10 months
[PATCH] build: Require qemu >= 1.3.0 and yajl.
by Richard W.M. Jones
Require qemu >= 1.3.0, the first version that supported
`qemu-img --output=json'.
This means we require yajl (for parsing the JSON output of qemu-img),
and that in turn has consequences elsewhere.
---
README | 10 +-
builder/Makefile.am | 2 -
builder/sources.ml | 9 +-
builder/yajl-c.c | 30 -----
builder/yajl.ml | 2 -
builder/yajl.mli | 4 -
builder/yajl_tests.ml | 2 -
daemon/ldm.c | 10 --
m4/guestfs_libraries.m4 | 9 +-
src/guestfs-internal.h | 6 -
src/info.c | 349 +++---------------------------------------------
11 files changed, 25 insertions(+), 408 deletions(-)
diff --git a/README b/README
index bf5542a..b3009a0 100644
--- a/README
+++ b/README
@@ -52,9 +52,9 @@ The full requirements are described below.
| This installs the disk management tools required by the appliance. The |
| list below is *additional* packages needed on the host. |
+--------------+-------------+---+-----------------------------------------+
-| qemu | 1.2.0 | R | 1.1 may work, but has broken virtio-scsi|
+| qemu | 1.3.0 | R | 1.1 may work, but has broken virtio-scsi|
+--------------+-------------+---+-----------------------------------------+
-| qemu-img | | R | >= 2.2.0 is required for virt-v2v but |
+| qemu-img | 1.3.0 | R | >= 2.2.0 is required for virt-v2v but |
| | | | optional elsewhere |
+--------------+-------------+---+-----------------------------------------+
| kernel | 2.6.34 | R | Make sure the following are enabled |
@@ -115,6 +115,9 @@ The full requirements are described below.
| xz | | R | Used to compress disk images. |
| | | | Used by virt-builder for compression. |
+--------------+-------------+---+-----------------------------------------+
+| yajl | 2.0.4 | R | JSON parser for parsing output of |
+| | | | ldmtool and qemu-img info commands. |
++--------------+-------------+---+-----------------------------------------+
| po4a | |R/O| Required if compiling from git. |
| | | | Optional if compiling from tarball. |
| | | | For localizing man pages. |
@@ -154,9 +157,6 @@ The full requirements are described below.
+--------------+-------------+---+-----------------------------------------+
| sd-journal | | O | systemd journal library |
+--------------+-------------+---+-----------------------------------------+
-| yajl | 2.0.4 | O | JSON parser for parsing output of |
-| | | | ldmtool and qemu-img info commands. |
-+--------------+-------------+---+-----------------------------------------+
| gdisk | | O | GPT disk support. |
+--------------+-------------+---+-----------------------------------------+
| netpbm | | O | Render icons from guests. |
diff --git a/builder/Makefile.am b/builder/Makefile.am
index a2509d7..ab27442 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -286,9 +286,7 @@ TESTS = \
test-virt-index-validate.sh
check_PROGRAMS =
-if HAVE_YAJL
TESTS += test-virt-builder-list-simplestreams.sh
-endif
if ENABLE_APPLIANCE
TESTS += test-virt-builder.sh
diff --git a/builder/sources.ml b/builder/sources.ml
index 149db6f..37027d6 100644
--- a/builder/sources.ml
+++ b/builder/sources.ml
@@ -83,14 +83,7 @@ let parse_conf file =
try
(match (List.assoc ("format", None) fields) with
| "native" | "" -> FormatNative
- | "simplestreams" as fmt ->
- if not (Yajl.yajl_is_available ()) then (
- if verbose () then (
- eprintf (f_"%s: repository type '%s' not supported (missing YAJL support), skipping it\n") prog fmt;
- );
- invalid_arg fmt
- ) else
- FormatSimpleStreams
+ | "simplestreams" -> FormatSimpleStreams
| fmt ->
if verbose () then (
eprintf (f_"%s: unknown repository type '%s' in %s, skipping it\n") prog fmt file;
diff --git a/builder/yajl-c.c b/builder/yajl-c.c
index 194fa34..f34196e 100644
--- a/builder/yajl-c.c
+++ b/builder/yajl-c.c
@@ -23,18 +23,13 @@
#include <caml/memory.h>
#include <caml/mlvalues.h>
-#if HAVE_YAJL
#include <yajl/yajl_tree.h>
-#endif
#include <stdio.h>
#include <string.h>
#define Val_none (Val_int (0))
-value virt_builder_yajl_is_available (value unit);
-
-#if HAVE_YAJL
value virt_builder_yajl_tree_parse (value stringv);
static value
@@ -95,13 +90,6 @@ convert_yajl_value (yajl_val val, int level)
}
value
-virt_builder_yajl_is_available (value unit)
-{
- /* NB: noalloc */
- return Val_true;
-}
-
-value
virt_builder_yajl_tree_parse (value stringv)
{
CAMLparam1 (stringv);
@@ -124,21 +112,3 @@ virt_builder_yajl_tree_parse (value stringv)
CAMLreturn (rv);
}
-
-#else
-value virt_builder_yajl_tree_parse (value stringv) __attribute__((noreturn));
-
-value
-virt_builder_yajl_is_available (value unit)
-{
- /* NB: noalloc */
- return Val_false;
-}
-
-value
-virt_builder_yajl_tree_parse (value stringv)
-{
- caml_invalid_argument ("virt-builder was compiled without yajl support");
-}
-
-#endif
diff --git a/builder/yajl.ml b/builder/yajl.ml
index f2d5c2b..00e4dac 100644
--- a/builder/yajl.ml
+++ b/builder/yajl.ml
@@ -25,6 +25,4 @@ type yajl_val =
| Yajl_array of yajl_val array
| Yajl_bool of bool
-external yajl_is_available : unit -> bool = "virt_builder_yajl_is_available" "noalloc"
-
external yajl_tree_parse : string -> yajl_val = "virt_builder_yajl_tree_parse"
diff --git a/builder/yajl.mli b/builder/yajl.mli
index aaa9389..9771e53 100644
--- a/builder/yajl.mli
+++ b/builder/yajl.mli
@@ -25,9 +25,5 @@ type yajl_val =
| Yajl_array of yajl_val array
| Yajl_bool of bool
-val yajl_is_available : unit -> bool
-(** Is YAJL built in? If not, calling any of the other yajl_*
- functions will result in an error. *)
-
val yajl_tree_parse : string -> yajl_val
(** Parse the JSON string. *)
diff --git a/builder/yajl_tests.ml b/builder/yajl_tests.ml
index 344a8db..f5a44f2 100644
--- a/builder/yajl_tests.ml
+++ b/builder/yajl_tests.ml
@@ -134,6 +134,4 @@ let suite =
]
let () =
- if not (yajl_is_available ()) then
- exit 77;
run_test_tt_main suite
diff --git a/daemon/ldm.c b/daemon/ldm.c
index 3705aa4..71cdf46 100644
--- a/daemon/ldm.c
+++ b/daemon/ldm.c
@@ -26,16 +26,12 @@
#include <glob.h>
#include <string.h>
-#if HAVE_YAJL
#include <yajl/yajl_tree.h>
-#endif
#include "daemon.h"
#include "actions.h"
#include "optgroups.h"
-#if HAVE_YAJL
-
GUESTFSD_EXT_CMD(str_ldmtool, ldmtool);
int
@@ -441,9 +437,3 @@ do_ldmtool_volume_partitions (const char *diskgroup, const char *volume)
return parse_json_get_object_string_list (out, "partitions",
__func__, "ldmtool show volume");
}
-
-#else /* !HAVE_YAJL */
-
-OPTGROUP_LDM_NOT_AVAILABLE
-
-#endif
diff --git a/m4/guestfs_libraries.m4 b/m4/guestfs_libraries.m4
index 0187c20..c5a4a01 100644
--- a/m4/guestfs_libraries.m4
+++ b/m4/guestfs_libraries.m4
@@ -261,13 +261,8 @@ LIBS="$LIBS $LIBXML2_LIBS"
AC_CHECK_FUNCS([xmlBufferDetach])
LIBS="$old_LIBS"
-dnl Check for yajl JSON library (optional).
-PKG_CHECK_MODULES([YAJL], [yajl >= 2.0.4], [
- AC_SUBST([YAJL_CFLAGS])
- AC_SUBST([YAJL_LIBS])
- AC_DEFINE([HAVE_YAJL],[1],[Define to 1 if you have yajl.])
-],[AC_MSG_WARN([yajl not found, some features will be disabled])])
-AM_CONDITIONAL([HAVE_YAJL],[test "x$YAJL_LIBS" != "x"])
+dnl Check for yajl JSON library (required).
+PKG_CHECK_MODULES([YAJL], [yajl >= 2.0.4])
dnl Check for C++ (optional, we just use this to test the header works).
AC_PROG_CXX
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 6ba056e..26dde67 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -477,12 +477,6 @@ struct guestfs_h
*/
int unique;
- /* In src/info.c: Use new (JSON) or old (human) qemu-img info parser. */
- int qemu_img_info_parser;
-#define QEMU_IMG_INFO_UNKNOWN_PARSER 0
-#define QEMU_IMG_INFO_NEW_PARSER 1
-#define QEMU_IMG_INFO_OLD_PARSER 2
-
/*** Protocol. ***/
struct connection *conn; /* Connection to appliance. */
int msg_next_serial;
diff --git a/src/info.c b/src/info.c
index 616ef50..9791730 100644
--- a/src/info.c
+++ b/src/info.c
@@ -38,92 +38,31 @@
#include <sys/resource.h>
#endif
-#if HAVE_YAJL
#include <yajl/yajl_tree.h>
-#endif
#include "guestfs.h"
#include "guestfs-internal.h"
#include "guestfs-internal-actions.h"
-static int which_parser (guestfs_h *g);
-static char *get_disk_format (guestfs_h *g, const char *filename);
-static int64_t get_disk_virtual_size (guestfs_h *g, const char *filename);
-static int get_disk_has_backing_file (guestfs_h *g, const char *filename);
-#if HAVE_YAJL
+#ifdef HAVE_ATTRIBUTE_CLEANUP
+#define CLEANUP_YAJL_TREE_FREE __attribute__((cleanup(cleanup_yajl_tree_free)))
+
+static void
+cleanup_yajl_tree_free (void *ptr)
+{
+ yajl_tree_free (* (yajl_val *) ptr);
+}
+
+#else
+#define CLEANUP_YAJL_TREE_FREE
+#endif
+
static yajl_val get_json_output (guestfs_h *g, const char *filename);
-#endif
-static char *old_parser_disk_format (guestfs_h *g, const char *filename);
-static int64_t old_parser_disk_virtual_size (guestfs_h *g, const char *filename);
-static int old_parser_disk_has_backing_file (guestfs_h *g, const char *filename);
static void set_child_rlimits (struct command *);
char *
guestfs_impl_disk_format (guestfs_h *g, const char *filename)
{
- switch (which_parser (g)) {
- case QEMU_IMG_INFO_NEW_PARSER:
- return get_disk_format (g, filename);
- case QEMU_IMG_INFO_OLD_PARSER:
- return old_parser_disk_format (g, filename);
- case QEMU_IMG_INFO_UNKNOWN_PARSER:
- abort ();
- }
-
- abort ();
-}
-
-int64_t
-guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
-{
- switch (which_parser (g)) {
- case QEMU_IMG_INFO_NEW_PARSER:
- return get_disk_virtual_size (g, filename);
- case QEMU_IMG_INFO_OLD_PARSER:
- return old_parser_disk_virtual_size (g, filename);
- case QEMU_IMG_INFO_UNKNOWN_PARSER:
- abort ();
- }
-
- abort ();
-}
-
-int
-guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
-{
- switch (which_parser (g)) {
- case QEMU_IMG_INFO_NEW_PARSER:
- return get_disk_has_backing_file (g, filename);
- case QEMU_IMG_INFO_OLD_PARSER:
- return old_parser_disk_has_backing_file (g, filename);
- case QEMU_IMG_INFO_UNKNOWN_PARSER:
- abort ();
- }
-
- abort ();
-}
-
-#if HAVE_YAJL
-
-# ifdef HAVE_ATTRIBUTE_CLEANUP
-# define CLEANUP_YAJL_TREE_FREE __attribute__((cleanup(cleanup_yajl_tree_free)))
-
-static void
-cleanup_yajl_tree_free (void *ptr)
-{
- yajl_tree_free (* (yajl_val *) ptr);
-}
-
-# else
-# define CLEANUP_YAJL_TREE_FREE
-# endif
-#endif
-
-static char *
-get_disk_format (guestfs_h *g, const char *filename)
-{
-#if HAVE_YAJL
-
size_t i, len;
CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
@@ -150,17 +89,11 @@ get_disk_format (guestfs_h *g, const char *filename)
bad_type:
error (g, _("qemu-img info: JSON output did not contain 'format' key"));
return NULL;
-
-#else /* !HAVE_YAJL */
- abort ();
-#endif /* !HAVE_YAJL */
}
-static int64_t
-get_disk_virtual_size (guestfs_h *g, const char *filename)
+int64_t
+guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
{
-#if HAVE_YAJL
-
size_t i, len;
CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
@@ -189,17 +122,11 @@ get_disk_virtual_size (guestfs_h *g, const char *filename)
bad_type:
error (g, _("qemu-img info: JSON output did not contain 'virtual-size' key"));
return -1;
-
-#else /* !HAVE_YAJL */
- abort ();
-#endif /* !HAVE_YAJL */
}
-static int
-get_disk_has_backing_file (guestfs_h *g, const char *filename)
+int
+guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
{
-#if HAVE_YAJL
-
size_t i, len;
CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
@@ -227,14 +154,8 @@ get_disk_has_backing_file (guestfs_h *g, const char *filename)
bad_type:
error (g, _("qemu-img info: JSON output was not an object"));
return -1;
-
-#else /* !HAVE_YAJL */
- abort ();
-#endif /* !HAVE_YAJL */
}
-#if HAVE_YAJL
-
/* Run 'qemu-img info --output json filename', and parse the output
* as JSON, returning a JSON tree and handling errors.
*/
@@ -332,242 +253,6 @@ parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
}
}
-static void help_contains_output_json (guestfs_h *g, void *datav, const char *help_line, size_t len);
-
-/* Choose new (JSON) or old (human) parser? */
-static int
-which_parser (guestfs_h *g)
-{
- if (g->qemu_img_info_parser == QEMU_IMG_INFO_UNKNOWN_PARSER) {
- int qemu_img_supports_json = 0;
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
-
- guestfs_int_cmd_add_arg (cmd, "qemu-img");
- guestfs_int_cmd_add_arg (cmd, "--help");
- guestfs_int_cmd_set_stdout_callback (cmd,
- help_contains_output_json,
- &qemu_img_supports_json, 0);
- guestfs_int_cmd_run (cmd);
- /* ignore return code, which would usually be 1 */
-
- if (qemu_img_supports_json)
- g->qemu_img_info_parser = QEMU_IMG_INFO_NEW_PARSER;
- else
- g->qemu_img_info_parser = QEMU_IMG_INFO_OLD_PARSER;
- }
-
- debug (g, "%s: g->qemu_img_info_parser = %d",
- __func__, g->qemu_img_info_parser);
-
- return g->qemu_img_info_parser;
-}
-
-static void
-help_contains_output_json (guestfs_h *g, void *datav,
- const char *help_line, size_t len)
-{
- if (strstr (help_line, "--output") != NULL &&
- strstr (help_line, "json") != NULL) {
- * (int *) datav = 1;
- }
-}
-
-#else /* !HAVE_YAJL */
-
-/* With no YAJL, only the old parser is available. */
-static int
-which_parser (guestfs_h *g)
-{
- return g->qemu_img_info_parser = QEMU_IMG_INFO_OLD_PARSER;
-}
-
-#endif /* !HAVE_YAJL */
-
-/*----------------------------------------------------------------------
- * This is the old parser for the old / human-readable output of
- * qemu-img info, ONLY used if EITHER you've got an old version of
- * qemu-img, OR you're not using yajl. It is highly recommended that
- * you upgrade qemu-img and install yajl so that you can use the new,
- * secure JSON parser above.
- */
-
-static int old_parser_run_qemu_img_info (guestfs_h *g, const char *filename, cmd_stdout_callback cb, void *data);
-
-/* NB: For security reasons, the check_* callbacks MUST bail
- * after seeing the first line that matches /^backing file: /. See:
- * https://lists.gnu.org/archive/html/qemu-devel/2012-09/msg00137.html
- */
-
-struct old_parser_check_data {
- int stop, failed;
- union {
- char *ret;
- int reti;
- int64_t reti64;
- };
-};
-
-static void old_parser_check_disk_format (guestfs_h *g, void *data, const char *line, size_t len);
-static void old_parser_check_disk_virtual_size (guestfs_h *g, void *data, const char *line, size_t len);
-static void old_parser_check_disk_has_backing_file (guestfs_h *g, void *data, const char *line, size_t len);
-
-static char *
-old_parser_disk_format (guestfs_h *g, const char *filename)
-{
- struct old_parser_check_data data;
-
- memset (&data, 0, sizeof data);
-
- if (old_parser_run_qemu_img_info (g, filename,
- old_parser_check_disk_format,
- &data) == -1) {
- free (data.ret);
- return NULL;
- }
-
- if (data.ret == NULL)
- data.ret = safe_strdup (g, "unknown");
-
- return data.ret;
-}
-
-static void
-old_parser_check_disk_format (guestfs_h *g, void *datav,
- const char *line, size_t len)
-{
- struct old_parser_check_data *data = datav;
- const char *p;
-
- if (data->stop)
- return;
-
- if (STRPREFIX (line, "backing file: ")) {
- data->stop = 1;
- return;
- }
-
- if (STRPREFIX (line, "file format: ")) {
- p = &line[13];
- data->ret = safe_strdup (g, p);
- data->stop = 1;
- }
-}
-
-static int64_t
-old_parser_disk_virtual_size (guestfs_h *g, const char *filename)
-{
- struct old_parser_check_data data;
-
- memset (&data, 0, sizeof data);
-
- if (old_parser_run_qemu_img_info (g, filename,
- old_parser_check_disk_virtual_size,
- &data) == -1)
- return -1;
-
- if (data.failed)
- error (g, _("%s: cannot detect virtual size of disk image"), filename);
-
- return data.reti64;
-}
-
-static void
-old_parser_check_disk_virtual_size (guestfs_h *g, void *datav,
- const char *line, size_t len)
-{
- struct old_parser_check_data *data = datav;
- const char *p;
-
- if (data->stop)
- return;
-
- if (STRPREFIX (line, "backing file: ")) {
- data->stop = 1;
- return;
- }
-
- if (STRPREFIX (line, "virtual size: ")) {
- /* "virtual size: 500M (524288000 bytes)\n" */
- p = &line[14];
- p = strchr (p, ' ');
- if (!p || p[1] != '(' || sscanf (&p[2], "%" SCNi64, &data->reti64) != 1)
- data->failed = 1;
- data->stop = 1;
- }
-}
-
-static int
-old_parser_disk_has_backing_file (guestfs_h *g, const char *filename)
-{
- struct old_parser_check_data data;
-
- memset (&data, 0, sizeof data);
-
- if (old_parser_run_qemu_img_info (g, filename,
- old_parser_check_disk_has_backing_file,
- &data) == -1)
- return -1;
-
- return data.reti;
-}
-
-static void
-old_parser_check_disk_has_backing_file (guestfs_h *g, void *datav,
- const char *line, size_t len)
-{
- struct old_parser_check_data *data = datav;
-
- if (data->stop)
- return;
-
- if (STRPREFIX (line, "backing file: ")) {
- data->reti = 1;
- data->stop = 1;
- }
-}
-
-static int
-old_parser_run_qemu_img_info (guestfs_h *g, const char *filename,
- cmd_stdout_callback fn, void *data)
-{
- CLEANUP_FREE char *abs_filename = NULL;
- CLEANUP_FREE char *safe_filename = NULL;
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
- int r;
-
- if (guestfs_int_lazy_make_tmpdir (g) == -1)
- return -1;
-
- safe_filename = safe_asprintf (g, "%s/format.%d", g->tmpdir, ++g->unique);
-
- /* 'filename' must be an absolute path so we can link to it. */
- abs_filename = realpath (filename, NULL);
- if (abs_filename == NULL) {
- perrorf (g, "realpath");
- return -1;
- }
-
- if (symlink (abs_filename, safe_filename) == -1) {
- perrorf (g, "symlink");
- return -1;
- }
-
- guestfs_int_cmd_add_arg (cmd, "qemu-img");
- guestfs_int_cmd_add_arg (cmd, "info");
- guestfs_int_cmd_add_arg (cmd, safe_filename);
- guestfs_int_cmd_set_stdout_callback (cmd, fn, data, 0);
- set_child_rlimits (cmd);
- r = guestfs_int_cmd_run (cmd);
- if (r == -1)
- return -1;
- if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
- guestfs_int_external_command_failed (g, r, "qemu-img info", filename);
- return -1;
- }
-
- return 0;
-}
-
static void
set_child_rlimits (struct command *cmd)
{
--
2.5.0
8 years, 10 months
Hyper-V v2v
by Kevin C
Hi list,
What is the best method to migrate Hyper-V 2012 VM to oVirt/RHEV ? I
made a v2v livecd, but it never load consoles and never launch p2v
service (works well with BIOS VM or hardware, but G2 HyperV VM needs EFI
to boot).
I must add some packages on my system to build an EL7 (kmod-hfsplus from
elrepo) and some other to boot on EFI :
#boot EFI
grub2
grub2-efi
grub2-efi-modules
grub2-tools
efibootmgr
shim
hfsplus-tools
Regards,
Kevin C
8 years, 10 months