xref: /openbmc/qemu/tests/qemu-iotests/qcow2.py (revision 3419ec713f04c323b030e0763459435335b25476)
1903cb1bfSPhilippe Mathieu-Daudé#!/usr/bin/env python3
216306a7bSVladimir Sementsov-Ogievskiy#
316306a7bSVladimir Sementsov-Ogievskiy# Manipulations with qcow2 image
416306a7bSVladimir Sementsov-Ogievskiy#
5*3419ec71SEric Blake# Copyright (C) 2012 Red Hat, Inc.
6*3419ec71SEric Blake#
716306a7bSVladimir Sementsov-Ogievskiy# This program is free software; you can redistribute it and/or modify
816306a7bSVladimir Sementsov-Ogievskiy# it under the terms of the GNU General Public License as published by
916306a7bSVladimir Sementsov-Ogievskiy# the Free Software Foundation; either version 2 of the License, or
1016306a7bSVladimir Sementsov-Ogievskiy# (at your option) any later version.
1116306a7bSVladimir Sementsov-Ogievskiy#
1216306a7bSVladimir Sementsov-Ogievskiy# This program is distributed in the hope that it will be useful,
1316306a7bSVladimir Sementsov-Ogievskiy# but WITHOUT ANY WARRANTY; without even the implied warranty of
1416306a7bSVladimir Sementsov-Ogievskiy# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1516306a7bSVladimir Sementsov-Ogievskiy# GNU General Public License for more details.
1616306a7bSVladimir Sementsov-Ogievskiy#
1716306a7bSVladimir Sementsov-Ogievskiy# You should have received a copy of the GNU General Public License
1816306a7bSVladimir Sementsov-Ogievskiy# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1916306a7bSVladimir Sementsov-Ogievskiy#
206e19b3c4SKevin Wolf
216e19b3c4SKevin Wolfimport sys
226e19b3c4SKevin Wolf
23d5262c71SVladimir Sementsov-Ogievskiyfrom qcow2_format import (
24d5262c71SVladimir Sementsov-Ogievskiy    QcowHeader,
25d5262c71SVladimir Sementsov-Ogievskiy    QcowHeaderExtension
26d5262c71SVladimir Sementsov-Ogievskiy)
276e19b3c4SKevin Wolf
286e19b3c4SKevin Wolf
296e19b3c4SKevin Wolfdef cmd_dump_header(fd):
306e19b3c4SKevin Wolf    h = QcowHeader(fd)
316e19b3c4SKevin Wolf    h.dump()
32eeafed5fSVladimir Sementsov-Ogievskiy    print()
336e19b3c4SKevin Wolf    h.dump_extensions()
346e19b3c4SKevin Wolf
3502756054SVladimir Sementsov-Ogievskiy
361aa6630eSMax Reitzdef cmd_dump_header_exts(fd):
371aa6630eSMax Reitz    h = QcowHeader(fd)
381aa6630eSMax Reitz    h.dump_extensions()
391aa6630eSMax Reitz
4002756054SVladimir Sementsov-Ogievskiy
41c93331c9SKevin Wolfdef cmd_set_header(fd, name, value):
42c93331c9SKevin Wolf    try:
43c93331c9SKevin Wolf        value = int(value, 0)
4402756054SVladimir Sementsov-Ogievskiy    except ValueError:
45f03868bdSEduardo Habkost        print("'%s' is not a valid number" % value)
46c93331c9SKevin Wolf        sys.exit(1)
47c93331c9SKevin Wolf
48c93331c9SKevin Wolf    fields = (field[2] for field in QcowHeader.fields)
4902756054SVladimir Sementsov-Ogievskiy    if name not in fields:
50f03868bdSEduardo Habkost        print("'%s' is not a known header field" % name)
51c93331c9SKevin Wolf        sys.exit(1)
52c93331c9SKevin Wolf
53c93331c9SKevin Wolf    h = QcowHeader(fd)
54c93331c9SKevin Wolf    h.__dict__[name] = value
55c93331c9SKevin Wolf    h.update(fd)
56c93331c9SKevin Wolf
5702756054SVladimir Sementsov-Ogievskiy
586e19b3c4SKevin Wolfdef cmd_add_header_ext(fd, magic, data):
596e19b3c4SKevin Wolf    try:
606e19b3c4SKevin Wolf        magic = int(magic, 0)
6102756054SVladimir Sementsov-Ogievskiy    except ValueError:
62f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
636e19b3c4SKevin Wolf        sys.exit(1)
646e19b3c4SKevin Wolf
656e19b3c4SKevin Wolf    h = QcowHeader(fd)
6602756054SVladimir Sementsov-Ogievskiy    h.extensions.append(QcowHeaderExtension.create(magic,
6702756054SVladimir Sementsov-Ogievskiy                                                   data.encode('ascii')))
686e19b3c4SKevin Wolf    h.update(fd)
696e19b3c4SKevin Wolf
7002756054SVladimir Sementsov-Ogievskiy
7112ac6d3dSKevin Wolfdef cmd_add_header_ext_stdio(fd, magic):
7212ac6d3dSKevin Wolf    data = sys.stdin.read()
7312ac6d3dSKevin Wolf    cmd_add_header_ext(fd, magic, data)
7412ac6d3dSKevin Wolf
7502756054SVladimir Sementsov-Ogievskiy
766e19b3c4SKevin Wolfdef cmd_del_header_ext(fd, magic):
776e19b3c4SKevin Wolf    try:
786e19b3c4SKevin Wolf        magic = int(magic, 0)
7902756054SVladimir Sementsov-Ogievskiy    except ValueError:
80f03868bdSEduardo Habkost        print("'%s' is not a valid magic number" % magic)
816e19b3c4SKevin Wolf        sys.exit(1)
826e19b3c4SKevin Wolf
836e19b3c4SKevin Wolf    h = QcowHeader(fd)
846e19b3c4SKevin Wolf    found = False
856e19b3c4SKevin Wolf
866e19b3c4SKevin Wolf    for ex in h.extensions:
876e19b3c4SKevin Wolf        if ex.magic == magic:
886e19b3c4SKevin Wolf            found = True
896e19b3c4SKevin Wolf            h.extensions.remove(ex)
906e19b3c4SKevin Wolf
916e19b3c4SKevin Wolf    if not found:
92f03868bdSEduardo Habkost        print("No such header extension")
936e19b3c4SKevin Wolf        return
946e19b3c4SKevin Wolf
956e19b3c4SKevin Wolf    h.update(fd)
966e19b3c4SKevin Wolf
9702756054SVladimir Sementsov-Ogievskiy
981b2eff62SStefan Hajnoczidef cmd_set_feature_bit(fd, group, bit):
991b2eff62SStefan Hajnoczi    try:
1001b2eff62SStefan Hajnoczi        bit = int(bit, 0)
1011b2eff62SStefan Hajnoczi        if bit < 0 or bit >= 64:
1021b2eff62SStefan Hajnoczi            raise ValueError
10302756054SVladimir Sementsov-Ogievskiy    except ValueError:
104f03868bdSEduardo Habkost        print("'%s' is not a valid bit number in range [0, 64)" % bit)
1051b2eff62SStefan Hajnoczi        sys.exit(1)
1061b2eff62SStefan Hajnoczi
1071b2eff62SStefan Hajnoczi    h = QcowHeader(fd)
1081b2eff62SStefan Hajnoczi    if group == 'incompatible':
1091b2eff62SStefan Hajnoczi        h.incompatible_features |= 1 << bit
1101b2eff62SStefan Hajnoczi    elif group == 'compatible':
1111b2eff62SStefan Hajnoczi        h.compatible_features |= 1 << bit
1121b2eff62SStefan Hajnoczi    elif group == 'autoclear':
1131b2eff62SStefan Hajnoczi        h.autoclear_features |= 1 << bit
1141b2eff62SStefan Hajnoczi    else:
11502756054SVladimir Sementsov-Ogievskiy        print("'%s' is not a valid group, try "
11602756054SVladimir Sementsov-Ogievskiy              "'incompatible', 'compatible', or 'autoclear'" % group)
1171b2eff62SStefan Hajnoczi        sys.exit(1)
1181b2eff62SStefan Hajnoczi
1191b2eff62SStefan Hajnoczi    h.update(fd)
1201b2eff62SStefan Hajnoczi
12102756054SVladimir Sementsov-Ogievskiy
1226e19b3c4SKevin Wolfcmds = [
12302756054SVladimir Sementsov-Ogievskiy    ['dump-header', cmd_dump_header, 0,
12402756054SVladimir Sementsov-Ogievskiy     'Dump image header and header extensions'],
12502756054SVladimir Sementsov-Ogievskiy    ['dump-header-exts', cmd_dump_header_exts, 0,
12602756054SVladimir Sementsov-Ogievskiy     'Dump image header extensions'],
127c93331c9SKevin Wolf    ['set-header', cmd_set_header, 2, 'Set a field in the header'],
1286e19b3c4SKevin Wolf    ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
12902756054SVladimir Sementsov-Ogievskiy    ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
13002756054SVladimir Sementsov-Ogievskiy     'Add a header extension, data from stdin'],
1316e19b3c4SKevin Wolf    ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
1321b2eff62SStefan Hajnoczi    ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
1336e19b3c4SKevin Wolf]
1346e19b3c4SKevin Wolf
13502756054SVladimir Sementsov-Ogievskiy
1366e19b3c4SKevin Wolfdef main(filename, cmd, args):
1376e19b3c4SKevin Wolf    fd = open(filename, "r+b")
1386e19b3c4SKevin Wolf    try:
1396e19b3c4SKevin Wolf        for name, handler, num_args, desc in cmds:
1406e19b3c4SKevin Wolf            if name != cmd:
1416e19b3c4SKevin Wolf                continue
1426e19b3c4SKevin Wolf            elif len(args) != num_args:
1436e19b3c4SKevin Wolf                usage()
1446e19b3c4SKevin Wolf                return
1456e19b3c4SKevin Wolf            else:
1466e19b3c4SKevin Wolf                handler(fd, *args)
1476e19b3c4SKevin Wolf                return
148f03868bdSEduardo Habkost        print("Unknown command '%s'" % cmd)
1496e19b3c4SKevin Wolf    finally:
1506e19b3c4SKevin Wolf        fd.close()
1516e19b3c4SKevin Wolf
15202756054SVladimir Sementsov-Ogievskiy
1536e19b3c4SKevin Wolfdef usage():
154f03868bdSEduardo Habkost    print("Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0])
155f03868bdSEduardo Habkost    print("")
156f03868bdSEduardo Habkost    print("Supported commands:")
1576e19b3c4SKevin Wolf    for name, handler, num_args, desc in cmds:
158f03868bdSEduardo Habkost        print("    %-20s - %s" % (name, desc))
1596e19b3c4SKevin Wolf
16002756054SVladimir Sementsov-Ogievskiy
161d2ef210cSKevin Wolfif __name__ == '__main__':
1626e19b3c4SKevin Wolf    if len(sys.argv) < 3:
1636e19b3c4SKevin Wolf        usage()
1646e19b3c4SKevin Wolf        sys.exit(1)
1656e19b3c4SKevin Wolf
1666e19b3c4SKevin Wolf    main(sys.argv[1], sys.argv[2], sys.argv[3:])
167