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

models.py (4442B)


      1"""
      2QMP Data Models
      3
      4This module provides simplistic data classes that represent the few
      5structures that the QMP spec mandates; they are used to verify incoming
      6data to make sure it conforms to spec.
      7"""
      8# pylint: disable=too-few-public-methods
      9
     10from collections import abc
     11import copy
     12from typing import (
     13    Any,
     14    Dict,
     15    Mapping,
     16    Optional,
     17    Sequence,
     18)
     19
     20
     21class Model:
     22    """
     23    Abstract data model, representing some QMP object of some kind.
     24
     25    :param raw: The raw object to be validated.
     26    :raise KeyError: If any required fields are absent.
     27    :raise TypeError: If any required fields have the wrong type.
     28    """
     29    def __init__(self, raw: Mapping[str, Any]):
     30        self._raw = raw
     31
     32    def _check_key(self, key: str) -> None:
     33        if key not in self._raw:
     34            raise KeyError(f"'{self._name}' object requires '{key}' member")
     35
     36    def _check_value(self, key: str, type_: type, typestr: str) -> None:
     37        assert key in self._raw
     38        if not isinstance(self._raw[key], type_):
     39            raise TypeError(
     40                f"'{self._name}' member '{key}' must be a {typestr}"
     41            )
     42
     43    def _check_member(self, key: str, type_: type, typestr: str) -> None:
     44        self._check_key(key)
     45        self._check_value(key, type_, typestr)
     46
     47    @property
     48    def _name(self) -> str:
     49        return type(self).__name__
     50
     51    def __repr__(self) -> str:
     52        return f"{self._name}({self._raw!r})"
     53
     54
     55class Greeting(Model):
     56    """
     57    Defined in qmp-spec.txt, section 2.2, "Server Greeting".
     58
     59    :param raw: The raw Greeting object.
     60    :raise KeyError: If any required fields are absent.
     61    :raise TypeError: If any required fields have the wrong type.
     62    """
     63    def __init__(self, raw: Mapping[str, Any]):
     64        super().__init__(raw)
     65        #: 'QMP' member
     66        self.QMP: QMPGreeting  # pylint: disable=invalid-name
     67
     68        self._check_member('QMP', abc.Mapping, "JSON object")
     69        self.QMP = QMPGreeting(self._raw['QMP'])
     70
     71    def _asdict(self) -> Dict[str, object]:
     72        """
     73        For compatibility with the iotests sync QMP wrapper.
     74
     75        The legacy QMP interface needs Greetings as a garden-variety Dict.
     76
     77        This interface is private in the hopes that it will be able to
     78        be dropped again in the near-future. Caller beware!
     79        """
     80        return dict(copy.deepcopy(self._raw))
     81
     82
     83class QMPGreeting(Model):
     84    """
     85    Defined in qmp-spec.txt, section 2.2, "Server Greeting".
     86
     87    :param raw: The raw QMPGreeting object.
     88    :raise KeyError: If any required fields are absent.
     89    :raise TypeError: If any required fields have the wrong type.
     90    """
     91    def __init__(self, raw: Mapping[str, Any]):
     92        super().__init__(raw)
     93        #: 'version' member
     94        self.version: Mapping[str, object]
     95        #: 'capabilities' member
     96        self.capabilities: Sequence[object]
     97
     98        self._check_member('version', abc.Mapping, "JSON object")
     99        self.version = self._raw['version']
    100
    101        self._check_member('capabilities', abc.Sequence, "JSON array")
    102        self.capabilities = self._raw['capabilities']
    103
    104
    105class ErrorResponse(Model):
    106    """
    107    Defined in qmp-spec.txt, section 2.4.2, "error".
    108
    109    :param raw: The raw ErrorResponse object.
    110    :raise KeyError: If any required fields are absent.
    111    :raise TypeError: If any required fields have the wrong type.
    112    """
    113    def __init__(self, raw: Mapping[str, Any]):
    114        super().__init__(raw)
    115        #: 'error' member
    116        self.error: ErrorInfo
    117        #: 'id' member
    118        self.id: Optional[object] = None  # pylint: disable=invalid-name
    119
    120        self._check_member('error', abc.Mapping, "JSON object")
    121        self.error = ErrorInfo(self._raw['error'])
    122
    123        if 'id' in raw:
    124            self.id = raw['id']
    125
    126
    127class ErrorInfo(Model):
    128    """
    129    Defined in qmp-spec.txt, section 2.4.2, "error".
    130
    131    :param raw: The raw ErrorInfo object.
    132    :raise KeyError: If any required fields are absent.
    133    :raise TypeError: If any required fields have the wrong type.
    134    """
    135    def __init__(self, raw: Mapping[str, Any]):
    136        super().__init__(raw)
    137        #: 'class' member, with an underscore to avoid conflicts in Python.
    138        self.class_: str
    139        #: 'desc' member
    140        self.desc: str
    141
    142        self._check_member('class', str, "string")
    143        self.class_ = self._raw['class']
    144
    145        self._check_member('desc', str, "string")
    146        self.desc = self._raw['desc']