mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
convert-legacy-stream is only used for incomming migration from pre Xen 4.7, and verify-stream-v2 appears to only be used by me during migration development - it is little surprise that they missed the main converstion effort in Xen 4.13. Fix it all up. Move open_file_or_fd() into a new util.py to avoid duplication, making it a more generic wrapper around open() or fdopen(). In libxc.py, drop all long() conversion. Python 2 will DTRT with int => long promotion, even on 32bit builds. In convert-legacy-stream, don't pass empty strings to write_record(). Join on the empty argl will do the right thing. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
149 lines
4.1 KiB
Python
Executable File
149 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" Verify a v2 format migration stream """
|
|
|
|
from __future__ import print_function
|
|
|
|
import sys
|
|
import struct
|
|
import os, os.path
|
|
import syslog
|
|
import traceback
|
|
|
|
from xen.util import open_file_or_fd as open_file_or_fd
|
|
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(msg, file = sys.stderr)
|
|
|
|
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 != b"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 Exception:
|
|
err("Script Error:")
|
|
err(traceback.format_exc())
|
|
err("Please fix me")
|
|
return 2
|
|
|
|
return 0
|
|
|
|
|
|
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 as e:
|
|
sys.exit(e.code)
|
|
except KeyboardInterrupt:
|
|
sys.exit(2)
|