mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
v2v: Work around buggy `virsh dumpxml'.
The `virsh dumpxml' command doesn't work properly when the libvirt source requires authentication. This is because the authentication prompts are sent to stdout, but stdout is also the place where we are reading the output XML from. Add a mini-binding to libvirt virDomainGetXMLDesc which avoids this, getting the XML directly using the libvirt API. Change existing external calls to `virsh dumpxml' to use this API instead.
This commit is contained in:
@@ -331,5 +331,6 @@ src/test-utils.c
|
||||
src/tmpdirs.c
|
||||
src/utils.c
|
||||
test-tool/test-tool.c
|
||||
v2v/domainxml-c.c
|
||||
v2v/utils-c.c
|
||||
v2v/xml-c.c
|
||||
|
||||
@@ -86,6 +86,7 @@ v2v/DOM.ml
|
||||
v2v/cmdline.ml
|
||||
v2v/convert_linux.ml
|
||||
v2v/convert_windows.ml
|
||||
v2v/domainxml.ml
|
||||
v2v/input_disk.ml
|
||||
v2v/input_libvirt.ml
|
||||
v2v/lib_esx.ml
|
||||
|
||||
@@ -30,6 +30,7 @@ SOURCES_MLI = \
|
||||
convert_linux.mli \
|
||||
convert_windows.mli \
|
||||
DOM.mli \
|
||||
domainxml.mli \
|
||||
lib_esx.mli \
|
||||
lib_linux.mli \
|
||||
input_disk.mli \
|
||||
@@ -45,6 +46,7 @@ SOURCES_ML = \
|
||||
types.ml \
|
||||
utils.ml \
|
||||
xml.ml \
|
||||
domainxml.ml \
|
||||
DOM.ml \
|
||||
lib_esx.ml \
|
||||
lib_linux.ml \
|
||||
@@ -65,7 +67,8 @@ SOURCES_C = \
|
||||
$(top_builddir)/mllib/mkdtemp-c.c \
|
||||
$(top_builddir)/customize/crypt-c.c \
|
||||
utils-c.c \
|
||||
xml-c.c
|
||||
xml-c.c \
|
||||
domainxml-c.c
|
||||
|
||||
if HAVE_OCAML
|
||||
|
||||
@@ -80,7 +83,8 @@ virt_v2v_CPPFLAGS = \
|
||||
-I$(top_srcdir)/fish
|
||||
virt_v2v_CFLAGS = \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
$(LIBXML2_CFLAGS) \
|
||||
$(LIBVIRT_CFLAGS)
|
||||
|
||||
BOBJECTS = \
|
||||
$(top_builddir)/mllib/common_gettext.cmo \
|
||||
|
||||
125
v2v/domainxml-c.c
Normal file
125
v2v/domainxml-c.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* virt-v2v
|
||||
* Copyright (C) 2009-2014 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.
|
||||
*/
|
||||
|
||||
/* [virsh dumpxml] but with non-broken authentication handling. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <caml/alloc.h>
|
||||
#include <caml/fail.h>
|
||||
#include <caml/memory.h>
|
||||
#include <caml/mlvalues.h>
|
||||
|
||||
#ifdef HAVE_LIBVIRT
|
||||
#include <libvirt/libvirt.h>
|
||||
#endif
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "guestfs-internal-frontend.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#ifdef HAVE_LIBVIRT
|
||||
|
||||
static void raise_error (const char *fs, ...)
|
||||
__attribute__((noreturn))
|
||||
__attribute__((format (printf,1,2)));
|
||||
|
||||
/* Note we rely on libvirt printing errors to stderr, so the exception
|
||||
* doesn't need to contain the actual error from libvirt.
|
||||
*/
|
||||
static void
|
||||
raise_error (const char *fs, ...)
|
||||
{
|
||||
va_list args;
|
||||
/* We have to assemble the error on the stack because a dynamic
|
||||
* string couldn't be freed.
|
||||
*/
|
||||
char msg[256];
|
||||
int len;
|
||||
|
||||
va_start (args, fs);
|
||||
len = vsnprintf (msg, sizeof msg, fs , args);
|
||||
va_end (args);
|
||||
|
||||
if (len < 0) caml_failwith (fs);
|
||||
|
||||
caml_invalid_argument (msg);
|
||||
}
|
||||
|
||||
value
|
||||
v2v_dumpxml (value connv, value domnamev)
|
||||
{
|
||||
CAMLparam2 (connv, domnamev);
|
||||
CAMLlocal1 (retv);
|
||||
const char *conn_uri = NULL;
|
||||
const char *domname;
|
||||
virConnectPtr conn;
|
||||
virDomainPtr dom;
|
||||
char *xml;
|
||||
|
||||
if (connv != Val_int (0))
|
||||
conn_uri = String_val (Field (connv, 0)); /* Some conn */
|
||||
|
||||
/* We have to call the default authentication handler, not least
|
||||
* since it handles all the PolicyKit crap. However it also makes
|
||||
* coding this simpler.
|
||||
*/
|
||||
conn = virConnectOpenAuth (conn_uri, virConnectAuthPtrDefault, VIR_CONNECT_RO);
|
||||
if (conn == NULL) {
|
||||
if (conn_uri)
|
||||
raise_error ("cannot open libvirt connection '%s'", conn_uri);
|
||||
else
|
||||
raise_error ("cannot open libvirt connection");
|
||||
}
|
||||
|
||||
/* Look up the domain. */
|
||||
domname = String_val (domnamev);
|
||||
|
||||
dom = virDomainLookupByName (conn, domname);
|
||||
if (!dom) {
|
||||
virConnectClose (conn);
|
||||
raise_error ("cannot find libvirt domain '%s'", domname);
|
||||
}
|
||||
|
||||
xml = virDomainGetXMLDesc (dom, 0);
|
||||
virDomainFree (dom);
|
||||
virConnectClose (conn);
|
||||
if (xml == NULL)
|
||||
raise_error ("cannot fetch XML description of guest '%s'", domname);
|
||||
|
||||
retv = caml_copy_string (xml);
|
||||
free (xml);
|
||||
|
||||
CAMLreturn (retv);
|
||||
}
|
||||
|
||||
#else /* !HAVE_LIBVIRT */
|
||||
|
||||
value
|
||||
v2v_dumpxml (value connv, value domv)
|
||||
{
|
||||
caml_invalid_argument ("virt-v2v was compiled without libvirt support");
|
||||
}
|
||||
|
||||
#endif /* !HAVE_LIBVIRT */
|
||||
21
v2v/domainxml.ml
Normal file
21
v2v/domainxml.ml
Normal file
@@ -0,0 +1,21 @@
|
||||
(* virt-v2v
|
||||
* Copyright (C) 2009-2014 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.
|
||||
*)
|
||||
|
||||
(* [virsh dumpxml] but with non-broken authentication handling. *)
|
||||
|
||||
external dumpxml : ?conn:string -> string -> string = "v2v_dumpxml"
|
||||
28
v2v/domainxml.mli
Normal file
28
v2v/domainxml.mli
Normal file
@@ -0,0 +1,28 @@
|
||||
(* virt-v2v
|
||||
* Copyright (C) 2009-2014 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.
|
||||
*)
|
||||
|
||||
(** [virsh dumpxml] but with non-broken authentication handling.
|
||||
|
||||
If you do [virsh dumpxml foo] and if the libvirt source (eg. ESX)
|
||||
requires an interactive password, then virsh unhelpfully sends the
|
||||
password prompt to stdout, which is the same place we would be
|
||||
reading the XML from. This file works around this brokenness. *)
|
||||
|
||||
val dumpxml : ?conn:string -> string -> string
|
||||
(** [dumpxml ?conn dom] returns the libvirt XML of domain [dom].
|
||||
The optional [?conn] parameter is the libvirt connection URI. *)
|
||||
@@ -311,11 +311,6 @@ let input_libvirt verbose libvirt_uri guest =
|
||||
None, None in
|
||||
|
||||
(* Get the libvirt XML. *)
|
||||
let cmd =
|
||||
match libvirt_uri with
|
||||
| None -> sprintf "virsh dumpxml %s" (quote guest)
|
||||
| Some uri -> sprintf "virsh -c %s dumpxml %s" (quote uri) (quote guest) in
|
||||
let lines = external_command ~prog cmd in
|
||||
let xml = String.concat "\n" lines in
|
||||
let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
|
||||
|
||||
new input_libvirt verbose options ?map_source_file ?map_source_dev xml
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
# Hack automake to link binary properly. There is no other way to add
|
||||
# the -cclib parameter to the end of the command line.
|
||||
|
||||
exec "$@" -linkpkg -cclib '-lutils -lncurses -lcrypt @LIBXML2_LIBS@ -lgnu'
|
||||
exec "$@" -linkpkg -cclib '-lutils -lncurses -lcrypt @LIBVIRT_LIBS@ @LIBXML2_LIBS@ -lgnu'
|
||||
|
||||
Reference in New Issue
Block a user