Validate VDI chain before moving into SR.
Fixes bug 949477 Change-Id: Ia3f283d82f189e680c5c8dd4fcf71bf5fe5f9889
This commit is contained in:
parent
70f0ea588e
commit
1da6a00a3b
@ -265,6 +265,34 @@ def _import_vhds(sr_path, staging_path, uuid_stack):
|
|||||||
link_vhds(new_path, parent_path)
|
link_vhds(new_path, parent_path)
|
||||||
return (new_path, vdi_uuid)
|
return (new_path, vdi_uuid)
|
||||||
|
|
||||||
|
def validate_vdi_chain(vdi_path):
|
||||||
|
"""
|
||||||
|
This check ensures that the parent pointers on the VHDs are valid
|
||||||
|
before we move the VDI chain to the SR. This is *very* important
|
||||||
|
because a bad parent pointer will corrupt the SR causing a cascade of
|
||||||
|
failures.
|
||||||
|
"""
|
||||||
|
def get_parent_path(path):
|
||||||
|
query_cmd = "vhd-util query -n %(path)s -p" % locals()
|
||||||
|
query_proc = _make_subprocess(query_cmd, stdout=True, stderr=True)
|
||||||
|
out, err = _finish_subprocess(
|
||||||
|
query_proc, query_cmd, ok_exit_codes=[0, 22])
|
||||||
|
first_line = out.splitlines()[0].strip()
|
||||||
|
if first_line.endswith(".vhd"):
|
||||||
|
return first_line
|
||||||
|
elif 'has no parent' in first_line:
|
||||||
|
return None
|
||||||
|
elif 'query failed' in first_line:
|
||||||
|
raise Exception("VDI '%(path)s' not present which breaks"
|
||||||
|
" the VDI chain, bailing out" % locals())
|
||||||
|
else:
|
||||||
|
raise Exception("Unexpected output '%(out)s' from vhd-util" %
|
||||||
|
locals())
|
||||||
|
|
||||||
|
cur_path = vdi_path
|
||||||
|
while cur_path:
|
||||||
|
cur_path = get_parent_path(cur_path)
|
||||||
|
|
||||||
vdi_return_list = []
|
vdi_return_list = []
|
||||||
paths_to_move = []
|
paths_to_move = []
|
||||||
|
|
||||||
@ -283,6 +311,7 @@ def _import_vhds(sr_path, staging_path, uuid_stack):
|
|||||||
snap_info = prepare_if_exists(staging_path, 'snap.vhd',
|
snap_info = prepare_if_exists(staging_path, 'snap.vhd',
|
||||||
image_info[0])
|
image_info[0])
|
||||||
if snap_info:
|
if snap_info:
|
||||||
|
validate_vdi_chain(snap_info[0])
|
||||||
# NOTE(sirp): this is an insert rather than an append since the
|
# NOTE(sirp): this is an insert rather than an append since the
|
||||||
# 'snapshot' vhd needs to be copied into the SR before the base copy.
|
# 'snapshot' vhd needs to be copied into the SR before the base copy.
|
||||||
# If it doesn't, then there is a possibliity that snapwatchd will
|
# If it doesn't, then there is a possibliity that snapwatchd will
|
||||||
@ -291,6 +320,7 @@ def _import_vhds(sr_path, staging_path, uuid_stack):
|
|||||||
# We return this snap as the VDI instead of image.vhd
|
# We return this snap as the VDI instead of image.vhd
|
||||||
vdi_return_list.append(dict(vdi_type="os", vdi_uuid=snap_info[1]))
|
vdi_return_list.append(dict(vdi_type="os", vdi_uuid=snap_info[1]))
|
||||||
else:
|
else:
|
||||||
|
validate_vdi_chain(image_info[0])
|
||||||
assert_vhd_not_hidden(image_info[0])
|
assert_vhd_not_hidden(image_info[0])
|
||||||
# If there's no snap, we return the image.vhd UUID
|
# If there's no snap, we return the image.vhd UUID
|
||||||
vdi_return_list.append(dict(vdi_type="os", vdi_uuid=image_info[1]))
|
vdi_return_list.append(dict(vdi_type="os", vdi_uuid=image_info[1]))
|
||||||
@ -439,14 +469,18 @@ def _make_subprocess(cmdline, stdout=False, stderr=False, stdin=False):
|
|||||||
return proc
|
return proc
|
||||||
|
|
||||||
|
|
||||||
def _finish_subprocess(proc, cmdline):
|
def _finish_subprocess(proc, cmdline, ok_exit_codes=None):
|
||||||
"""Ensure that the process returned a zero exit code indicating success
|
"""Ensure that the process returned a zero exit code indicating success
|
||||||
"""
|
"""
|
||||||
|
if ok_exit_codes is None:
|
||||||
|
ok_exit_codes = [0]
|
||||||
|
|
||||||
out, err = proc.communicate()
|
out, err = proc.communicate()
|
||||||
ret = proc.returncode
|
ret = proc.returncode
|
||||||
if ret != 0:
|
if ret not in ok_exit_codes:
|
||||||
raise Exception("'%(cmdline)s' returned non-zero exit code: "
|
raise Exception("'%(cmdline)s' returned non-zero exit code: "
|
||||||
"retcode=%(ret)i, stderr='%(err)s'" % locals())
|
"retcode=%(ret)i, out='%(out)s', stderr='%(err)s'"
|
||||||
|
% locals())
|
||||||
return out, err
|
return out, err
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user