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
maqet/core.py
DELETED
@@ -1,411 +0,0 @@
|
|
1
|
-
import argparse
|
2
|
-
import time
|
3
|
-
from functools import wraps
|
4
|
-
from pathlib import Path
|
5
|
-
from typing import Callable, List
|
6
|
-
|
7
|
-
from benedict import benedict
|
8
|
-
|
9
|
-
from qemu.machine import QEMUMachine
|
10
|
-
|
11
|
-
from .functions import parse_args, split_args
|
12
|
-
from .logger import LOG
|
13
|
-
from .storage import DRIVE_TYPES, Drive
|
14
|
-
|
15
|
-
# To be moved into input.py
|
16
|
-
SPEC_CHAR_KEYS = {
|
17
|
-
"\r": ["ret"],
|
18
|
-
"\n": ["ret"],
|
19
|
-
" ": ["spc"],
|
20
|
-
"=": ["equal"],
|
21
|
-
"+": ["shift", "equal"],
|
22
|
-
"-": ["minus"],
|
23
|
-
"_": ["shift", "minus"],
|
24
|
-
";": ["semicolon"],
|
25
|
-
":": ["shift", "semicolon"],
|
26
|
-
"&": ["shift", "7"],
|
27
|
-
"/": ["slash"],
|
28
|
-
".": ["dot"],
|
29
|
-
">": ["shift", "dot"],
|
30
|
-
"<": ["shift", "comma"],
|
31
|
-
"#": ["shift", "3"],
|
32
|
-
}
|
33
|
-
|
34
|
-
|
35
|
-
class MaqetError(Exception):
|
36
|
-
"""
|
37
|
-
General exception
|
38
|
-
"""
|
39
|
-
|
40
|
-
|
41
|
-
class MachineError(Exception):
|
42
|
-
"""
|
43
|
-
Machine generic error
|
44
|
-
"""
|
45
|
-
|
46
|
-
|
47
|
-
class Machine(QEMUMachine):
|
48
|
-
def __init__(self, *args, **kwargs):
|
49
|
-
"""
|
50
|
-
TODO: make docstring
|
51
|
-
|
52
|
-
Machine objects should be created with **kwargs
|
53
|
-
"""
|
54
|
-
self._config = benedict(kwargs)
|
55
|
-
if 'storage_path' in self._config:
|
56
|
-
self._config.storage_path = Path(self._config.storage_path)
|
57
|
-
if 'binary' not in self._config:
|
58
|
-
raise MachineError("Binary not stated in config")
|
59
|
-
|
60
|
-
self._config.typing_delay = kwargs.get('typing_delay', 0.1)
|
61
|
-
|
62
|
-
binary = self._config['binary']
|
63
|
-
|
64
|
-
qemumachine_args = dict()
|
65
|
-
for key in ['args', 'wrapper', 'name', 'base_temp_dir',
|
66
|
-
'monitor_address', 'drain_console', 'console_log',
|
67
|
-
'log_dir', 'qmp_timer']:
|
68
|
-
if key in self._config:
|
69
|
-
qemumachine_args[key] = self._config[key]
|
70
|
-
|
71
|
-
super().__init__(binary=binary, **qemumachine_args)
|
72
|
-
|
73
|
-
self.storage = dict()
|
74
|
-
if 'storage' in self._config:
|
75
|
-
for name, drive in self._config.storage.items():
|
76
|
-
self.add_drive(name=name, **drive)
|
77
|
-
|
78
|
-
def launch(self):
|
79
|
-
LOG.info(f'VM launch with command: {self.command}')
|
80
|
-
super().launch()
|
81
|
-
|
82
|
-
def add_drive(self, name, **kwargs) -> None:
|
83
|
-
if 'path' not in kwargs:
|
84
|
-
if 'storage_path' in self._config:
|
85
|
-
# Adding default storage path from config
|
86
|
-
kwargs['path'] = self._config.storage_path / name
|
87
|
-
else:
|
88
|
-
raise MachineError(
|
89
|
-
'Cannot add drive: stated neither path nor storage_path')
|
90
|
-
self.storage[name] = Drive(**kwargs)
|
91
|
-
|
92
|
-
# def add_argument(self, argument: str) -> None:
|
93
|
-
# """
|
94
|
-
# Add user argument to VM config
|
95
|
-
# """
|
96
|
-
# self._config['user_arguments'].append(argument)
|
97
|
-
|
98
|
-
def add_args(self, *args: str) -> None:
|
99
|
-
"""
|
100
|
-
Adds to the list of extra arguments to be given to the QEMU binary
|
101
|
-
"""
|
102
|
-
super().add_args(*split_args(args))
|
103
|
-
|
104
|
-
@property
|
105
|
-
def command(self) -> str:
|
106
|
-
"""
|
107
|
-
get full command string that will be executed at start
|
108
|
-
"""
|
109
|
-
return self._binary + ' ' + ' '.join(self._base_args)
|
110
|
-
|
111
|
-
@property
|
112
|
-
def _const_args(self) -> List[str]:
|
113
|
-
if 'arguments' not in self._config:
|
114
|
-
return []
|
115
|
-
return parse_args(self._config.arguments)
|
116
|
-
|
117
|
-
@property
|
118
|
-
def _var_args(self) -> List[str]:
|
119
|
-
# TODO:more reliable method. Maybe add-fd?
|
120
|
-
|
121
|
-
args = []
|
122
|
-
for id, drive in self.storage.items():
|
123
|
-
args += drive()
|
124
|
-
|
125
|
-
return [
|
126
|
-
a_splitted
|
127
|
-
for a in args
|
128
|
-
for a_splitted in a.split()
|
129
|
-
]
|
130
|
-
|
131
|
-
@property
|
132
|
-
def user_args(self):
|
133
|
-
return [
|
134
|
-
a_splitted
|
135
|
-
for a in self._config.user_arguments
|
136
|
-
for a_splitted in a.split()
|
137
|
-
]
|
138
|
-
|
139
|
-
@ property
|
140
|
-
def _base_args(self):
|
141
|
-
args = self._var_args + self._const_args + self.user_args
|
142
|
-
|
143
|
-
if self._qmp_set:
|
144
|
-
if self._sock_pair:
|
145
|
-
moncdev = f"socket,id=mon,fd={self._sock_pair[0].fileno()}"
|
146
|
-
elif isinstance(self._monitor_address, tuple):
|
147
|
-
moncdev = "socket,id=mon,host={},port={}".format(
|
148
|
-
*self._monitor_address
|
149
|
-
)
|
150
|
-
else:
|
151
|
-
moncdev = f"socket,id=mon,path={self._monitor_address}"
|
152
|
-
args.extend(['-chardev', moncdev, '-mon',
|
153
|
-
'chardev=mon,mode=control'])
|
154
|
-
|
155
|
-
if self._machine is not None:
|
156
|
-
args.extend(['-machine', self._machine])
|
157
|
-
for _ in range(self._console_index):
|
158
|
-
args.extend(['-serial', 'null'])
|
159
|
-
if self._console_set:
|
160
|
-
assert self._cons_sock_pair is not None
|
161
|
-
fd = self._cons_sock_pair[0].fileno()
|
162
|
-
chardev = f"socket,id=console,fd={fd}"
|
163
|
-
args.extend(['-chardev', chardev])
|
164
|
-
if self._console_device_type is None:
|
165
|
-
args.extend(['-serial', 'chardev:console'])
|
166
|
-
else:
|
167
|
-
device = '%s,chardev=console' % self._console_device_type
|
168
|
-
args.extend(['-device', device])
|
169
|
-
return args
|
170
|
-
|
171
|
-
def send_keys(self, keys: list[str] = []) -> dict:
|
172
|
-
LOG.debug(f"QMP: keys to input: {keys}")
|
173
|
-
command = "input-send-event"
|
174
|
-
|
175
|
-
arguments = benedict({"events": []})
|
176
|
-
arguments.events = []
|
177
|
-
|
178
|
-
for k in keys:
|
179
|
-
arguments.events.append(benedict(
|
180
|
-
{
|
181
|
-
"type": "key",
|
182
|
-
"data": {"down": True, "key":
|
183
|
-
{"type": "qcode", "data": k}},
|
184
|
-
}
|
185
|
-
))
|
186
|
-
|
187
|
-
r = self.qmp(cmd=command, args_dict=arguments)
|
188
|
-
LOG.debug(f"QMP: {keys}")
|
189
|
-
|
190
|
-
for e in arguments.events:
|
191
|
-
e.data.down = False
|
192
|
-
|
193
|
-
r = self.qmp(cmd=command, args_dict=arguments)
|
194
|
-
LOG.debug(f"QMP: {keys}")
|
195
|
-
return r
|
196
|
-
|
197
|
-
def send_input(self, string: str = "",):
|
198
|
-
"""
|
199
|
-
Send input string to VM by emulating key press events
|
200
|
-
"""
|
201
|
-
chars = list(string)
|
202
|
-
|
203
|
-
for c in chars:
|
204
|
-
keys = []
|
205
|
-
if c in SPEC_CHAR_KEYS.keys(): # Enter
|
206
|
-
keys = SPEC_CHAR_KEYS[c]
|
207
|
-
elif c.isnumeric(): # Numbers
|
208
|
-
keys.append(c)
|
209
|
-
elif c.isalpha(): # Letters
|
210
|
-
if c.isupper():
|
211
|
-
keys.append('shift')
|
212
|
-
keys.append(c.lower())
|
213
|
-
|
214
|
-
LOG.debug(f"Sending keys: {keys}")
|
215
|
-
self.send_keys(keys=keys)
|
216
|
-
time.sleep(self._config.typing_delay)
|
217
|
-
|
218
|
-
def qmp_command(self, command_name: str = None, verbose=False,
|
219
|
-
*args, **kwargs) -> dict:
|
220
|
-
"""
|
221
|
-
Execute custom or pre-cooked qmp command from config.qmp_commands
|
222
|
-
"""
|
223
|
-
# TODO: add kwargs usage for templating cooked commands
|
224
|
-
if command_name is None:
|
225
|
-
command = kwargs
|
226
|
-
else:
|
227
|
-
if 'qmp_commands' not in self._config:
|
228
|
-
raise MachineError('qmp_commands not stated in config')
|
229
|
-
if command_name not in self._config.qmp_commands:
|
230
|
-
raise MachineError('qmp command not stated qmp_commands')
|
231
|
-
command = self._config.qmp_commands[command_name]
|
232
|
-
|
233
|
-
if 'execute' not in command:
|
234
|
-
raise MachineError(
|
235
|
-
'qmp command: execute key and value not found')
|
236
|
-
|
237
|
-
if 'arguments' in command:
|
238
|
-
r = self.qmp(cmd=command.execute, args_dict=command.arguments)
|
239
|
-
else:
|
240
|
-
r = self.qmp(cmd=command.execute)
|
241
|
-
|
242
|
-
if verbose:
|
243
|
-
LOG.debug(f"QMP: {command}\nRETURN: {r}")
|
244
|
-
return r
|
245
|
-
|
246
|
-
def shutdown(self, *args, **kwargs):
|
247
|
-
"""
|
248
|
-
Perform shutdown if machine is running
|
249
|
-
"""
|
250
|
-
if self.is_running():
|
251
|
-
super().shutdown(*args, **kwargs)
|
252
|
-
|
253
|
-
|
254
|
-
class Maqet:
|
255
|
-
"""
|
256
|
-
TODO
|
257
|
-
"""
|
258
|
-
|
259
|
-
def __init__(self, *args, **kwargs) -> None:
|
260
|
-
self.Machine = Machine # For comfortable stage building
|
261
|
-
self._config = benedict(kwargs)
|
262
|
-
|
263
|
-
self._validate_config()
|
264
|
-
|
265
|
-
self._stages = dict()
|
266
|
-
self.storage: dict[str, Drive] = dict()
|
267
|
-
|
268
|
-
def __call__(self, *args, **kwargs) -> None:
|
269
|
-
# Start pipeline
|
270
|
-
|
271
|
-
LOG.info(f"Stages to run: {args}")
|
272
|
-
|
273
|
-
for stage in args:
|
274
|
-
if stage in self._stages:
|
275
|
-
LOG.info(f"Executing stage {stage}")
|
276
|
-
with self.Machine(**self._config.deepcopy()) as vm:
|
277
|
-
self._stages[stage](vm)
|
278
|
-
else:
|
279
|
-
LOG.warning(f"Stage {stage} not found. Skipping")
|
280
|
-
|
281
|
-
def _validate_config(self):
|
282
|
-
default_config_fields = {
|
283
|
-
'binary': 'qemu-system-x86_64',
|
284
|
-
'arguments': [],
|
285
|
-
'user_arguments': [],
|
286
|
-
'storage': {}
|
287
|
-
}
|
288
|
-
|
289
|
-
for k, v in default_config_fields.items():
|
290
|
-
if k not in self._config:
|
291
|
-
self._config[k] = v
|
292
|
-
|
293
|
-
@property
|
294
|
-
def command(self) -> str:
|
295
|
-
"""
|
296
|
-
get full command string that will be executed at start
|
297
|
-
"""
|
298
|
-
with self.Machine(**self._config) as vm:
|
299
|
-
return vm.command
|
300
|
-
|
301
|
-
@property
|
302
|
-
def DRIVE_TYPES(self) -> list:
|
303
|
-
"""
|
304
|
-
Get available drive types
|
305
|
-
"""
|
306
|
-
return list(DRIVE_TYPES)
|
307
|
-
|
308
|
-
@property
|
309
|
-
def config(self) -> dict:
|
310
|
-
return self._config
|
311
|
-
|
312
|
-
@config.setter
|
313
|
-
def set_config(self, new_config: dict):
|
314
|
-
self._config = benedict(new_config)
|
315
|
-
self._validate_config()
|
316
|
-
|
317
|
-
def merge_config(self, new_config: dict):
|
318
|
-
self._config.merge(new_config)
|
319
|
-
self._validate_config()
|
320
|
-
|
321
|
-
def add_argument(self, argument: str) -> None:
|
322
|
-
"""
|
323
|
-
Add user argument to config.
|
324
|
-
It will be added to Machine arguments in every stage
|
325
|
-
"""
|
326
|
-
self._config['user_arguments'].append(argument)
|
327
|
-
|
328
|
-
def stage(self, stage_func: Callable, *args, **kwargs) -> Callable:
|
329
|
-
"""
|
330
|
-
Include function as stage into Maqet pipeline. Does not modify function
|
331
|
-
"""
|
332
|
-
self._stages[stage_func.__name__] = lambda vm: stage_func(vm)
|
333
|
-
|
334
|
-
@ wraps
|
335
|
-
def wrapper(*args, **kwargs):
|
336
|
-
raise MaqetError(
|
337
|
-
"Do not call stage functions by themselves, "
|
338
|
-
f"call {self.__class__}(<stage function name>)"
|
339
|
-
f"or {self.__class__}.cli() "
|
340
|
-
"and enter stages as positional args"
|
341
|
-
)
|
342
|
-
return wrapper
|
343
|
-
|
344
|
-
def cli(self, *args, **kwargs) -> None:
|
345
|
-
"""
|
346
|
-
Run Maqet in Command Line Interface mode
|
347
|
-
"""
|
348
|
-
parser = argparse.ArgumentParser()
|
349
|
-
|
350
|
-
parser.add_argument(
|
351
|
-
"stage",
|
352
|
-
nargs="*",
|
353
|
-
help="stages to run. If not stated - "
|
354
|
-
"start VM with given config and wait for shutdown",
|
355
|
-
)
|
356
|
-
parser.add_argument(
|
357
|
-
"-c", "--config-file",
|
358
|
-
help="Set yaml file as a config",
|
359
|
-
required=False,
|
360
|
-
default=None,
|
361
|
-
type=Path,
|
362
|
-
)
|
363
|
-
parser.add_argument(
|
364
|
-
"-a", "--argument",
|
365
|
-
help="State additional argument for qemu binary",
|
366
|
-
action="append",
|
367
|
-
default=[],
|
368
|
-
# nargs="*",
|
369
|
-
)
|
370
|
-
parser.add_argument(
|
371
|
-
"-s", "--storage-path",
|
372
|
-
help="Set default path for drives",
|
373
|
-
required=False,
|
374
|
-
type=Path,
|
375
|
-
default=None
|
376
|
-
)
|
377
|
-
parser.add_argument(
|
378
|
-
"-v", "--verbose",
|
379
|
-
action='count',
|
380
|
-
help="increase verbose level",
|
381
|
-
default=0
|
382
|
-
)
|
383
|
-
parser.add_argument(
|
384
|
-
"--command",
|
385
|
-
action='store_true',
|
386
|
-
help="Output command with config and exit",
|
387
|
-
default=False
|
388
|
-
)
|
389
|
-
|
390
|
-
cli_args = parser.parse_args()
|
391
|
-
LOG.setLevel(50 - cli_args.verbose *
|
392
|
-
10 if cli_args.verbose < 5 else 10)
|
393
|
-
|
394
|
-
LOG.info(cli_args)
|
395
|
-
|
396
|
-
if cli_args.storage_path is not None:
|
397
|
-
self._config.storage_path = cli_args.storage_path
|
398
|
-
if cli_args.config_file is not None:
|
399
|
-
self.merge_config(
|
400
|
-
benedict.from_yaml(cli_args.config_file.resolve())
|
401
|
-
)
|
402
|
-
if len(cli_args.argument) > 0:
|
403
|
-
for a in cli_args.argument:
|
404
|
-
self.add_argument(a)
|
405
|
-
if cli_args.command:
|
406
|
-
print(self.command)
|
407
|
-
exit(0)
|
408
|
-
|
409
|
-
self(
|
410
|
-
*cli_args.stage,
|
411
|
-
)
|
maqet/functions.py
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import subprocess
|
3
|
-
from pathlib import Path
|
4
|
-
from typing import List
|
5
|
-
|
6
|
-
from benedict import benedict
|
7
|
-
|
8
|
-
from .logger import LOG
|
9
|
-
|
10
|
-
|
11
|
-
def shell_command(command: str, verbose: bool = True) -> benedict:
|
12
|
-
"""
|
13
|
-
Run shell command and return dictionary of stdout, stderr, returncode
|
14
|
-
Return is benedict object, members can be accessed as fields
|
15
|
-
"""
|
16
|
-
command = " ".join(command.split())
|
17
|
-
|
18
|
-
proc = subprocess.Popen(command, shell=True,
|
19
|
-
stdout=subprocess.PIPE,
|
20
|
-
stderr=subprocess.PIPE)
|
21
|
-
out = proc.communicate()
|
22
|
-
|
23
|
-
output = benedict({
|
24
|
-
"stdout": out[0].decode('ascii').strip("\n"),
|
25
|
-
"stderr": out[1].decode('ascii').strip("\n"),
|
26
|
-
"rc": proc.returncode
|
27
|
-
})
|
28
|
-
|
29
|
-
message = f"command `{command}` returned {output}"
|
30
|
-
|
31
|
-
if verbose:
|
32
|
-
level = logging.DEBUG
|
33
|
-
if output.stderr != '':
|
34
|
-
level = logging.WARNING
|
35
|
-
if output.rc != 0:
|
36
|
-
level = logging.ERROR
|
37
|
-
|
38
|
-
LOG.log(level, message)
|
39
|
-
return output
|
40
|
-
|
41
|
-
|
42
|
-
def mount_disk_to_host(path: Path) -> Path:
|
43
|
-
return Path(shell_command(f"""
|
44
|
-
udiskie-mount {str(path)} | grep mounted |\
|
45
|
-
grep -o 'on .*$' | sed 's/on //'
|
46
|
-
""").stdout)
|
47
|
-
|
48
|
-
|
49
|
-
def split_args(args: List):
|
50
|
-
"""
|
51
|
-
Split args by spaces, used to send them into qemu methods
|
52
|
-
"""
|
53
|
-
return [
|
54
|
-
a_splitted
|
55
|
-
for a in args
|
56
|
-
for a_splitted in a.split()
|
57
|
-
]
|
58
|
-
|
59
|
-
|
60
|
-
def parse_options(arg, stack=[], key_only=False):
|
61
|
-
if not isinstance(arg, (list, dict)):
|
62
|
-
if len(stack) > 0:
|
63
|
-
if key_only:
|
64
|
-
return '.'.join(stack) + f'.{arg}'
|
65
|
-
else:
|
66
|
-
return '.'.join(stack) + f'={arg}'
|
67
|
-
else:
|
68
|
-
return arg
|
69
|
-
|
70
|
-
options = []
|
71
|
-
if isinstance(arg, list):
|
72
|
-
for v in arg:
|
73
|
-
if isinstance(arg, (list, dict)):
|
74
|
-
options.append(parse_options(v, stack, key_only=True))
|
75
|
-
else:
|
76
|
-
options.append('.'.join(stack) + f'.{v}')
|
77
|
-
|
78
|
-
elif isinstance(arg, dict):
|
79
|
-
for k, v in arg.items():
|
80
|
-
if isinstance(arg, (list, dict)):
|
81
|
-
options.append(parse_options(v, stack+[k], key_only=False))
|
82
|
-
else:
|
83
|
-
option = '.'.join(stack) + f'={v}'
|
84
|
-
options.append(option)
|
85
|
-
return ','.join(options)
|
86
|
-
|
87
|
-
|
88
|
-
def parse_args(args: list) -> List[str]:
|
89
|
-
final_args = []
|
90
|
-
|
91
|
-
for arg in args:
|
92
|
-
if type(arg) is str:
|
93
|
-
argument = f'-{arg}'
|
94
|
-
else:
|
95
|
-
al = list(arg.items())
|
96
|
-
if len(al) == 1:
|
97
|
-
argument = f"-{al[0][0]} {parse_options(al[0][1])}"
|
98
|
-
else:
|
99
|
-
subarg = arg.copy()
|
100
|
-
del subarg[al[0][0]]
|
101
|
-
argument = f"-{al[0][0]} {al[0][1]},{parse_options(subarg)}"
|
102
|
-
final_args.append(argument)
|
103
|
-
|
104
|
-
return split_args(final_args)
|
maqet-0.0.1.4.dist-info/METADATA
DELETED
maqet-0.0.1.4.dist-info/RECORD
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
maqet/__init__.py,sha256=hH-7x9aitvZKK46YFjdGLvHRSGMl67QLWwYlzikeoRw,96
|
2
|
-
maqet/core.py,sha256=lq1sQU3lGSiADiD_nYMKXv4zYvhSrJaVPfSDzv03wiw,12274
|
3
|
-
maqet/functions.py,sha256=gZRIeCZpalnK6T9ktDzGHIT8LzniXaEMdzFNVTccXOo,2856
|
4
|
-
maqet/logger.py,sha256=3N9TnInogdYVZ7DrT6Cg6lL8Q-c6AufBDspy9RmLWhk,1821
|
5
|
-
maqet/storage.py,sha256=09atk3-eMf2xH-CGdwrr9D-zHMPXkaLXT1AIjZ6WMxI,6273
|
6
|
-
qemu/machine/__init__.py,sha256=X8_E5OIwoB8zsmqb8mJGOozzSlm5zujaJih6I12BBdg,945
|
7
|
-
qemu/machine/console_socket.py,sha256=uZdScPgbtQXjAtzpBIpXwLuLgMj6MMblaOj4jLjYaEM,5314
|
8
|
-
qemu/machine/machine.py,sha256=wXb2TmPfS9HOC5HoCKhZ0pwcXolqDNi10YmCQs14sCU,32965
|
9
|
-
qemu/machine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
qemu/machine/qtest.py,sha256=ELhoX5pSIL4jeUZjlT5oh5wty4zOTdcfasAjTBxel1Y,5926
|
11
|
-
qemu/qmp/__init__.py,sha256=Gz9qHFm1IPfva9CmBOT1H4MjBygpzXTK-JrHP0ba71E,1545
|
12
|
-
qemu/qmp/error.py,sha256=tCa_0PXVfGfj0-U88WzYnIpSVoo2kCnvyEZWh0hMp0A,1701
|
13
|
-
qemu/qmp/events.py,sha256=ztOo_BbzLJZC3_X0EV4BhY5ibNt0CjnGVWAWEmTTiVk,22653
|
14
|
-
qemu/qmp/legacy.py,sha256=zogqHC05n8RineXAD68iEP6K6RQFMZTlwx9wSpq3zvc,9962
|
15
|
-
qemu/qmp/message.py,sha256=HxYZ5XguixBi1G6xXrKI5NQLekxzdPuOLxeWpz9Qhxw,6355
|
16
|
-
qemu/qmp/models.py,sha256=mz3oDKmHUjro9vFDreooD0PucNFU4tCKJVYxTFfWdN8,4418
|
17
|
-
qemu/qmp/protocol.py,sha256=d-3pInzEUJqI_RlM6IOOyYCOruEEfLm0U96NIjZa1OA,38506
|
18
|
-
qemu/qmp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
qemu/qmp/qmp_client.py,sha256=LqHwh1cFUcgr8kWYBo9Z1XIlrMNypL9_4xeLQ9kRdGk,22584
|
20
|
-
qemu/qmp/qmp_shell.py,sha256=LbI2bIlrGLbKIbLSeGyoxA_Vh4Eb1j3R8fqYxLqrP6c,19897
|
21
|
-
qemu/qmp/qmp_tui.py,sha256=DRq2VhEqG8WkyQ7OdPVKYvJYi502WDpmHQDbISU4Rac,22318
|
22
|
-
qemu/qmp/util.py,sha256=A2ThMPFtt6CpqNGPa4F6T2D4vmhTcyEPGe8vjBV9Bbk,6231
|
23
|
-
qemu/utils/__init__.py,sha256=hC2_82OPDhVTKE6UUG_bsuBVDkqjwD7LArxBxuzu8BY,5646
|
24
|
-
qemu/utils/accel.py,sha256=jOuuDLXyJMjZX9Uae-XnhNdYFnrXMlaGaUlxyCNntwU,2348
|
25
|
-
qemu/utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
-
qemu/utils/qemu_ga_client.py,sha256=ycQ6lOh7Q0DEwvNq_LyE0Y4DRZfimq8kjhNlyn3K0Zk,9484
|
27
|
-
qemu/utils/qom.py,sha256=sC2wXMZ_dH4E5HnYinjCMpagx_I-9NJ5oJi0rEiqqQQ,7564
|
28
|
-
qemu/utils/qom_common.py,sha256=UQitmqLNGYfd3DoMaLNxRprgJeaEs6hX-8mrhGQ2mkc,4991
|
29
|
-
qemu/utils/qom_fuse.py,sha256=uDbTKVWWej1Ey1Jsnw2p9sjmuLC_2vBBtBZpPG40I-k,5966
|
30
|
-
maqet-0.0.1.4.dist-info/METADATA,sha256=sltSMjplayRAPOPAf5RV8rJ8s_xXdZufdEVPWp5OXGs,116
|
31
|
-
maqet-0.0.1.4.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
32
|
-
maqet-0.0.1.4.dist-info/top_level.txt,sha256=9J0eHJ7TIdifxVkOxhgWVSyxkKRQhuFcbqUzIjhmgWg,11
|
33
|
-
maqet-0.0.1.4.dist-info/RECORD,,
|
qemu/machine/__init__.py
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
QEMU development and testing library.
|
3
|
-
|
4
|
-
This library provides a few high-level classes for driving QEMU from a
|
5
|
-
test suite, not intended for production use.
|
6
|
-
|
7
|
-
| QEMUQtestProtocol: send/receive qtest messages.
|
8
|
-
| QEMUMachine: Configure and Boot a QEMU VM
|
9
|
-
| +-- QEMUQtestMachine: VM class, with a qtest socket.
|
10
|
-
|
11
|
-
"""
|
12
|
-
|
13
|
-
# Copyright (C) 2020-2021 John Snow for Red Hat Inc.
|
14
|
-
# Copyright (C) 2015-2016 Red Hat Inc.
|
15
|
-
# Copyright (C) 2012 IBM Corp.
|
16
|
-
#
|
17
|
-
# Authors:
|
18
|
-
# John Snow <jsnow@redhat.com>
|
19
|
-
# Fam Zheng <fam@euphon.net>
|
20
|
-
#
|
21
|
-
# This work is licensed under the terms of the GNU GPL, version 2. See
|
22
|
-
# the COPYING file in the top-level directory.
|
23
|
-
#
|
24
|
-
|
25
|
-
# pylint: disable=import-error
|
26
|
-
# see: https://github.com/PyCQA/pylint/issues/3624
|
27
|
-
# see: https://github.com/PyCQA/pylint/issues/3651
|
28
|
-
from .machine import QEMUMachine
|
29
|
-
from .qtest import QEMUQtestMachine, QEMUQtestProtocol
|
30
|
-
|
31
|
-
|
32
|
-
__all__ = (
|
33
|
-
'QEMUMachine',
|
34
|
-
'QEMUQtestProtocol',
|
35
|
-
'QEMUQtestMachine',
|
36
|
-
)
|