Blame SOURCES/0166-v2v-o-libvirt-Check-if-the-domain-exists-on-the-targ.patch

ffd6ed
From ff74f692fdeb34f7e315cd94c4675b9f78c40baa Mon Sep 17 00:00:00 2001
ffd6ed
From: "Richard W.M. Jones" <rjones@redhat.com>
ffd6ed
Date: Tue, 5 May 2015 16:11:46 +0100
ffd6ed
Subject: [PATCH] v2v: -o libvirt: Check if the domain exists on the target
ffd6ed
 (RHBZ#889082).
ffd6ed
ffd6ed
(cherry picked from commit badfc2e9b2a56fd5bac849a6edca4fec823abeea)
ffd6ed
---
ffd6ed
 v2v/domainxml-c.c     | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
ffd6ed
 v2v/domainxml.ml      |  2 ++
ffd6ed
 v2v/domainxml.mli     |  6 +++++
ffd6ed
 v2v/output_libvirt.ml |  5 ++++
ffd6ed
 4 files changed, 78 insertions(+)
ffd6ed
ffd6ed
diff --git a/v2v/domainxml-c.c b/v2v/domainxml-c.c
ffd6ed
index 2aebc5c..ea93c41 100644
ffd6ed
--- a/v2v/domainxml-c.c
ffd6ed
+++ b/v2v/domainxml-c.c
ffd6ed
@@ -416,6 +416,71 @@ v2v_capabilities (value connv, value unitv)
ffd6ed
   CAMLreturn (capabilitiesv);
ffd6ed
 }
ffd6ed
 
ffd6ed
+value
ffd6ed
+v2v_domain_exists (value connv, value domnamev)
ffd6ed
+{
ffd6ed
+  CAMLparam2 (connv, domnamev);
ffd6ed
+  const char *conn_uri = NULL;
ffd6ed
+  const char *domname;
ffd6ed
+  /* We have to assemble the error on the stack because a dynamic
ffd6ed
+   * string couldn't be freed.
ffd6ed
+   */
ffd6ed
+  char errmsg[256];
ffd6ed
+  virErrorPtr err;
ffd6ed
+  virConnectPtr conn;
ffd6ed
+  virDomainPtr dom;
ffd6ed
+  int domain_exists;
ffd6ed
+
ffd6ed
+  if (connv != Val_int (0))
ffd6ed
+    conn_uri = String_val (Field (connv, 0)); /* Some conn */
ffd6ed
+
ffd6ed
+  /* We have to call the default authentication handler, not least
ffd6ed
+   * since it handles all the PolicyKit crap.  However it also makes
ffd6ed
+   * coding this simpler.
ffd6ed
+   */
ffd6ed
+  conn = virConnectOpenAuth (conn_uri, virConnectAuthPtrDefault,
ffd6ed
+                             VIR_CONNECT_RO);
ffd6ed
+  if (conn == NULL) {
ffd6ed
+    if (conn_uri)
ffd6ed
+      snprintf (errmsg, sizeof errmsg,
ffd6ed
+                _("cannot open libvirt connection '%s'"), conn_uri);
ffd6ed
+    else
ffd6ed
+      snprintf (errmsg, sizeof errmsg, _("cannot open libvirt connection"));
ffd6ed
+    caml_invalid_argument (errmsg);
ffd6ed
+  }
ffd6ed
+
ffd6ed
+  /* Suppress default behaviour of printing errors to stderr.  Note
ffd6ed
+   * you can't set this to NULL to ignore errors; setting it to NULL
ffd6ed
+   * restores the default error handler ...
ffd6ed
+   */
ffd6ed
+  virConnSetErrorFunc (conn, NULL, ignore_errors);
ffd6ed
+
ffd6ed
+  /* Look up the domain. */
ffd6ed
+  domname = String_val (domnamev);
ffd6ed
+  dom = virDomainLookupByName (conn, domname);
ffd6ed
+
ffd6ed
+  if (dom) {
ffd6ed
+    domain_exists = 1;
ffd6ed
+    virDomainFree (dom);
ffd6ed
+  }
ffd6ed
+  else {
ffd6ed
+    err = virGetLastError ();
ffd6ed
+    if (err->code == VIR_ERR_NO_DOMAIN)
ffd6ed
+      domain_exists = 0;
ffd6ed
+    else {
ffd6ed
+      snprintf (errmsg, sizeof errmsg,
ffd6ed
+                _("cannot find libvirt domain '%s': %s"),
ffd6ed
+                domname, err->message);
ffd6ed
+      virConnectClose (conn);
ffd6ed
+      caml_invalid_argument (errmsg);
ffd6ed
+    }
ffd6ed
+  }
ffd6ed
+
ffd6ed
+  virConnectClose (conn);
ffd6ed
+
ffd6ed
+  CAMLreturn (Val_bool (domain_exists));
ffd6ed
+}
ffd6ed
+
ffd6ed
 #else /* !HAVE_LIBVIRT */
