From fe36f57d5f5c19d17c29e04c68526eb4b0118db6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 May 2015 15:55:53 +0100 Subject: [PATCH] v2v: Add a C function to fetch libvirt hypervisor capabilities. Instead of having to run external 'virsh capabilities' command and parsing the output. (cherry picked from commit e7833a5eea350ca3579d1f9e6702e116b45572fc) --- v2v/domainxml-c.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++- v2v/domainxml.ml | 5 +++- v2v/domainxml.mli | 7 +++++- v2v/output_libvirt.ml | 9 +------- 4 files changed, 74 insertions(+), 11 deletions(-) diff --git a/v2v/domainxml-c.c b/v2v/domainxml-c.c index 60157e1..2aebc5c 100644 --- a/v2v/domainxml-c.c +++ b/v2v/domainxml-c.c @@ -16,7 +16,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* [virsh dumpxml] but with non-broken authentication handling. */ +/* This module implements various [virsh]-like commands, but with + * non-broken authentication handling. + */ #include @@ -360,6 +362,60 @@ v2v_vol_dumpxml (value connv, value poolnamev, value volnamev) CAMLreturn (retv); } +value +v2v_capabilities (value connv, value unitv) +{ + CAMLparam2 (connv, unitv); + CAMLlocal1 (capabilitiesv); + const char *conn_uri = NULL; + char *capabilities; + /* We have to assemble the error on the stack because a dynamic + * string couldn't be freed. + */ + char errmsg[256]; + virErrorPtr err; + virConnectPtr conn; + + 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) + snprintf (errmsg, sizeof errmsg, + _("cannot open libvirt connection '%s'"), conn_uri); + else + snprintf (errmsg, sizeof errmsg, _("cannot open libvirt connection")); + caml_invalid_argument (errmsg); + } + + /* Suppress default behaviour of printing errors to stderr. Note + * you can't set this to NULL to ignore errors; setting it to NULL + * restores the default error handler ... + */ + virConnSetErrorFunc (conn, NULL, ignore_errors); + + capabilities = virConnectGetCapabilities (conn); + if (!capabilities) { + err = virGetLastError (); + snprintf (errmsg, sizeof errmsg, + _("cannot get libvirt hypervisor capabilities: %s"), + err->message); + virConnectClose (conn); + caml_invalid_argument (errmsg); + } + + capabilitiesv = caml_copy_string (capabilities); + free (capabilities); + + CAMLreturn (capabilitiesv); +} + #else /* !HAVE_LIBVIRT */ value @@ -380,4 +436,10 @@ v2v_vol_dumpxml (value connv, value poolnamev, value volnamev) caml_invalid_argument ("virt-v2v was compiled without libvirt support"); } +value +v2v_capabilities (value connv, value unitv) +{ + caml_invalid_argument ("virt-v2v was compiled without libvirt support"); +} + #endif /* !HAVE_LIBVIRT */ diff --git a/v2v/domainxml.ml b/v2v/domainxml.ml index d8b9ed4..3357856 100644 --- a/v2v/domainxml.ml +++ b/v2v/domainxml.ml @@ -16,8 +16,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) -(* [virsh dumpxml] but with non-broken authentication handling. *) +(* This module implements various [virsh]-like commands, but with + non-broken authentication handling. *) external dumpxml : ?password:string -> ?conn:string -> string -> string = "v2v_dumpxml" external pool_dumpxml : ?conn:string -> string -> string = "v2v_pool_dumpxml" external vol_dumpxml : ?conn:string -> string -> string -> string = "v2v_vol_dumpxml" + +external capabilities : ?conn:string -> unit -> string = "v2v_capabilities" diff --git a/v2v/domainxml.mli b/v2v/domainxml.mli index 98690fe..089b793 100644 --- a/v2v/domainxml.mli +++ b/v2v/domainxml.mli @@ -16,7 +16,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) -(** [virsh dumpxml] but with non-broken authentication handling. +(** This module implements various [virsh]-like commands, 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 @@ -38,3 +39,7 @@ val vol_dumpxml : ?conn:string -> string -> string -> string which is part of the pool [pool]. The optional [?conn] parameter is the libvirt connection URI. [pool] may be a pool name or UUID. *) + +val capabilities : ?conn:string -> unit -> string +(** [capabilities ?conn ()] returns the libvirt capabilities XML. + The optional [?conn] parameter is the libvirt connection URI. *) diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml index 48d39e2..b516d51 100644 --- a/v2v/output_libvirt.ml +++ b/v2v/output_libvirt.ml @@ -325,14 +325,7 @@ class output_libvirt verbose oc output_pool = object method prepare_targets source targets = (* Get the capabilities from libvirt. *) - let cmd = - match oc with - | None -> "virsh capabilities" - | Some uri -> sprintf "virsh -c %s capabilities" (quote uri) in - if verbose then printf "%s\n%!" cmd; - let xml = external_command ~prog cmd in - let xml = String.concat "\n" xml in - + let xml = Domainxml.capabilities ?conn:oc () in if verbose then printf "libvirt capabilities XML:\n%s\n%!" xml; (* This just checks that the capabilities XML is well-formed, -- 1.8.3.1