maqet 0.0.1.3__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.
Files changed (83) hide show
  1. maqet/__init__.py +50 -6
  2. maqet/__main__.py +96 -0
  3. maqet/__version__.py +3 -0
  4. maqet/api/__init__.py +35 -0
  5. maqet/api/decorators.py +184 -0
  6. maqet/api/metadata.py +147 -0
  7. maqet/api/registry.py +182 -0
  8. maqet/cli.py +71 -0
  9. maqet/config/__init__.py +26 -0
  10. maqet/config/merger.py +237 -0
  11. maqet/config/parser.py +198 -0
  12. maqet/config/validators.py +519 -0
  13. maqet/config_handlers.py +684 -0
  14. maqet/constants.py +200 -0
  15. maqet/exceptions.py +226 -0
  16. maqet/formatters.py +294 -0
  17. maqet/generators/__init__.py +12 -0
  18. maqet/generators/base_generator.py +101 -0
  19. maqet/generators/cli_generator.py +635 -0
  20. maqet/generators/python_generator.py +247 -0
  21. maqet/generators/rest_generator.py +58 -0
  22. maqet/handlers/__init__.py +12 -0
  23. maqet/handlers/base.py +108 -0
  24. maqet/handlers/init.py +147 -0
  25. maqet/handlers/stage.py +196 -0
  26. maqet/ipc/__init__.py +29 -0
  27. maqet/ipc/retry.py +265 -0
  28. maqet/ipc/runner_client.py +285 -0
  29. maqet/ipc/unix_socket_server.py +239 -0
  30. maqet/logger.py +160 -55
  31. maqet/machine.py +884 -0
  32. maqet/managers/__init__.py +7 -0
  33. maqet/managers/qmp_manager.py +333 -0
  34. maqet/managers/snapshot_coordinator.py +327 -0
  35. maqet/managers/vm_manager.py +683 -0
  36. maqet/maqet.py +1120 -0
  37. maqet/os_interactions.py +46 -0
  38. maqet/process_spawner.py +395 -0
  39. maqet/qemu_args.py +76 -0
  40. maqet/qmp/__init__.py +10 -0
  41. maqet/qmp/commands.py +92 -0
  42. maqet/qmp/keyboard.py +311 -0
  43. maqet/qmp/qmp.py +17 -0
  44. maqet/snapshot.py +473 -0
  45. maqet/state.py +958 -0
  46. maqet/storage.py +702 -162
  47. maqet/validation/__init__.py +9 -0
  48. maqet/validation/config_validator.py +170 -0
  49. maqet/vm_runner.py +523 -0
  50. maqet-0.0.5.dist-info/METADATA +237 -0
  51. maqet-0.0.5.dist-info/RECORD +55 -0
  52. {maqet-0.0.1.3.dist-info → maqet-0.0.5.dist-info}/WHEEL +1 -1
  53. maqet-0.0.5.dist-info/entry_points.txt +2 -0
  54. maqet-0.0.5.dist-info/licenses/LICENSE +21 -0
  55. {maqet-0.0.1.3.dist-info → maqet-0.0.5.dist-info}/top_level.txt +0 -1
  56. maqet/core.py +0 -395
  57. maqet/functions.py +0 -104
  58. maqet-0.0.1.3.dist-info/METADATA +0 -104
  59. maqet-0.0.1.3.dist-info/RECORD +0 -33
  60. qemu/machine/__init__.py +0 -36
  61. qemu/machine/console_socket.py +0 -142
  62. qemu/machine/machine.py +0 -954
  63. qemu/machine/py.typed +0 -0
  64. qemu/machine/qtest.py +0 -191
  65. qemu/qmp/__init__.py +0 -59
  66. qemu/qmp/error.py +0 -50
  67. qemu/qmp/events.py +0 -717
  68. qemu/qmp/legacy.py +0 -319
  69. qemu/qmp/message.py +0 -209
  70. qemu/qmp/models.py +0 -146
  71. qemu/qmp/protocol.py +0 -1057
  72. qemu/qmp/py.typed +0 -0
  73. qemu/qmp/qmp_client.py +0 -655
  74. qemu/qmp/qmp_shell.py +0 -618
  75. qemu/qmp/qmp_tui.py +0 -655
  76. qemu/qmp/util.py +0 -219
  77. qemu/utils/__init__.py +0 -162
  78. qemu/utils/accel.py +0 -84
  79. qemu/utils/py.typed +0 -0
  80. qemu/utils/qemu_ga_client.py +0 -323
  81. qemu/utils/qom.py +0 -273
  82. qemu/utils/qom_common.py +0 -175
  83. qemu/utils/qom_fuse.py +0 -207
