Merge "Improve message and logging for corrupt VHD footers"
This commit is contained in:
commit
04c446f575
|
@ -15,6 +15,7 @@
|
||||||
"""Various utilities used by XenServer plugins."""
|
"""Various utilities used by XenServer plugins."""
|
||||||
|
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
import errno
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shlex
|
import shlex
|
||||||
|
@ -24,6 +25,7 @@ import tempfile
|
||||||
|
|
||||||
import XenAPIPlugin
|
import XenAPIPlugin
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
CHUNK_SIZE = 8192
|
CHUNK_SIZE = 8192
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,18 +34,18 @@ def delete_if_exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
logging.warning("'%s' was already deleted, skipping delete" % path)
|
LOG.warning("'%s' was already deleted, skipping delete" % path)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def _link(src, dst):
|
def _link(src, dst):
|
||||||
logging.info("Hard-linking file '%s' -> '%s'" % (src, dst))
|
LOG.info("Hard-linking file '%s' -> '%s'" % (src, dst))
|
||||||
os.link(src, dst)
|
os.link(src, dst)
|
||||||
|
|
||||||
|
|
||||||
def _rename(src, dst):
|
def _rename(src, dst):
|
||||||
logging.info("Renaming file '%s' -> '%s'" % (src, dst))
|
LOG.info("Renaming file '%s' -> '%s'" % (src, dst))
|
||||||
os.rename(src, dst)
|
os.rename(src, dst)
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,14 +56,14 @@ def make_subprocess(cmdline, stdout=False, stderr=False, stdin=False,
|
||||||
# NOTE(dprince): shlex python 2.4 doesn't like unicode so we
|
# NOTE(dprince): shlex python 2.4 doesn't like unicode so we
|
||||||
# explicitly convert to ascii
|
# explicitly convert to ascii
|
||||||
cmdline = cmdline.encode('ascii')
|
cmdline = cmdline.encode('ascii')
|
||||||
logging.info("Running cmd '%s'" % cmdline)
|
LOG.info("Running cmd '%s'" % cmdline)
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
kwargs['stdout'] = stdout and subprocess.PIPE or None
|
kwargs['stdout'] = stdout and subprocess.PIPE or None
|
||||||
kwargs['stderr'] = stderr and subprocess.PIPE or None
|
kwargs['stderr'] = stderr and subprocess.PIPE or None
|
||||||
kwargs['stdin'] = stdin and subprocess.PIPE or None
|
kwargs['stdin'] = stdin and subprocess.PIPE or None
|
||||||
kwargs['universal_newlines'] = universal_newlines
|
kwargs['universal_newlines'] = universal_newlines
|
||||||
args = shlex.split(cmdline)
|
args = shlex.split(cmdline)
|
||||||
logging.info("Running args '%s'" % args)
|
LOG.info("Running args '%s'" % args)
|
||||||
proc = subprocess.Popen(args, **kwargs)
|
proc = subprocess.Popen(args, **kwargs)
|
||||||
return proc
|
return proc
|
||||||
|
|
||||||
|
@ -162,7 +164,7 @@ def _assert_vhd_not_hidden(path):
|
||||||
out, err = finish_subprocess(query_proc, query_cmd)
|
out, err = finish_subprocess(query_proc, query_cmd)
|
||||||
|
|
||||||
for line in out.splitlines():
|
for line in out.splitlines():
|
||||||
if line.startswith('hidden'):
|
if line.lower().startswith('hidden'):
|
||||||
value = line.split(':')[1].strip()
|
value = line.split(':')[1].strip()
|
||||||
if value == "1":
|
if value == "1":
|
||||||
raise Exception(
|
raise Exception(
|
||||||
|
@ -170,8 +172,13 @@ def _assert_vhd_not_hidden(path):
|
||||||
locals())
|
locals())
|
||||||
|
|
||||||
|
|
||||||
def _validate_footer_timestamp(vdi_path):
|
def _validate_vhd(vdi_path):
|
||||||
"""
|
"""
|
||||||
|
This checks for several errors in the VHD structure.
|
||||||
|
|
||||||
|
Most notably, it checks that the timestamp in the footer is correct, but
|
||||||
|
may pick up other errors also.
|
||||||
|
|
||||||
This check ensures that the timestamps listed in the VHD footer aren't in
|
This check ensures that the timestamps listed in the VHD footer aren't in
|
||||||
the future. This can occur during a migration if the clocks on the the two
|
the future. This can occur during a migration if the clocks on the the two
|
||||||
Dom0's are out-of-sync. This would corrupt the SR if it were imported, so
|
Dom0's are out-of-sync. This would corrupt the SR if it were imported, so
|
||||||
|
@ -183,13 +190,30 @@ def _validate_footer_timestamp(vdi_path):
|
||||||
check_proc, check_cmd, ok_exit_codes=[0, 22])
|
check_proc, check_cmd, ok_exit_codes=[0, 22])
|
||||||
first_line = out.splitlines()[0].strip()
|
first_line = out.splitlines()[0].strip()
|
||||||
|
|
||||||
if 'primary footer invalid' in first_line:
|
if 'invalid' in first_line:
|
||||||
raise Exception("VDI '%(vdi_path)s' has timestamp in the future,"
|
if 'footer' in first_line:
|
||||||
" ensure source and destination host machines have"
|
part = 'footer'
|
||||||
" time set correctly" % locals())
|
elif 'header' in first_line:
|
||||||
elif check_proc.returncode != 0:
|
part = 'header'
|
||||||
raise Exception("Unexpected output '%(out)s' from vhd-util" %
|
else:
|
||||||
locals())
|
part = 'setting'
|
||||||
|
|
||||||
|
details = first_line.split(':', 1)
|
||||||
|
if len(details) == 2:
|
||||||
|
details = details[1]
|
||||||
|
else:
|
||||||
|
details = first_line
|
||||||
|
|
||||||
|
extra = ''
|
||||||
|
if 'timestamp' in first_line:
|
||||||
|
extra = (" ensure source and destination host machines have "
|
||||||
|
"time set correctly")
|
||||||
|
|
||||||
|
LOG.info("VDI Error details: %s" % out)
|
||||||
|
|
||||||
|
raise Exception(
|
||||||
|
"VDI '%(vdi_path)s' has an invalid %(part)s: '%(details)s'"
|
||||||
|
"%(extra)s" % locals())
|
||||||
|
|
||||||
|
|
||||||
def _validate_vdi_chain(vdi_path):
|
def _validate_vdi_chain(vdi_path):
|
||||||
|
@ -219,7 +243,7 @@ def _validate_vdi_chain(vdi_path):
|
||||||
|
|
||||||
cur_path = vdi_path
|
cur_path = vdi_path
|
||||||
while cur_path:
|
while cur_path:
|
||||||
_validate_footer_timestamp(cur_path)
|
_validate_vhd(cur_path)
|
||||||
cur_path = get_parent_path(cur_path)
|
cur_path = get_parent_path(cur_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue