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