qemu/qmp/util.py DELETED
@@ -1,219 +0,0 @@
1
- """
2
- Miscellaneous Utilities
3
-
4
- This module provides asyncio utilities and compatibility wrappers for
5
- Python 3.6 to provide some features that otherwise become available in
6
- Python 3.7+.
7
-
8
- Various logging and debugging utilities are also provided, such as
9
- `exception_summary()` and `pretty_traceback()`, used primarily for
10
- adding information into the logging stream.
11
- """
12
-
13
- import asyncio
14
- import sys
15
- import traceback
16
- from typing import (
17
- Any,
18
- Coroutine,
19
- Optional,
20
- TypeVar,
21
- cast,
22
- )
23
-
24
-
25
- T = TypeVar('T')
26
-
27
-
28
- # --------------------------
29
- # Section: Utility Functions
30
- # --------------------------
31
-
32
-
33
- async def flush(writer: asyncio.StreamWriter) -> None:
34
- """
35
- Utility function to ensure a StreamWriter is *fully* drained.
36
-
37
- `asyncio.StreamWriter.drain` only promises we will return to below
38
- the "high-water mark". This function ensures we flush the entire
39
- buffer -- by setting the high water mark to 0 and then calling
40
- drain. The flow control limits are restored after the call is
41
- completed.
42
- """
43
- transport = cast( # type: ignore[redundant-cast]
44
- asyncio.WriteTransport, writer.transport
45
- )
46
-
47
- # https://github.com/python/typeshed/issues/5779
48
- low, high = transport.get_write_buffer_limits() # type: ignore
49
- transport.set_write_buffer_limits(0, 0)
50
- try:
51
- await writer.drain()
52
- finally:
53
- transport.set_write_buffer_limits(high, low)
54
-
55
-
56
- def upper_half(func: T) -> T:
57
- """
58
- Do-nothing decorator that annotates a method as an "upper-half" method.
59
-
60
- These methods must not call bottom-half functions directly, but can
61
- schedule them to run.
62
- """
63
- return func
64
-
65
-
66
- def bottom_half(func: T) -> T:
67
- """
68
- Do-nothing decorator that annotates a method as a "bottom-half" method.
69
-
70
- These methods must take great care to handle their own exceptions whenever
71
- possible. If they go unhandled, they will cause termination of the loop.
72
-
73
- These methods do not, in general, have the ability to directly
74
- report information to a caller’s context and will usually be
75
- collected as a Task result instead.
76
-
77
- They must not call upper-half functions directly.
78
- """
79
- return func
80
-
81
-
82
- # -------------------------------
83
- # Section: Compatibility Wrappers
84
- # -------------------------------
85
-
86
-
87
- def create_task(coro: Coroutine[Any, Any, T],
88
- loop: Optional[asyncio.AbstractEventLoop] = None
89
- ) -> 'asyncio.Future[T]':
90
- """
91
- Python 3.6-compatible `asyncio.create_task` wrapper.
92
-
93
- :param coro: The coroutine to execute in a task.
94
- :param loop: Optionally, the loop to create the task in.
95
-
96
- :return: An `asyncio.Future` object.
97
- """
98
- if sys.version_info >= (3, 7):
99
- if loop is not None:
100
- return loop.create_task(coro)
101
- return asyncio.create_task(coro) # pylint: disable=no-member
102
-
103
- # Python 3.6:
104
- return asyncio.ensure_future(coro, loop=loop)
105
-
106
-
107
- def is_closing(writer: asyncio.StreamWriter) -> bool:
108
- """
109
- Python 3.6-compatible `asyncio.StreamWriter.is_closing` wrapper.
110
-
111
- :param writer: The `asyncio.StreamWriter` object.
112
- :return: `True` if the writer is closing, or closed.
113
- """
114
- if sys.version_info >= (3, 7):
115
- return writer.is_closing()
116
-
117
- # Python 3.6:
118
- transport = writer.transport
119
- assert isinstance(transport, asyncio.WriteTransport)
120
- return transport.is_closing()
121
-
122
-
123
- async def wait_closed(writer: asyncio.StreamWriter) -> None:
124
- """
125
- Python 3.6-compatible `asyncio.StreamWriter.wait_closed` wrapper.
126
-
127
- :param writer: The `asyncio.StreamWriter` to wait on.
128
- """
129
- if sys.version_info >= (3, 7):
130
- await writer.wait_closed()
131
- return
132
-
133
- # Python 3.6
134
- transport = writer.transport
135
- assert isinstance(transport, asyncio.WriteTransport)
136
-
137
- while not transport.is_closing():
138
- await asyncio.sleep(0)
139
-
140
- # This is an ugly workaround, but it's the best I can come up with.
141
- sock = transport.get_extra_info('socket')
142
-
143
- if sock is None:
144
- # Our transport doesn't have a socket? ...
145
- # Nothing we can reasonably do.
146
- return
147
-
148
- while sock.fileno() != -1:
149
- await asyncio.sleep(0)
150
-
151
-
152
- def asyncio_run(coro: Coroutine[Any, Any, T], *, debug: bool = False) -> T:
153
- """
154
- Python 3.6-compatible `asyncio.run` wrapper.
155
-
156
- :param coro: A coroutine to execute now.
157
- :return: The return value from the coroutine.
158
- """
159
- if sys.version_info >= (3, 7):
160
- return asyncio.run(coro, debug=debug)
161
-
162
- # Python 3.6
163
- loop = asyncio.get_event_loop()
164
- loop.set_debug(debug)
165
- ret = loop.run_until_complete(coro)
166
- loop.close()
167
-
168
- return ret
169
-
170
-
171
- # ----------------------------
172
- # Section: Logging & Debugging
173
- # ----------------------------
174
-
175
-
176
- def exception_summary(exc: BaseException) -> str:
177
- """
178
- Return a summary string of an arbitrary exception.
179
-
180
- It will be of the form "ExceptionType: Error Message", if the error
181
- string is non-empty, and just "ExceptionType" otherwise.
182
- """
183
- name = type(exc).__qualname__
184
- smod = type(exc).__module__
185
- if smod not in ("__main__", "builtins"):
186
- name = smod + '.' + name
187
-
188
- error = str(exc)
189
- if error:
190
- return f"{name}: {error}"
191
- return name
192
-
193
-
194
- def pretty_traceback(prefix: str = " | ") -> str:
195
- """
196
- Formats the current traceback, indented to provide visual distinction.
197
-
198
- This is useful for printing a traceback within a traceback for
199
- debugging purposes when encapsulating errors to deliver them up the
200
- stack; when those errors are printed, this helps provide a nice
201
- visual grouping to quickly identify the parts of the error that
202
- belong to the inner exception.
203
-
204
- :param prefix: The prefix to append to each line of the traceback.
205
- :return: A string, formatted something like the following::
206
-
207
- | Traceback (most recent call last):
208
- | File "foobar.py", line 42, in arbitrary_example
209
- | foo.baz()
210
- | ArbitraryError: [Errno 42] Something bad happened!
211
- """
212
- output = "".join(traceback.format_exception(*sys.exc_info()))
213
-
214
- exc_lines = []
215
- for line in output.split('\n'):
216
- exc_lines.append(prefix + line)
217
-
218
- # The last line is always empty, omit it
219
- return "\n".join(exc_lines[:-1])
qemu/utils/__init__.py DELETED
@@ -1,162 +0,0 @@
1
- """
2
- QEMU development and testing utilities
3
-
4
- This package provides a small handful of utilities for performing
5
- various tasks not directly related to the launching of a VM.
6
- """
7
-
8
- # Copyright (C) 2021 Red Hat Inc.
9
- #
10
- # Authors:
11
- # John Snow <jsnow@redhat.com>
12
- # Cleber Rosa <crosa@redhat.com>
13
- #
14
- # This work is licensed under the terms of the GNU GPL, version 2. See
15
- # the COPYING file in the top-level directory.
16
- #
17
-
18
- import os
19
- import re
20
- import shutil
21
- from subprocess import CalledProcessError
22
- import textwrap
23
- from typing import Optional
24
-
25
- # pylint: disable=import-error
26
- from .accel import kvm_available, list_accel, tcg_available
27
-
28
-
29
- __all__ = (
30
- 'VerboseProcessError',
31
- 'add_visual_margin',
32
- 'get_info_usernet_hostfwd_port',
33
- 'kvm_available',
34
- 'list_accel',
35
- 'tcg_available',
36
- )
37
-
38
-
39
- def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
40
- """
41
- Returns the port given to the hostfwd parameter via info usernet
42
-
43
- :param info_usernet_output: output generated by hmp command "info usernet"
44
- :return: the port number allocated by the hostfwd option
45
- """
46
- for line in info_usernet_output.split('\r\n'):
47
- regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
48
- match = re.search(regex, line)
49
- if match is not None:
50
- return int(match[1])
51
- return None
52
-
53
-
54
- # pylint: disable=too-many-arguments
55
- def add_visual_margin(
56
- content: str = '',
57
- width: Optional[int] = None,
58
- name: Optional[str] = None,
59
- padding: int = 1,
60
- upper_left: str = '┏',
61
- lower_left: str = '┗',
62
- horizontal: str = '━',
63
- vertical: str = '┃',
64
- ) -> str:
65
- """
66
- Decorate and wrap some text with a visual decoration around it.
67
-
68
- This function assumes that the text decoration characters are single
69
- characters that display using a single monospace column.
70
-
71
- ┏━ Example ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
72
- ┃ This is what this function looks like with text content that's
73
- ┃ wrapped to 66 characters. The right-hand margin is left open to
74
- ┃ accommodate the occasional unicode character that might make
75
- ┃ predicting the total "visual" width of a line difficult. This
76
- ┃ provides a visual distinction that's good-enough, though.
77
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
78
-
79
- :param content: The text to wrap and decorate.
80
- :param width:
81
- The number of columns to use, including for the decoration
82
- itself. The default (None) uses the available width of the
83
- current terminal, or a fallback of 72 lines. A negative number
84
- subtracts a fixed-width from the default size. The default obeys
85
- the COLUMNS environment variable, if set.
86
- :param name: A label to apply to the upper-left of the box.
87
- :param padding: How many columns of padding to apply inside.
88
- :param upper_left: Upper-left single-width text decoration character.
89
- :param lower_left: Lower-left single-width text decoration character.
90
- :param horizontal: Horizontal single-width text decoration character.
91
- :param vertical: Vertical single-width text decoration character.
92
- """
93
- if width is None or width < 0:
94
- avail = shutil.get_terminal_size(fallback=(72, 24))[0]
95
- if width is None:
96
- _width = avail
97
- else:
98
- _width = avail + width
99
- else:
100
- _width = width
101
-
102
- prefix = vertical + (' ' * padding)
103
-
104
- def _bar(name: Optional[str], top: bool = True) -> str:
105
- ret = upper_left if top else lower_left
106
- if name is not None:
107
- ret += f"{horizontal} {name} "
108
-
109
- filler_len = _width - len(ret)
110
- ret += f"{horizontal * filler_len}"
111
- return ret
112
-
113
- def _wrap(line: str) -> str:
114
- return os.linesep.join(
115
- textwrap.wrap(
116
- line, width=_width - padding, initial_indent=prefix,
117
- subsequent_indent=prefix, replace_whitespace=False,
118
- drop_whitespace=True, break_on_hyphens=False)
119
- )
120
-
121
- return os.linesep.join((
122
- _bar(name, top=True),
123
- os.linesep.join(_wrap(line) for line in content.splitlines()),
124
- _bar(None, top=False),
125
- ))
126
-
127
-
128
- class VerboseProcessError(CalledProcessError):
129
- """
130
- The same as CalledProcessError, but more verbose.
131
-
132
- This is useful for debugging failed calls during test executions.
133
- The return code, signal (if any), and terminal output will be displayed
134
- on unhandled exceptions.
135
- """
136
- def summary(self) -> str:
137
- """Return the normal CalledProcessError str() output."""
138
- return super().__str__()
139
-
140
- def __str__(self) -> str:
141
- lmargin = ' '
142
- width = -len(lmargin)
143
- sections = []
144
-
145
- # Does self.stdout contain both stdout and stderr?
146
- has_combined_output = self.stderr is None
147
-
148
- name = 'output' if has_combined_output else 'stdout'
149
- if self.stdout:
150
- sections.append(add_visual_margin(self.stdout, width, name))
151
- else:
152
- sections.append(f"{name}: N/A")
153
-
154
- if self.stderr:
155
- sections.append(add_visual_margin(self.stderr, width, 'stderr'))
156
- elif not has_combined_output:
157
- sections.append("stderr: N/A")
158
-
159
- return os.linesep.join((
160
- self.summary(),
161
- textwrap.indent(os.linesep.join(sections), prefix=lmargin),
162
- ))
qemu/utils/accel.py DELETED
@@ -1,84 +0,0 @@
1
- """
2
- QEMU accel module:
3
-
4
- This module provides utilities for discover and check the availability of
5
- accelerators.
6
- """
7
- # Copyright (C) 2015-2016 Red Hat Inc.
8
- # Copyright (C) 2012 IBM Corp.
9
- #
10
- # Authors:
11
- # Fam Zheng <famz@redhat.com>
12
- #
13
- # This work is licensed under the terms of the GNU GPL, version 2. See
14
- # the COPYING file in the top-level directory.
15
- #
16
-
17
- import logging
18
- import os
19
- import subprocess
20
- from typing import List, Optional
21
-
22
-
23
- LOG = logging.getLogger(__name__)
24
-
25
- # Mapping host architecture to any additional architectures it can
26
- # support which often includes its 32 bit cousin.
27
- ADDITIONAL_ARCHES = {
28
- "x86_64": "i386",
29
- "aarch64": "armhf",
30
- "ppc64le": "ppc64",
31
- }
32
-
33
-
34
- def list_accel(qemu_bin: str) -> List[str]:
35
- """
36
- List accelerators enabled in the QEMU binary.
37
-
38
- @param qemu_bin (str): path to the QEMU binary.
39
- @raise Exception: if failed to run ``qemu -accel help``
40
- @return a list of accelerator names.
41
- """
42
- if not qemu_bin:
43
- return []
44
- try:
45
- out = subprocess.check_output([qemu_bin, '-accel', 'help'],
46
- universal_newlines=True)
47
- except:
48
- LOG.debug("Failed to get the list of accelerators in %s", qemu_bin)
49
- raise
50
- # Skip the first line which is the header.
51
- return [acc.strip() for acc in out.splitlines()[1:]]
52
-
53
-
54
- def kvm_available(target_arch: Optional[str] = None,
55
- qemu_bin: Optional[str] = None) -> bool:
56
- """
57
- Check if KVM is available using the following heuristic:
58
- - Kernel module is present in the host;
59
- - Target and host arches don't mismatch;
60
- - KVM is enabled in the QEMU binary.
61
-
62
- @param target_arch (str): target architecture
63
- @param qemu_bin (str): path to the QEMU binary
64
- @return True if kvm is available, otherwise False.
65
- """
66
- if not os.access("/dev/kvm", os.R_OK | os.W_OK):
67
- return False
68
- if target_arch:
69
- host_arch = os.uname()[4]
70
- if target_arch != host_arch:
71
- if target_arch != ADDITIONAL_ARCHES.get(host_arch):
72
- return False
73
- if qemu_bin and "kvm" not in list_accel(qemu_bin):
74
- return False
75
- return True
76
-
77
-
78
- def tcg_available(qemu_bin: str) -> bool:
79
- """
80
- Check if TCG is available.
81
-
82
- @param qemu_bin (str): path to the QEMU binary
83
- """
84
- return 'tcg' in list_accel(qemu_bin)
qemu/utils/py.typed DELETED
File without changes