Instead of having to run external 'virsh capabilities' command and
parsing the output.
---
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 abf39f1..27b1389 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 v2v_dumpxml (value connv, value domv) __attribute__((noreturn));
@@ -386,4 +442,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 7dbfcbd..2ac304b 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 7008769..11cf48e 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 0ed7a61..8e2337d 100644
--- a/v2v/output_libvirt.ml
+++ b/v2v/output_libvirt.ml
@@ -319,14 +319,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,
--
2.3.1