cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qom.py (7580B)


      1"""
      2QEMU Object Model testing tools.
      3
      4usage: qom [-h] {set,get,list,tree,fuse} ...
      5
      6Query and manipulate QOM data
      7
      8optional arguments:
      9  -h, --help           show this help message and exit
     10
     11QOM commands:
     12  {set,get,list,tree,fuse}
     13    set                Set a QOM property value
     14    get                Get a QOM property value
     15    list               List QOM properties at a given path
     16    tree               Show QOM tree from a given path
     17    fuse               Mount a QOM tree as a FUSE filesystem
     18"""
     19##
     20# Copyright John Snow 2020, for Red Hat, Inc.
     21# Copyright IBM, Corp. 2011
     22#
     23# Authors:
     24#  John Snow <jsnow@redhat.com>
     25#  Anthony Liguori <aliguori@amazon.com>
     26#
     27# This work is licensed under the terms of the GNU GPL, version 2 or later.
     28# See the COPYING file in the top-level directory.
     29#
     30# Based on ./scripts/qmp/qom-[set|get|tree|list]
     31##
     32
     33import argparse
     34
     35from . import QMPResponseError
     36from .qom_common import QOMCommand
     37
     38
     39try:
     40    from .qom_fuse import QOMFuse
     41except ModuleNotFoundError as _err:
     42    if _err.name != 'fuse':
     43        raise
     44else:
     45    assert issubclass(QOMFuse, QOMCommand)
     46
     47
     48class QOMSet(QOMCommand):
     49    """
     50    QOM Command - Set a property to a given value.
     51
     52    usage: qom-set [-h] [--socket SOCKET] <path>.<property> <value>
     53
     54    Set a QOM property value
     55
     56    positional arguments:
     57      <path>.<property>     QOM path and property, separated by a period '.'
     58      <value>               new QOM property value
     59
     60    optional arguments:
     61      -h, --help            show this help message and exit
     62      --socket SOCKET, -s SOCKET
     63                            QMP socket path or address (addr:port). May also be
     64                            set via QMP_SOCKET environment variable.
     65    """
     66    name = 'set'
     67    help = 'Set a QOM property value'
     68
     69    @classmethod
     70    def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
     71        super().configure_parser(parser)
     72        cls.add_path_prop_arg(parser)
     73        parser.add_argument(
     74            'value',
     75            metavar='<value>',
     76            action='store',
     77            help='new QOM property value'
     78        )
     79
     80    def __init__(self, args: argparse.Namespace):
     81        super().__init__(args)
     82        self.path, self.prop = args.path_prop.rsplit('.', 1)
     83        self.value = args.value
     84
     85    def run(self) -> int:
     86        rsp = self.qmp.command(
     87            'qom-set',
     88            path=self.path,
     89            property=self.prop,
     90            value=self.value
     91        )
     92        print(rsp)
     93        return 0
     94
     95
     96class QOMGet(QOMCommand):
     97    """
     98    QOM Command - Get a property's current value.
     99
    100    usage: qom-get [-h] [--socket SOCKET] <path>.<property>
    101
    102    Get a QOM property value
    103
    104    positional arguments:
    105      <path>.<property>     QOM path and property, separated by a period '.'
    106
    107    optional arguments:
    108      -h, --help            show this help message and exit
    109      --socket SOCKET, -s SOCKET
    110                            QMP socket path or address (addr:port). May also be
    111                            set via QMP_SOCKET environment variable.
    112    """
    113    name = 'get'
    114    help = 'Get a QOM property value'
    115
    116    @classmethod
    117    def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
    118        super().configure_parser(parser)
    119        cls.add_path_prop_arg(parser)
    120
    121    def __init__(self, args: argparse.Namespace):
    122        super().__init__(args)
    123        try:
    124            tmp = args.path_prop.rsplit('.', 1)
    125        except ValueError as err:
    126            raise ValueError('Invalid format for <path>.<property>') from err
    127        self.path = tmp[0]
    128        self.prop = tmp[1]
    129
    130    def run(self) -> int:
    131        rsp = self.qmp.command(
    132            'qom-get',
    133            path=self.path,
    134            property=self.prop
    135        )
    136        if isinstance(rsp, dict):
    137            for key, value in rsp.items():
    138                print(f"{key}: {value}")
    139        else:
    140            print(rsp)
    141        return 0
    142
    143
    144class QOMList(QOMCommand):
    145    """
    146    QOM Command - List the properties at a given path.
    147
    148    usage: qom-list [-h] [--socket SOCKET] <path>
    149
    150    List QOM properties at a given path
    151
    152    positional arguments:
    153      <path>                QOM path
    154
    155    optional arguments:
    156      -h, --help            show this help message and exit
    157      --socket SOCKET, -s SOCKET
    158                            QMP socket path or address (addr:port). May also be
    159                            set via QMP_SOCKET environment variable.
    160    """
    161    name = 'list'
    162    help = 'List QOM properties at a given path'
    163
    164    @classmethod
    165    def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
    166        super().configure_parser(parser)
    167        parser.add_argument(
    168            'path',
    169            metavar='<path>',
    170            action='store',
    171            help='QOM path',
    172        )
    173
    174    def __init__(self, args: argparse.Namespace):
    175        super().__init__(args)
    176        self.path = args.path
    177
    178    def run(self) -> int:
    179        rsp = self.qom_list(self.path)
    180        for item in rsp:
    181            if item.child:
    182                print(f"{item.name}/")
    183            elif item.link:
    184                print(f"@{item.name}/")
    185            else:
    186                print(item.name)
    187        return 0
    188
    189
    190class QOMTree(QOMCommand):
    191    """
    192    QOM Command - Show the full tree below a given path.
    193
    194    usage: qom-tree [-h] [--socket SOCKET] [<path>]
    195
    196    Show QOM tree from a given path
    197
    198    positional arguments:
    199      <path>                QOM path
    200
    201    optional arguments:
    202      -h, --help            show this help message and exit
    203      --socket SOCKET, -s SOCKET
    204                            QMP socket path or address (addr:port). May also be
    205                            set via QMP_SOCKET environment variable.
    206    """
    207    name = 'tree'
    208    help = 'Show QOM tree from a given path'
    209
    210    @classmethod
    211    def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
    212        super().configure_parser(parser)
    213        parser.add_argument(
    214            'path',
    215            metavar='<path>',
    216            action='store',
    217            help='QOM path',
    218            nargs='?',
    219            default='/'
    220        )
    221
    222    def __init__(self, args: argparse.Namespace):
    223        super().__init__(args)
    224        self.path = args.path
    225
    226    def _list_node(self, path: str) -> None:
    227        print(path)
    228        items = self.qom_list(path)
    229        for item in items:
    230            if item.child:
    231                continue
    232            try:
    233                rsp = self.qmp.command('qom-get', path=path,
    234                                       property=item.name)
    235                print(f"  {item.name}: {rsp} ({item.type})")
    236            except QMPResponseError as err:
    237                print(f"  {item.name}: <EXCEPTION: {err!s}> ({item.type})")
    238        print('')
    239        for item in items:
    240            if not item.child:
    241                continue
    242            if path == '/':
    243                path = ''
    244            self._list_node(f"{path}/{item.name}")
    245
    246    def run(self) -> int:
    247        self._list_node(self.path)
    248        return 0
    249
    250
    251def main() -> int:
    252    """QOM script main entry point."""
    253    parser = argparse.ArgumentParser(
    254        description='Query and manipulate QOM data'
    255    )
    256    subparsers = parser.add_subparsers(
    257        title='QOM commands',
    258        dest='command'
    259    )
    260
    261    for command in QOMCommand.__subclasses__():
    262        command.register(subparsers)
    263
    264    args = parser.parse_args()
    265
    266    if args.command is None:
    267        parser.error('Command not specified.')
    268        return 1
    269
    270    cmd_class = args.cmd_class
    271    assert isinstance(cmd_class, type(QOMCommand))
    272    return cmd_class.command_runner(args)