From bfdae32efbeffcb74e7b2a0c48cb89cbf4c11329 Mon Sep 17 00:00:00 2001 From: John Garbutt Date: Tue, 26 Aug 2014 17:05:58 +0100 Subject: [PATCH] XenAPI: run vhd-util repair if VHD check fails We can hit issues with corrupted VHDs if we copy a VHD while XenServer is performing other operations. This happens because there are times when we copy the VHD chains while XenServer is still performing a coalesce of the VHD chain. In most cases, vhd-util should be able to safely repair any metadata corruption. It can copy the copy of the VHD footer at the front of the VHD file and add it at the bottom on the VHD file. There is no VM data loss, due to the way the coalesce happens, but the chain will be bigger than it would be both before and after the coalesce. This does not, however, ensure that snapshots are valid before uploading them to glance. But should you launch a corrupted snapshot, this change would fix up the snapshot, and allow it to boot correctly. Closes-Bug: #1362595 Change-Id: I88b737d7e97964a9db5ccf2c39dea7fd0701ead4 --- .../xenapi/etc/xapi.d/plugins/utils.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py index 4e21ed1c5066..deaf158c8b75 100644 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py @@ -214,6 +214,13 @@ def _assert_vhd_not_hidden(path): "VHD %s is marked as hidden without child" % path) +def _vhd_util_check(vdi_path): + check_cmd = ["vhd-util", "check", "-n", vdi_path, "-p"] + out = run_command(check_cmd, ok_exit_codes=[0, 22]) + first_line = out.splitlines()[0].strip() + return out, first_line + + def _validate_vhd(vdi_path): """This checks for several errors in the VHD structure. @@ -225,9 +232,13 @@ def _validate_vhd(vdi_path): Dom0's are out-of-sync. This would corrupt the SR if it were imported, so generate an exception to bail. """ - check_cmd = ["vhd-util", "check", "-n", vdi_path, "-p"] - out = run_command(check_cmd, ok_exit_codes=[0, 22]) - first_line = out.splitlines()[0].strip() + out, first_line = _vhd_util_check(vdi_path) + + if 'invalid' in first_line: + LOG.warning("VHD invalid, attempting repair.") + repair_cmd = ["vhd-util", "repair", "-n", vdi_path] + run_command(repair_cmd) + out, first_line = _vhd_util_check(vdi_path) if 'invalid' in first_line: if 'footer' in first_line: @@ -255,6 +266,8 @@ def _validate_vhd(vdi_path): "%(extra)s" % {'vdi_path': vdi_path, 'part': part, 'details': details, 'extra': extra}) + LOG.info("VDI is valid: %s" % vdi_path) + def _validate_vdi_chain(vdi_path): """This check ensures that the parent pointers on the VHDs are valid