Blob Blame History Raw
From fe36f57d5f5c19d17c29e04c68526eb4b0118db6 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
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 <config.h>
 
@@ -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