[Libguestfs] [PATCH 3/8] v2v: -o rhv-upload: improve lookup of specified resources (RHBZ#1612653)

Pino Toscano ptoscano at redhat.com
Mon Sep 16 17:13:46 UTC 2019


Improve the way the precheck script checks for the specified resources:
- look directly for a data center with the specified storage domain
- get the storage domain object from the storage domains attached to the
  data center found
- similarly, look for the specified cluster among the ones attached to
  the data center found
When everything is found, return the UUID of the storage domain, and of
the cluster back to virt-v2v, which will store them.

Similarly, rework the createvm script to directly get the requested
cluster, instead of looking for it once again.  Also, since the UUID of
the storage domain is available in virt-v2v already, use it directly
instead of using a placeholder.

This should fix a number of issues:
- unexisting/unattached storage domains are rejected outright
- the cluster is rejected if not part of the same data center of the
  selected storage domain
- renaming the specified storage domain during the data copying will not
  cause the conversion to fail (which will still use the specified
  storage domain, no matter the new name)
---
 v2v/output_rhv_upload.ml   | 24 +++++++++++++++++++-----
 v2v/rhv-upload-createvm.py | 11 ++++-------
 v2v/rhv-upload-precheck.py | 30 ++++++++++++++++++++++++------
 3 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml
index e74a897b9..5599ef2c2 100644
--- a/v2v/output_rhv_upload.ml
+++ b/v2v/output_rhv_upload.ml
@@ -223,6 +223,11 @@ See also the virt-v2v-output-rhv(1) manual.")
 object
   inherit output
 
+  (* The storage domain UUID. *)
+  val mutable rhv_storagedomain_uuid = None
+  (* The cluster UUID. *)
+  val mutable rhv_cluster_uuid = None
+
   method precheck () =
     Python_script.error_unless_python_interpreter_found ();
     error_unless_ovirtsdk4_module_available ();
@@ -237,6 +242,10 @@ object
     let json = JSON_parser.json_parser_tree_parse_file precheck_fn in
     debug "precheck output parsed as: %s"
           (JSON.string_of_doc ~fmt:JSON.Indented ["", json]);
+    rhv_storagedomain_uuid <-
+       Some (JSON_parser.object_get_string "rhv_storagedomain_uuid" json);
+    rhv_cluster_uuid <-
+       Some (JSON_parser.object_get_string "rhv_cluster_uuid" json);
     if have_selinux then
       error_unless_nbdkit_compiled_with_selinux ()
 
@@ -383,11 +392,11 @@ If the messages above are not sufficient to diagnose the problem then add the 
           diskid
       ) targets in
 
-    (* We don't have the storage domain UUID, but instead we write
-     * in a magic value which the Python code (which can get it)
-     * will substitute.
-     *)
-    let sd_uuid = "@SD_UUID@" in
+    (* The storage domain UUID. *)
+    let sd_uuid =
+      match rhv_storagedomain_uuid with
+      | None -> assert false
+      | Some uuid -> uuid in
 
     (* The volume and VM UUIDs are made up. *)
     let vol_uuids = List.map (fun _ -> uuidgen ()) targets
@@ -401,6 +410,11 @@ If the messages above are not sufficient to diagnose the problem then add the 
                             OVirt in
     let ovf = DOM.doc_to_string ovf in
 
+    let json_params =
+      match rhv_cluster_uuid with
+      | None -> assert false
+      | Some uuid -> ("rhv_cluster_uuid", JSON.String uuid) :: json_params in
+
     let ovf_file = tmpdir // "vm.ovf" in
     with_open_out ovf_file (fun chan -> output_string chan ovf);
     if Python_script.run_command createvm_script json_params [ovf_file] <> 0
diff --git a/v2v/rhv-upload-createvm.py b/v2v/rhv-upload-createvm.py
index 1d0e8c95d..ed57a9b20 100644
--- a/v2v/rhv-upload-createvm.py
+++ b/v2v/rhv-upload-createvm.py
@@ -65,17 +65,14 @@ connection = sdk.Connection(
 
 system_service = connection.system_service()
 
-# Get the storage domain UUID and substitute it into the OVF doc.
-sds_service = system_service.storage_domains_service()
-sd = sds_service.list(search=("name=%s" % params['output_storage']))[0]
-sd_uuid = sd.id
-
-ovf = ovf.replace("@SD_UUID@", sd_uuid)
+# Get the cluster.
+cluster = system_service.clusters_service().cluster_service(params['rhv_cluster_uuid'])
+cluster = cluster.get()
 
 vms_service = system_service.vms_service()
 vm = vms_service.add(
     types.Vm(
-        cluster=types.Cluster(name = params['rhv_cluster']),
+        cluster=cluster,
         initialization=types.Initialization(
             configuration = types.Configuration(
                 type = types.ConfigurationType.OVA,
diff --git a/v2v/rhv-upload-precheck.py b/v2v/rhv-upload-precheck.py
index a317d997c..9ccfd1fdf 100644
--- a/v2v/rhv-upload-precheck.py
+++ b/v2v/rhv-upload-precheck.py
@@ -60,18 +60,36 @@ connection = sdk.Connection(
 
 system_service = connection.system_service()
 
-# Check whether the specified cluster exists.
-clusters_service = system_service.clusters_service()
-clusters = clusters_service.list(
-    search='name=%s' % params['rhv_cluster'],
+# Check whether there is a datacenter for the specified storage.
+data_centers = system_service.data_centers_service().list(
+    search='storage.name=%s' % params['output_storage'],
     case_sensitive=True,
 )
+if len(data_centers) == 0:
+    # The storage domain is not attached to a datacenter
+    # (shouldn't happen, would fail on disk creation).
+    raise RuntimeError("The storage domain ‘%s’ is not attached to a DC" %
+                       (params['output_storage']))
+datacenter = data_centers[0]
+
+# Get the storage domain.
+storage_domains = connection.follow_link(datacenter.storage_domains)
+storage_domain = [sd for sd in storage_domains if sd.name == params['output_storage']][0]
+
+# Get the cluster.
+clusters = connection.follow_link(datacenter.clusters)
+clusters = [cluster for cluster in clusters if cluster.name == params['rhv_cluster']]
 if len(clusters) == 0:
-    raise RuntimeError("The cluster ‘%s’ does not exist" %
-                       (params['rhv_cluster']))
+    raise RuntimeError("The cluster ‘%s’ is not part of the DC ‘%s’, "
+                       "where the storage domain ‘%s’ is" %
+                       (params['rhv_cluster'], datacenter.name,
+                        params['output_storage']))
+cluster = clusters[0]
 
 # Otherwise everything is OK, print a JSON with the results.
 results = {
+  "rhv_storagedomain_uuid": storage_domain.id,
+  "rhv_cluster_uuid": cluster.id,
 }
 
 json.dump(results, sys.stdout)
-- 
2.21.0




More information about the Libguestfs mailing list