ffd6ed
 
ffd6ed
 value
ffd6ed
diff --git a/v2v/domainxml.ml b/v2v/domainxml.ml
ffd6ed
index 3357856..1e7f27b 100644
ffd6ed
--- a/v2v/domainxml.ml
ffd6ed
+++ b/v2v/domainxml.ml
ffd6ed
@@ -24,3 +24,5 @@ external pool_dumpxml : ?conn:string -> string -> string = "v2v_pool_dumpxml"
ffd6ed
 external vol_dumpxml : ?conn:string -> string -> string -> string = "v2v_vol_dumpxml"
ffd6ed
 
ffd6ed
 external capabilities : ?conn:string -> unit -> string = "v2v_capabilities"
ffd6ed
+
ffd6ed
+external domain_exists : ?conn:string -> string -> bool = "v2v_domain_exists"
ffd6ed
diff --git a/v2v/domainxml.mli b/v2v/domainxml.mli
ffd6ed
index 089b793..a689621 100644
ffd6ed
--- a/v2v/domainxml.mli
ffd6ed
+++ b/v2v/domainxml.mli
ffd6ed
@@ -43,3 +43,9 @@ val vol_dumpxml : ?conn:string -> string -> string -> string
ffd6ed
 val capabilities : ?conn:string -> unit -> string
ffd6ed
 (** [capabilities ?conn ()] returns the libvirt capabilities XML.
ffd6ed
     The optional [?conn] parameter is the libvirt connection URI. *)
ffd6ed
+
ffd6ed
+val domain_exists : ?conn:string -> string -> bool
ffd6ed
+(** [domain_exists ?conn dom] returns a boolean indicating if the
ffd6ed
+    the libvirt XML domain [dom] exists.
ffd6ed
+    The optional [?conn] parameter is the libvirt connection URI.
ffd6ed
+    [dom] may be a guest name, but not a UUID. *)
ffd6ed
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
ffd6ed
index b516d51..23e881a 100644
ffd6ed
--- a/v2v/output_libvirt.ml
ffd6ed
+++ b/v2v/output_libvirt.ml
ffd6ed
@@ -339,6 +339,11 @@ class output_libvirt verbose oc output_pool = object
ffd6ed
      *)
ffd6ed
     capabilities_doc <- Some doc;
ffd6ed
 
ffd6ed
+    (* Does the domain already exist on the target?  (RHBZ#889082) *)
ffd6ed
+    if Domainxml.domain_exists ?conn:oc source.s_name then
ffd6ed
+      error (f_"a libvirt domain called '%s' already exists on the target.\n\nIf using virt-v2v directly, use the '-on' option to select a different name. If using virt-p2v, select a different 'Name' in the 'Target properties'. Or delete the existing domain on the target using the 'virsh undefine' command.")
ffd6ed
+            source.s_name;
ffd6ed
+
ffd6ed
     (* Connect to output libvirt instance and check that the pool exists
ffd6ed
      * and dump out its XML.
ffd6ed
      *)
ffd6ed
-- 
ffd6ed
1.8.3.1
ffd6ed