mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Ian Campbell <Ian.Campbell@citrix.com> CC: Ian Jackson <Ian.Jackson@eu.citrix.com> CC: Wei Liu <wei.liu2@citrix.com> --- This is exceedingly useful for development, but not of practical use being installed into a production dom0.
175 lines
4.8 KiB
Python
Executable File
175 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" Verify a v2 format migration stream """
|
|
|
|
import sys
|
|
import struct
|
|
import os, os.path
|
|
import syslog
|
|
import traceback
|
|
|
|
from xen.migration.verify import StreamError, RecordError
|
|
from xen.migration.libxc import VerifyLibxc
|
|
from xen.migration.libxl import VerifyLibxl
|
|
|
|
fin = None # Input file/fd
|
|
log_to_syslog = False # Boolean - Log to syslog instead of stdout/err?
|
|
verbose = False # Boolean - Summarise stream contents
|
|
quiet = False # Boolean - Suppress error printing
|
|
|
|
def info(msg):
|
|
"""Info message, routed to appropriate destination"""
|
|
if not quiet and verbose:
|
|
if log_to_syslog:
|
|
for line in msg.split("\n"):
|
|
syslog.syslog(syslog.LOG_INFO, line)
|
|
else:
|
|
print msg
|
|
|
|
def err(msg):
|
|
"""Error message, routed to appropriate destination"""
|
|
if not quiet:
|
|
if log_to_syslog:
|
|
for line in msg.split("\n"):
|
|
syslog.syslog(syslog.LOG_ERR, line)
|
|
print >> sys.stderr, msg
|
|
|
|
def stream_read(_ = None):
|
|
"""Read from input"""
|
|
return fin.read(_)
|
|
|
|
def rdexact(nr_bytes):
|
|
"""Read exactly nr_bytes from fin"""
|
|
_ = stream_read(nr_bytes)
|
|
if len(_) != nr_bytes:
|
|
raise IOError("Stream truncated")
|
|
return _
|
|
|
|
def unpack_exact(fmt):
|
|
"""Unpack a format from fin"""
|
|
sz = struct.calcsize(fmt)
|
|
return struct.unpack(fmt, rdexact(sz))
|
|
|
|
|
|
def skip_xl_header():
|
|
"""Skip over an xl header in the stream"""
|
|
|
|
hdr = rdexact(32)
|
|
if hdr != "Xen saved domain, xl format\n \0 \r":
|
|
raise StreamError("No xl header")
|
|
|
|
_, mflags, _, optlen = unpack_exact("=IIII")
|
|
_ = rdexact(optlen)
|
|
|
|
info("Processed xl header")
|
|
|
|
if mflags & 2: # XL_MANDATORY_FLAG_STREAMv2
|
|
return "libxl"
|
|
else:
|
|
return "libxc"
|
|
|
|
def read_stream(fmt):
|
|
""" Read an entire stream """
|
|
|
|
try:
|
|
if fmt == "xl":
|
|
fmt = skip_xl_header()
|
|
|
|
if fmt == "libxc":
|
|
VerifyLibxc(info, stream_read).verify()
|
|
else:
|
|
VerifyLibxl(info, stream_read).verify()
|
|
|
|
except (IOError, StreamError, RecordError):
|
|
err("Stream Error:")
|
|
err(traceback.format_exc())
|
|
return 1
|
|
|
|
except StandardError:
|
|
err("Script Error:")
|
|
err(traceback.format_exc())
|
|
err("Please fix me")
|
|
return 2
|
|
|
|
return 0
|
|
|
|
def open_file_or_fd(val, mode, buffering):
|
|
"""
|
|
If 'val' looks like a decimal integer, open it as an fd. If not, try to
|
|
open it as a regular file.
|
|
"""
|
|
|
|
fd = -1
|
|
try:
|
|
# Does it look like an integer?
|
|
try:
|
|
fd = int(val, 10)
|
|
except ValueError:
|
|
pass
|
|
|
|
# Try to open it...
|
|
if fd != -1:
|
|
return os.fdopen(fd, mode, buffering)
|
|
else:
|
|
return open(val, mode, buffering)
|
|
|
|
except StandardError, e:
|
|
if fd != -1:
|
|
err("Unable to open fd %d: %s: %s" %
|
|
(fd, e.__class__.__name__, e))
|
|
else:
|
|
err("Unable to open file '%s': %s: %s" %
|
|
(val, e.__class__.__name__, e))
|
|
|
|
raise SystemExit(2)
|
|
|
|
def main():
|
|
""" main """
|
|
from optparse import OptionParser
|
|
global fin, quiet, verbose
|
|
|
|
# Change stdout to be line-buffered.
|
|
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
|
|
|
|
parser = OptionParser(usage = "%prog [options]",
|
|
description =
|
|
"Verify a stream according to the v2 spec")
|
|
|
|
# Optional options
|
|
parser.add_option("-i", "--in", dest = "fin", metavar = "<FD or FILE>",
|
|
default = "0",
|
|
help = "Stream to verify (defaults to stdin)")
|
|
parser.add_option("-v", "--verbose", action = "store_true", default = False,
|
|
help = "Summarise stream contents")
|
|
parser.add_option("-q", "--quiet", action = "store_true", default = False,
|
|
help = "Suppress all logging/errors")
|
|
parser.add_option("-f", "--format", dest = "format",
|
|
metavar = "<libxc|libxl|xl>", default = "libxc",
|
|
choices = ["libxc", "libxl", "xl"],
|
|
help = "Format of the incoming stream (defaults to libxc)")
|
|
parser.add_option("--syslog", action = "store_true", default = False,
|
|
help = "Log to syslog instead of stdout")
|
|
|
|
opts, _ = parser.parse_args()
|
|
|
|
if opts.syslog:
|
|
global log_to_syslog
|
|
|
|
syslog.openlog("verify-stream-v2", syslog.LOG_PID)
|
|
log_to_syslog = True
|
|
|
|
verbose = opts.verbose
|
|
quiet = opts.quiet
|
|
fin = open_file_or_fd(opts.fin, "rb", 0)
|
|
|
|
return read_stream(opts.format)
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
sys.exit(main())
|
|
except SystemExit, e:
|
|
sys.exit(e.code)
|
|
except KeyboardInterrupt:
|
|
sys.exit(2)
|