aboutsummaryrefslogtreecommitdiffstats
path: root/tests/qemu-iotests/qcow2.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qemu-iotests/qcow2.py')
-rwxr-xr-xtests/qemu-iotests/qcow2.py176
1 files changed, 176 insertions, 0 deletions
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
new file mode 100755
index 000000000..77ca59cc6
--- /dev/null
+++ b/tests/qemu-iotests/qcow2.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python3
+#
+# Manipulations with qcow2 image
+#
+# Copyright (C) 2012 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+
+from qcow2_format import (
+ QcowHeader,
+ QcowHeaderExtension
+)
+
+
+is_json = False
+
+
+def cmd_dump_header(fd):
+ h = QcowHeader(fd)
+ h.dump(is_json)
+ print()
+ h.dump_extensions(is_json)
+
+
+def cmd_dump_header_exts(fd):
+ h = QcowHeader(fd)
+ h.dump_extensions(is_json)
+
+
+def cmd_set_header(fd, name, value):
+ try:
+ value = int(value, 0)
+ except ValueError:
+ print("'%s' is not a valid number" % value)
+ sys.exit(1)
+
+ fields = (field[2] for field in QcowHeader.fields)
+ if name not in fields:
+ print("'%s' is not a known header field" % name)
+ sys.exit(1)
+
+ h = QcowHeader(fd)
+ h.__dict__[name] = value
+ h.update(fd)
+
+
+def cmd_add_header_ext(fd, magic, data):
+ try:
+ magic = int(magic, 0)
+ except ValueError:
+ print("'%s' is not a valid magic number" % magic)
+ sys.exit(1)
+
+ h = QcowHeader(fd)
+ h.extensions.append(QcowHeaderExtension.create(magic,
+ data.encode('ascii')))
+ h.update(fd)
+
+
+def cmd_add_header_ext_stdio(fd, magic):
+ data = sys.stdin.read()
+ cmd_add_header_ext(fd, magic, data)
+
+
+def cmd_del_header_ext(fd, magic):
+ try:
+ magic = int(magic, 0)
+ except ValueError:
+ print("'%s' is not a valid magic number" % magic)
+ sys.exit(1)
+
+ h = QcowHeader(fd)
+ found = False
+
+ for ex in h.extensions:
+ if ex.magic == magic:
+ found = True
+ h.extensions.remove(ex)
+
+ if not found:
+ print("No such header extension")
+ return
+
+ h.update(fd)
+
+
+def cmd_set_feature_bit(fd, group, bit):
+ try:
+ bit = int(bit, 0)
+ if bit < 0 or bit >= 64:
+ raise ValueError
+ except ValueError:
+ print("'%s' is not a valid bit number in range [0, 64)" % bit)
+ sys.exit(1)
+
+ h = QcowHeader(fd)
+ if group == 'incompatible':
+ h.incompatible_features |= 1 << bit
+ elif group == 'compatible':
+ h.compatible_features |= 1 << bit
+ elif group == 'autoclear':
+ h.autoclear_features |= 1 << bit
+ else:
+ print("'%s' is not a valid group, try "
+ "'incompatible', 'compatible', or 'autoclear'" % group)
+ sys.exit(1)
+
+ h.update(fd)
+
+
+cmds = [
+ ['dump-header', cmd_dump_header, 0,
+ 'Dump image header and header extensions'],
+ ['dump-header-exts', cmd_dump_header_exts, 0,
+ 'Dump image header extensions'],
+ ['set-header', cmd_set_header, 2, 'Set a field in the header'],
+ ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
+ ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
+ 'Add a header extension, data from stdin'],
+ ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
+ ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
+]
+
+
+def main(filename, cmd, args):
+ fd = open(filename, "r+b")
+ try:
+ for name, handler, num_args, desc in cmds:
+ if name != cmd:
+ continue
+ elif len(args) != num_args:
+ usage()
+ return
+ else:
+ handler(fd, *args)
+ return
+ print("Unknown command '%s'" % cmd)
+ finally:
+ fd.close()
+
+
+def usage():
+ print("Usage: %s <file> <cmd> [<arg>, ...] [<key>, ...]" % sys.argv[0])
+ print("")
+ print("Supported commands:")
+ for name, handler, num_args, desc in cmds:
+ print(" %-20s - %s" % (name, desc))
+ print("")
+ print("Supported keys:")
+ print(" %-20s - %s" % ('-j', 'Dump in JSON format'))
+
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ usage()
+ sys.exit(1)
+
+ is_json = '-j' in sys.argv
+ if is_json:
+ sys.argv.remove('-j')
+
+ main(sys.argv[1], sys.argv[2], sys.argv[3:])