maqet 0.0.1.4__py3-none-any.whl → 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- maqet/__init__.py +50 -6
- maqet/__main__.py +96 -0
- maqet/__version__.py +3 -0
- maqet/api/__init__.py +35 -0
- maqet/api/decorators.py +184 -0
- maqet/api/metadata.py +147 -0
- maqet/api/registry.py +182 -0
- maqet/cli.py +71 -0
- maqet/config/__init__.py +26 -0
- maqet/config/merger.py +237 -0
- maqet/config/parser.py +198 -0
- maqet/config/validators.py +519 -0
- maqet/config_handlers.py +684 -0
- maqet/constants.py +200 -0
- maqet/exceptions.py +226 -0
- maqet/formatters.py +294 -0
- maqet/generators/__init__.py +12 -0
- maqet/generators/base_generator.py +101 -0
- maqet/generators/cli_generator.py +635 -0
- maqet/generators/python_generator.py +247 -0
- maqet/generators/rest_generator.py +58 -0
- maqet/handlers/__init__.py +12 -0
- maqet/handlers/base.py +108 -0
- maqet/handlers/init.py +147 -0
- maqet/handlers/stage.py +196 -0
- maqet/ipc/__init__.py +29 -0
- maqet/ipc/retry.py +265 -0
- maqet/ipc/runner_client.py +285 -0
- maqet/ipc/unix_socket_server.py +239 -0
- maqet/logger.py +160 -55
- maqet/machine.py +884 -0
- maqet/managers/__init__.py +7 -0
- maqet/managers/qmp_manager.py +333 -0
- maqet/managers/snapshot_coordinator.py +327 -0
- maqet/managers/vm_manager.py +683 -0
- maqet/maqet.py +1120 -0
- maqet/os_interactions.py +46 -0
- maqet/process_spawner.py +395 -0
- maqet/qemu_args.py +76 -0
- maqet/qmp/__init__.py +10 -0
- maqet/qmp/commands.py +92 -0
- maqet/qmp/keyboard.py +311 -0
- maqet/qmp/qmp.py +17 -0
- maqet/snapshot.py +473 -0
- maqet/state.py +958 -0
- maqet/storage.py +702 -162
- maqet/validation/__init__.py +9 -0
- maqet/validation/config_validator.py +170 -0
- maqet/vm_runner.py +523 -0
- maqet-0.0.5.dist-info/METADATA +237 -0
- maqet-0.0.5.dist-info/RECORD +55 -0
- {maqet-0.0.1.4.dist-info → maqet-0.0.5.dist-info}/WHEEL +1 -1
- maqet-0.0.5.dist-info/entry_points.txt +2 -0
- maqet-0.0.5.dist-info/licenses/LICENSE +21 -0
- {maqet-0.0.1.4.dist-info → maqet-0.0.5.dist-info}/top_level.txt +0 -1
- maqet/core.py +0 -411
- maqet/functions.py +0 -104
- maqet-0.0.1.4.dist-info/METADATA +0 -6
- maqet-0.0.1.4.dist-info/RECORD +0 -33
- qemu/machine/__init__.py +0 -36
- qemu/machine/console_socket.py +0 -142
- qemu/machine/machine.py +0 -954
- qemu/machine/py.typed +0 -0
- qemu/machine/qtest.py +0 -191
- qemu/qmp/__init__.py +0 -59
- qemu/qmp/error.py +0 -50
- qemu/qmp/events.py +0 -717
- qemu/qmp/legacy.py +0 -319
- qemu/qmp/message.py +0 -209
- qemu/qmp/models.py +0 -146
- qemu/qmp/protocol.py +0 -1057
- qemu/qmp/py.typed +0 -0
- qemu/qmp/qmp_client.py +0 -655
- qemu/qmp/qmp_shell.py +0 -618
- qemu/qmp/qmp_tui.py +0 -655
- qemu/qmp/util.py +0 -219
- qemu/utils/__init__.py +0 -162
- qemu/utils/accel.py +0 -84
- qemu/utils/py.typed +0 -0
- qemu/utils/qemu_ga_client.py +0 -323
- qemu/utils/qom.py +0 -273
- qemu/utils/qom_common.py +0 -175
- qemu/utils/qom_fuse.py +0 -207
qemu/utils/qom_common.py
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
QOM Command abstractions.
|
3
|
-
"""
|
4
|
-
##
|
5
|
-
# Copyright John Snow 2020, for Red Hat, Inc.
|
6
|
-
# Copyright IBM, Corp. 2011
|
7
|
-
#
|
8
|
-
# Authors:
|
9
|
-
# John Snow <jsnow@redhat.com>
|
10
|
-
# Anthony Liguori <aliguori@amazon.com>
|
11
|
-
#
|
12
|
-
# This work is licensed under the terms of the GNU GPL, version 2 or later.
|
13
|
-
# See the COPYING file in the top-level directory.
|
14
|
-
#
|
15
|
-
# Based on ./scripts/qmp/qom-[set|get|tree|list]
|
16
|
-
##
|
17
|
-
|
18
|
-
import argparse
|
19
|
-
import os
|
20
|
-
import sys
|
21
|
-
from typing import (
|
22
|
-
Any,
|
23
|
-
Dict,
|
24
|
-
List,
|
25
|
-
Optional,
|
26
|
-
Type,
|
27
|
-
TypeVar,
|
28
|
-
)
|
29
|
-
|
30
|
-
from qemu.qmp import QMPError
|
31
|
-
from qemu.qmp.legacy import QEMUMonitorProtocol
|
32
|
-
|
33
|
-
|
34
|
-
class ObjectPropertyInfo:
|
35
|
-
"""
|
36
|
-
Represents the return type from e.g. qom-list.
|
37
|
-
"""
|
38
|
-
def __init__(self, name: str, type_: str,
|
39
|
-
description: Optional[str] = None,
|
40
|
-
default_value: Optional[object] = None):
|
41
|
-
self.name = name
|
42
|
-
self.type = type_
|
43
|
-
self.description = description
|
44
|
-
self.default_value = default_value
|
45
|
-
|
46
|
-
@classmethod
|
47
|
-
def make(cls, value: Dict[str, Any]) -> 'ObjectPropertyInfo':
|
48
|
-
"""
|
49
|
-
Build an ObjectPropertyInfo from a Dict with an unknown shape.
|
50
|
-
"""
|
51
|
-
assert value.keys() >= {'name', 'type'}
|
52
|
-
assert value.keys() <= {'name', 'type', 'description', 'default-value'}
|
53
|
-
return cls(value['name'], value['type'],
|
54
|
-
value.get('description'),
|
55
|
-
value.get('default-value'))
|
56
|
-
|
57
|
-
@property
|
58
|
-
def child(self) -> bool:
|
59
|
-
"""Is this property a child property?"""
|
60
|
-
return self.type.startswith('child<')
|
61
|
-
|
62
|
-
@property
|
63
|
-
def link(self) -> bool:
|
64
|
-
"""Is this property a link property?"""
|
65
|
-
return self.type.startswith('link<')
|
66
|
-
|
67
|
-
|
68
|
-
CommandT = TypeVar('CommandT', bound='QOMCommand')
|
69
|
-
|
70
|
-
|
71
|
-
class QOMCommand:
|
72
|
-
"""
|
73
|
-
Represents a QOM sub-command.
|
74
|
-
|
75
|
-
:param args: Parsed arguments, as returned from parser.parse_args.
|
76
|
-
"""
|
77
|
-
name: str
|
78
|
-
help: str
|
79
|
-
|
80
|
-
def __init__(self, args: argparse.Namespace):
|
81
|
-
if args.socket is None:
|
82
|
-
raise QMPError("No QMP socket path or address given")
|
83
|
-
self.qmp = QEMUMonitorProtocol(
|
84
|
-
QEMUMonitorProtocol.parse_address(args.socket)
|
85
|
-
)
|
86
|
-
self.qmp.connect()
|
87
|
-
|
88
|
-
@classmethod
|
89
|
-
def register(cls, subparsers: Any) -> None:
|
90
|
-
"""
|
91
|
-
Register this command with the argument parser.
|
92
|
-
|
93
|
-
:param subparsers: argparse subparsers object, from "add_subparsers".
|
94
|
-
"""
|
95
|
-
subparser = subparsers.add_parser(cls.name, help=cls.help,
|
96
|
-
description=cls.help)
|
97
|
-
cls.configure_parser(subparser)
|
98
|
-
|
99
|
-
@classmethod
|
100
|
-
def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
|
101
|
-
"""
|
102
|
-
Configure a parser with this command's arguments.
|
103
|
-
|
104
|
-
:param parser: argparse parser or subparser object.
|
105
|
-
"""
|
106
|
-
default_path = os.environ.get('QMP_SOCKET')
|
107
|
-
parser.add_argument(
|
108
|
-
'--socket', '-s',
|
109
|
-
dest='socket',
|
110
|
-
action='store',
|
111
|
-
help='QMP socket path or address (addr:port).'
|
112
|
-
' May also be set via QMP_SOCKET environment variable.',
|
113
|
-
default=default_path
|
114
|
-
)
|
115
|
-
parser.set_defaults(cmd_class=cls)
|
116
|
-
|
117
|
-
@classmethod
|
118
|
-
def add_path_prop_arg(cls, parser: argparse.ArgumentParser) -> None:
|
119
|
-
"""
|
120
|
-
Add the <path>.<proptery> positional argument to this command.
|
121
|
-
|
122
|
-
:param parser: The parser to add the argument to.
|
123
|
-
"""
|
124
|
-
parser.add_argument(
|
125
|
-
'path_prop',
|
126
|
-
metavar='<path>.<property>',
|
127
|
-
action='store',
|
128
|
-
help="QOM path and property, separated by a period '.'"
|
129
|
-
)
|
130
|
-
|
131
|
-
def run(self) -> int:
|
132
|
-
"""
|
133
|
-
Run this command.
|
134
|
-
|
135
|
-
:return: 0 on success, 1 otherwise.
|
136
|
-
"""
|
137
|
-
raise NotImplementedError
|
138
|
-
|
139
|
-
def qom_list(self, path: str) -> List[ObjectPropertyInfo]:
|
140
|
-
"""
|
141
|
-
:return: a strongly typed list from the 'qom-list' command.
|
142
|
-
"""
|
143
|
-
rsp = self.qmp.cmd('qom-list', path=path)
|
144
|
-
# qom-list returns List[ObjectPropertyInfo]
|
145
|
-
assert isinstance(rsp, list)
|
146
|
-
return [ObjectPropertyInfo.make(x) for x in rsp]
|
147
|
-
|
148
|
-
@classmethod
|
149
|
-
def command_runner(
|
150
|
-
cls: Type[CommandT],
|
151
|
-
args: argparse.Namespace
|
152
|
-
) -> int:
|
153
|
-
"""
|
154
|
-
Run a fully-parsed subcommand, with error-handling for the CLI.
|
155
|
-
|
156
|
-
:return: The return code from `run()`.
|
157
|
-
"""
|
158
|
-
try:
|
159
|
-
cmd = cls(args)
|
160
|
-
return cmd.run()
|
161
|
-
except QMPError as err:
|
162
|
-
print(f"{type(err).__name__}: {err!s}", file=sys.stderr)
|
163
|
-
return -1
|
164
|
-
|
165
|
-
@classmethod
|
166
|
-
def entry_point(cls) -> int:
|
167
|
-
"""
|
168
|
-
Build this command's parser, parse arguments, and run the command.
|
169
|
-
|
170
|
-
:return: `run`'s return code.
|
171
|
-
"""
|
172
|
-
parser = argparse.ArgumentParser(description=cls.help)
|
173
|
-
cls.configure_parser(parser)
|
174
|
-
args = parser.parse_args()
|
175
|
-
return cls.command_runner(args)
|
qemu/utils/qom_fuse.py
DELETED
@@ -1,207 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
QEMU Object Model FUSE filesystem tool
|
3
|
-
|
4
|
-
This script offers a simple FUSE filesystem within which the QOM tree
|
5
|
-
may be browsed, queried and edited using traditional shell tooling.
|
6
|
-
|
7
|
-
This script requires the 'fusepy' python package.
|
8
|
-
|
9
|
-
|
10
|
-
usage: qom-fuse [-h] [--socket SOCKET] <mount>
|
11
|
-
|
12
|
-
Mount a QOM tree as a FUSE filesystem
|
13
|
-
|
14
|
-
positional arguments:
|
15
|
-
<mount> Mount point
|
16
|
-
|
17
|
-
optional arguments:
|
18
|
-
-h, --help show this help message and exit
|
19
|
-
--socket SOCKET, -s SOCKET
|
20
|
-
QMP socket path or address (addr:port). May also be
|
21
|
-
set via QMP_SOCKET environment variable.
|
22
|
-
"""
|
23
|
-
##
|
24
|
-
# Copyright IBM, Corp. 2012
|
25
|
-
# Copyright (C) 2020 Red Hat, Inc.
|
26
|
-
#
|
27
|
-
# Authors:
|
28
|
-
# Anthony Liguori <aliguori@us.ibm.com>
|
29
|
-
# Markus Armbruster <armbru@redhat.com>
|
30
|
-
#
|
31
|
-
# This work is licensed under the terms of the GNU GPL, version 2 or later.
|
32
|
-
# See the COPYING file in the top-level directory.
|
33
|
-
##
|
34
|
-
|
35
|
-
import argparse
|
36
|
-
from errno import ENOENT, EPERM
|
37
|
-
import stat
|
38
|
-
import sys
|
39
|
-
from typing import (
|
40
|
-
IO,
|
41
|
-
Dict,
|
42
|
-
Iterator,
|
43
|
-
Mapping,
|
44
|
-
Optional,
|
45
|
-
Union,
|
46
|
-
)
|
47
|
-
|
48
|
-
import fuse
|
49
|
-
from fuse import FUSE, FuseOSError, Operations
|
50
|
-
|
51
|
-
from qemu.qmp import ExecuteError
|
52
|
-
|
53
|
-
from .qom_common import QOMCommand
|
54
|
-
|
55
|
-
|
56
|
-
fuse.fuse_python_api = (0, 2)
|
57
|
-
|
58
|
-
|
59
|
-
class QOMFuse(QOMCommand, Operations):
|
60
|
-
"""
|
61
|
-
QOMFuse implements both fuse.Operations and QOMCommand.
|
62
|
-
|
63
|
-
Operations implements the FS, and QOMCommand implements the CLI command.
|
64
|
-
"""
|
65
|
-
name = 'fuse'
|
66
|
-
help = 'Mount a QOM tree as a FUSE filesystem'
|
67
|
-
fuse: FUSE
|
68
|
-
|
69
|
-
@classmethod
|
70
|
-
def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
|
71
|
-
super().configure_parser(parser)
|
72
|
-
parser.add_argument(
|
73
|
-
'mount',
|
74
|
-
metavar='<mount>',
|
75
|
-
action='store',
|
76
|
-
help="Mount point",
|
77
|
-
)
|
78
|
-
|
79
|
-
def __init__(self, args: argparse.Namespace):
|
80
|
-
super().__init__(args)
|
81
|
-
self.mount = args.mount
|
82
|
-
self.ino_map: Dict[str, int] = {}
|
83
|
-
self.ino_count = 1
|
84
|
-
|
85
|
-
def run(self) -> int:
|
86
|
-
print(f"Mounting QOMFS to '{self.mount}'", file=sys.stderr)
|
87
|
-
self.fuse = FUSE(self, self.mount, foreground=True)
|
88
|
-
return 0
|
89
|
-
|
90
|
-
def get_ino(self, path: str) -> int:
|
91
|
-
"""Get an inode number for a given QOM path."""
|
92
|
-
if path in self.ino_map:
|
93
|
-
return self.ino_map[path]
|
94
|
-
self.ino_map[path] = self.ino_count
|
95
|
-
self.ino_count += 1
|
96
|
-
return self.ino_map[path]
|
97
|
-
|
98
|
-
def is_object(self, path: str) -> bool:
|
99
|
-
"""Is the given QOM path an object?"""
|
100
|
-
try:
|
101
|
-
self.qom_list(path)
|
102
|
-
return True
|
103
|
-
except ExecuteError:
|
104
|
-
return False
|
105
|
-
|
106
|
-
def is_property(self, path: str) -> bool:
|
107
|
-
"""Is the given QOM path a property?"""
|
108
|
-
path, prop = path.rsplit('/', 1)
|
109
|
-
if path == '':
|
110
|
-
path = '/'
|
111
|
-
try:
|
112
|
-
for item in self.qom_list(path):
|
113
|
-
if item.name == prop:
|
114
|
-
return True
|
115
|
-
return False
|
116
|
-
except ExecuteError:
|
117
|
-
return False
|
118
|
-
|
119
|
-
def is_link(self, path: str) -> bool:
|
120
|
-
"""Is the given QOM path a link?"""
|
121
|
-
path, prop = path.rsplit('/', 1)
|
122
|
-
if path == '':
|
123
|
-
path = '/'
|
124
|
-
try:
|
125
|
-
for item in self.qom_list(path):
|
126
|
-
if item.name == prop and item.link:
|
127
|
-
return True
|
128
|
-
return False
|
129
|
-
except ExecuteError:
|
130
|
-
return False
|
131
|
-
|
132
|
-
def read(self, path: str, size: int, offset: int, fh: IO[bytes]) -> bytes:
|
133
|
-
if not self.is_property(path):
|
134
|
-
raise FuseOSError(ENOENT)
|
135
|
-
|
136
|
-
path, prop = path.rsplit('/', 1)
|
137
|
-
if path == '':
|
138
|
-
path = '/'
|
139
|
-
try:
|
140
|
-
data = str(self.qmp.cmd('qom-get', path=path, property=prop))
|
141
|
-
data += '\n' # make values shell friendly
|
142
|
-
except ExecuteError as err:
|
143
|
-
raise FuseOSError(EPERM) from err
|
144
|
-
|
145
|
-
if offset > len(data):
|
146
|
-
return b''
|
147
|
-
|
148
|
-
return bytes(data[offset:][:size], encoding='utf-8')
|
149
|
-
|
150
|
-
def readlink(self, path: str) -> Union[bool, str]:
|
151
|
-
if not self.is_link(path):
|
152
|
-
return False
|
153
|
-
path, prop = path.rsplit('/', 1)
|
154
|
-
prefix = '/'.join(['..'] * (len(path.split('/')) - 1))
|
155
|
-
return prefix + str(self.qmp.cmd('qom-get', path=path,
|
156
|
-
property=prop))
|
157
|
-
|
158
|
-
def getattr(self, path: str,
|
159
|
-
fh: Optional[IO[bytes]] = None) -> Mapping[str, object]:
|
160
|
-
if self.is_link(path):
|
161
|
-
value = {
|
162
|
-
'st_mode': 0o755 | stat.S_IFLNK,
|
163
|
-
'st_ino': self.get_ino(path),
|
164
|
-
'st_dev': 0,
|
165
|
-
'st_nlink': 2,
|
166
|
-
'st_uid': 1000,
|
167
|
-
'st_gid': 1000,
|
168
|
-
'st_size': 4096,
|
169
|
-
'st_atime': 0,
|
170
|
-
'st_mtime': 0,
|
171
|
-
'st_ctime': 0
|
172
|
-
}
|
173
|
-
elif self.is_object(path):
|
174
|
-
value = {
|
175
|
-
'st_mode': 0o755 | stat.S_IFDIR,
|
176
|
-
'st_ino': self.get_ino(path),
|
177
|
-
'st_dev': 0,
|
178
|
-
'st_nlink': 2,
|
179
|
-
'st_uid': 1000,
|
180
|
-
'st_gid': 1000,
|
181
|
-
'st_size': 4096,
|
182
|
-
'st_atime': 0,
|
183
|
-
'st_mtime': 0,
|
184
|
-
'st_ctime': 0
|
185
|
-
}
|
186
|
-
elif self.is_property(path):
|
187
|
-
value = {
|
188
|
-
'st_mode': 0o644 | stat.S_IFREG,
|
189
|
-
'st_ino': self.get_ino(path),
|
190
|
-
'st_dev': 0,
|
191
|
-
'st_nlink': 1,
|
192
|
-
'st_uid': 1000,
|
193
|
-
'st_gid': 1000,
|
194
|
-
'st_size': 4096,
|
195
|
-
'st_atime': 0,
|
196
|
-
'st_mtime': 0,
|
197
|
-
'st_ctime': 0
|
198
|
-
}
|
199
|
-
else:
|
200
|
-
raise FuseOSError(ENOENT)
|
201
|
-
return value
|
202
|
-
|
203
|
-
def readdir(self, path: str, fh: IO[bytes]) -> Iterator[str]:
|
204
|
-
yield '.'
|
205
|
-
yield '..'
|
206
|
-
for item in self.qom_list(path):
|
207
|
-
yield item.name
|