[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH 7/8] v2v: -o rhv-upload: remove uploaded disks on failure



In case the whole conversion fails, run a new Python script to cleanup
all the uploaded (and finalized) disks.
---
 v2v/Makefile.am                              |  6 ++
 v2v/output_rhv_upload.ml                     | 29 +++++++-
 v2v/output_rhv_upload_deletedisks_source.mli | 19 ++++++
 v2v/rhv-upload-deletedisks.py                | 71 ++++++++++++++++++++
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 v2v/output_rhv_upload_deletedisks_source.mli
 create mode 100644 v2v/rhv-upload-deletedisks.py

diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 067e11049..84b56d259 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -25,6 +25,7 @@ BUILT_SOURCES = \
 	$(generator_built) \
 	config.ml \
 	output_rhv_upload_createvm_source.ml \
+	output_rhv_upload_deletedisks_source.ml \
 	output_rhv_upload_plugin_source.ml \
 	output_rhv_upload_precheck_source.ml \
 	output_rhv_upload_vmcheck_source.ml
@@ -35,6 +36,7 @@ EXTRA_DIST = \
 	copy_to_local.mli \
 	embed.sh \
 	rhv-upload-createvm.py \
+	rhv-upload-deletedisks.py \
 	rhv-upload-plugin.py \
 	rhv-upload-precheck.py \
 	rhv-upload-vmcheck.py \
@@ -88,6 +90,7 @@ SOURCES_MLI = \
 	output_rhv.mli \
 	output_rhv_upload.mli \
 	output_rhv_upload_createvm_source.mli \
+	output_rhv_upload_deletedisks_source.mli \
 	output_rhv_upload_plugin_source.mli \
 	output_rhv_upload_precheck_source.mli \
 	output_rhv_upload_vmcheck_source.mli \
@@ -154,6 +157,7 @@ SOURCES_ML = \
 	output_qemu.ml \
 	output_rhv.ml \
 	output_rhv_upload_createvm_source.ml \
+	output_rhv_upload_deletedisks_source.ml \
 	output_rhv_upload_plugin_source.ml \
 	output_rhv_upload_precheck_source.ml \
 	output_rhv_upload_vmcheck_source.ml \
@@ -173,6 +177,8 @@ SOURCES_C = \
 # These files are generated and contain *.py embedded as an OCaml string.
 output_rhv_upload_createvm_source.ml: $(srcdir)/rhv-upload-createvm.py
 	$(srcdir)/embed.sh code $^ $@
+output_rhv_upload_deletedisks_source.ml: $(srcdir)/rhv-upload-deletedisks.py
+	$(srcdir)/embed.sh code $^ $@
 output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py
 	$(srcdir)/embed.sh code $^ $@
 output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py
diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml
index 0952af188..89d8e9612 100644
--- a/v2v/output_rhv_upload.ml
+++ b/v2v/output_rhv_upload.ml
@@ -107,6 +107,9 @@ class output_rhv_upload output_alloc output_conn
   let createvm_script =
     Python_script.create ~name:"rhv-upload-createvm.py"
                          Output_rhv_upload_createvm_source.code in
+  let deletedisks_script =
+    Python_script.create ~name:"rhv-upload-deletedisks.py"
+                         Output_rhv_upload_deletedisks_source.code in
 
   (* Check that the 'ovirtsdk4' Python module is available. *)
   let error_unless_ovirtsdk4_module_available () =
@@ -220,6 +223,18 @@ See also the virt-v2v-output-rhv(1) manual.")
       else args in
     args in
 
+  (* Delete disks.
+   *
+   * This ignores errors since the only time we are doing this is on
+   * the failure path.
+   *)
+  let delete_disks uuids =
+    let ids = List.map (fun uuid -> JSON.String uuid) uuids in
+    let json_params =
+      ("disk_uuids", JSON.List ids) :: json_params in
+    ignore (Python_script.run_command deletedisks_script json_params [])
+  in
+
 object
   inherit output
 
@@ -275,6 +290,13 @@ object
     if Python_script.run_command vmcheck_script json_params [] <> 0 then
       error (f_"failed vmchecks, see earlier errors");
 
+    (* Set up an at-exit handler so we delete the orphan disks on failure. *)
+    at_exit (
+      fun () ->
+        if disks_uuids <> [] then
+          delete_disks disks_uuids
+    );
+
     (* Create an nbdkit instance for each disk and set the
      * target URI to point to the NBD socket.
      *)
@@ -419,7 +441,12 @@ If the messages above are not sufficient to diagnose the problem then add the 
     with_open_out ovf_file (fun chan -> output_string chan ovf);
     if Python_script.run_command createvm_script json_params [ovf_file] <> 0
     then
-      error (f_"failed to create virtual machine, see earlier errors")
+      error (f_"failed to create virtual machine, see earlier errors");
+
+    (* The virtual machine was created successfully, so there are no disks
+     * to remove manually.
+     *)
+    disks_uuids <- []
 
 end
 
diff --git a/v2v/output_rhv_upload_deletedisks_source.mli b/v2v/output_rhv_upload_deletedisks_source.mli
new file mode 100644
index 000000000..c1bafa15b
--- /dev/null
+++ b/v2v/output_rhv_upload_deletedisks_source.mli
@@ -0,0 +1,19 @@
+(* virt-v2v
+ * Copyright (C) 2018 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val code : string
diff --git a/v2v/rhv-upload-deletedisks.py b/v2v/rhv-upload-deletedisks.py
new file mode 100644
index 000000000..7e6c819f8
--- /dev/null
+++ b/v2v/rhv-upload-deletedisks.py
@@ -0,0 +1,71 @@
+# -*- python -*-
+# oVirt or RHV upload create VM used by ‘virt-v2v -o rhv-upload’
+# Copyright (C) 2018 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import json
+import logging
+import sys
+import time
+
+from http.client import HTTPSConnection
+from urllib.parse import urlparse
+
+import ovirtsdk4 as sdk
+import ovirtsdk4.types as types
+
+# Parameters are passed in via a JSON doc from the OCaml code.
+# Because this Python code ships embedded inside virt-v2v there
+# is no formal API here.
+params = None
+
+if len(sys.argv) != 2:
+    raise RuntimeError("incorrect number of parameters")
+
+# Parameters are passed in via a JSON document.
+with open(sys.argv[1], 'r') as fp:
+    params = json.load(fp)
+
+# What is passed in is a password file, read the actual password.
+with open(params['output_password'], 'r') as fp:
+    output_password = fp.read()
+output_password = output_password.rstrip()
+
+# Parse out the username from the output_conn URL.
+parsed = urlparse(params['output_conn'])
+username = parsed.username or "admin internal"
+
+# Connect to the server.
+connection = sdk.Connection(
+    url = params['output_conn'],
+    username = username,
+    password = output_password,
+    ca_file = params['rhv_cafile'],
+    log = logging.getLogger(),
+    insecure = params['insecure'],
+)
+
+system_service = connection.system_service()
+disks_service = system_service.disks_service()
+
+for uuid in params['disk_uuids']:
+    # Try to get and remove the disk, however do not fail
+    # if it does not exist (maybe removed in the meanwhile).
+    try:
+        disk_service = disks_service.disk_service(uuid)
+        disk_service.remove()
+    except sdk.NotFoundError:
+        pass
-- 
2.21.0


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]