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/constants.py
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
"""
|
2
|
+
Maqet Constants and Defaults
|
3
|
+
|
4
|
+
Centralizes magic numbers for maintainability and documentation.
|
5
|
+
All timeout values are in seconds unless otherwise noted.
|
6
|
+
"""
|
7
|
+
|
8
|
+
|
9
|
+
class Timeouts:
|
10
|
+
"""Timeout values in seconds."""
|
11
|
+
|
12
|
+
# VM operations
|
13
|
+
VM_START = 30
|
14
|
+
VM_STOP = 30
|
15
|
+
VM_GRACEFUL_SHUTDOWN = 5
|
16
|
+
VM_GRACEFUL_SHUTDOWN_SHORT = 2 # Shorter timeout for cleanup/exit scenarios
|
17
|
+
VM_FORCE_KILL = 5
|
18
|
+
|
19
|
+
# IPC operations
|
20
|
+
IPC_CONNECT = 10
|
21
|
+
IPC_COMMAND = 10
|
22
|
+
IPC_SOCKET_WAIT = 5
|
23
|
+
IPC_HEALTH_CHECK = 1
|
24
|
+
|
25
|
+
# Process operations
|
26
|
+
PROCESS_SPAWN = 30
|
27
|
+
PROCESS_KILL = 5
|
28
|
+
PROCESS_WAIT_AFTER_KILL = 1
|
29
|
+
|
30
|
+
# QEMU operations
|
31
|
+
QEMU_START = 60
|
32
|
+
QEMU_HEALTH_CHECK = 5
|
33
|
+
QEMU_QMP_THREAD_JOIN = 2
|
34
|
+
QMP_COMMAND = 30 # QMP command execution timeout
|
35
|
+
|
36
|
+
# Database operations
|
37
|
+
DB_LOCK = 30 # SQLite busy_timeout
|
38
|
+
DB_OPERATION_RETRY = 5 # Per-attempt timeout for DB operations
|
39
|
+
|
40
|
+
# Cleanup operations
|
41
|
+
CLEANUP_VM_STOP = 5
|
42
|
+
CLEANUP_RUNNER_STOP = 5
|
43
|
+
|
44
|
+
# Binary validation
|
45
|
+
BINARY_VERSION_CHECK = 5
|
46
|
+
|
47
|
+
|
48
|
+
class Intervals:
|
49
|
+
"""Polling and check intervals in seconds."""
|
50
|
+
|
51
|
+
# Event loop and polling
|
52
|
+
EVENT_LOOP_SLEEP = 0.05 # 50ms
|
53
|
+
SOCKET_POLL = 0.1 # 100ms
|
54
|
+
PROCESS_POLL = 0.5 # 500ms
|
55
|
+
SHUTDOWN_POLL = 0.5 # Polling interval during VM shutdown
|
56
|
+
|
57
|
+
# Retry intervals
|
58
|
+
DB_RETRY_BASE = 0.1 # Base interval for exponential backoff (100ms)
|
59
|
+
IPC_BACKOFF_BASE = 0.5 # Base interval for IPC retry exponential backoff (500ms)
|
60
|
+
PROCESS_STARTUP_WAIT = 0.5 # Wait after spawning process
|
61
|
+
|
62
|
+
# Health checks
|
63
|
+
VM_HEALTH_CHECK = 0.1 # Check if VM process is alive
|
64
|
+
RUNNER_HEALTH_CHECK = 1 # Check if runner process is alive
|
65
|
+
|
66
|
+
# Signal handling
|
67
|
+
SIGTERM_WAIT = 2.0 # Wait after SIGTERM before sending SIGKILL
|
68
|
+
CLEANUP_WAIT = 1.0 # Wait for DB status updates and cleanup operations
|
69
|
+
|
70
|
+
|
71
|
+
class Retries:
|
72
|
+
"""Retry counts for operations."""
|
73
|
+
|
74
|
+
# Database operations
|
75
|
+
DB_OPERATION = 3 # Max attempts for DB operations with locks
|
76
|
+
DB_LOCK_MAX_ATTEMPTS = 10 # Max attempts for lock acquisition
|
77
|
+
|
78
|
+
# IPC operations
|
79
|
+
IPC_CONNECT = 3 # Max attempts for IPC connection
|
80
|
+
IPC_MAX_RETRIES = 3 # Max attempts for IPC operations (alias for consistency)
|
81
|
+
SOCKET_CONNECT = 5
|
82
|
+
|
83
|
+
# Snapshot operations
|
84
|
+
SNAPSHOT_OPERATION = 3 # Max attempts for transient snapshot failures
|
85
|
+
|
86
|
+
|
87
|
+
class Limits:
|
88
|
+
"""Size and count limits."""
|
89
|
+
|
90
|
+
# Configuration
|
91
|
+
CONFIG_MAX_SIZE = 1024 * 1024 # 1MB
|
92
|
+
CONFIG_MAX_DEPTH = 10 # Max depth for nested configuration
|
93
|
+
|
94
|
+
# Logging
|
95
|
+
LOG_FILE_MAX_SIZE = 10 * 1024 * 1024 # 10MB
|
96
|
+
LOG_MAX_BACKUPS = 5
|
97
|
+
|
98
|
+
# Resource limits
|
99
|
+
MAX_CONCURRENT_VMS = 100
|
100
|
+
MAX_STORAGE_DEVICES = 16 # QEMU limit
|
101
|
+
MAX_SNAPSHOT_NAME_LENGTH = 255
|
102
|
+
|
103
|
+
# IPC
|
104
|
+
MAX_IPC_MESSAGE_SIZE = 1024 * 1024 # 1MB
|
105
|
+
MAX_CONCURRENT_WORKERS = 10 # For parallel VM cleanup
|
106
|
+
|
107
|
+
|
108
|
+
class Paths:
|
109
|
+
"""Default path patterns.
|
110
|
+
|
111
|
+
These use format strings that can be filled in at runtime.
|
112
|
+
"""
|
113
|
+
|
114
|
+
# Runtime paths (XDG_RUNTIME_DIR)
|
115
|
+
SOCKET_PATTERN = "{runtime_dir}/maqet/sockets/{vm_id}.sock"
|
116
|
+
PID_PATTERN = "{runtime_dir}/maqet/pids/{vm_id}.pid"
|
117
|
+
|
118
|
+
# Data paths (XDG_DATA_HOME)
|
119
|
+
DATABASE_PATTERN = "{data_dir}/instances.db"
|
120
|
+
VM_DEFINITIONS_PATTERN = "{data_dir}/vm-definitions"
|
121
|
+
LOG_PATTERN = "{data_dir}/logs/vm_{vm_id}.log"
|
122
|
+
RUNNER_LOG_PATTERN = "{data_dir}/logs/runner_{vm_id}.log"
|
123
|
+
|
124
|
+
# Config paths (XDG_CONFIG_HOME)
|
125
|
+
CONFIG_PATTERN = "{config_dir}/maqet/config.toml"
|
126
|
+
|
127
|
+
|
128
|
+
class Database:
|
129
|
+
"""Database-specific constants."""
|
130
|
+
|
131
|
+
# Schema version
|
132
|
+
SCHEMA_VERSION = 2
|
133
|
+
|
134
|
+
# SQLite pragmas
|
135
|
+
JOURNAL_MODE = "WAL" # Write-Ahead Logging for better concurrency
|
136
|
+
SYNCHRONOUS = "NORMAL" # Balance between safety and performance
|
137
|
+
FOREIGN_KEYS = "ON" # Enable foreign key constraints
|
138
|
+
|
139
|
+
# Table names
|
140
|
+
TABLE_VM_INSTANCES = "vm_instances"
|
141
|
+
TABLE_SCHEMA_VERSION = "schema_version"
|
142
|
+
|
143
|
+
|
144
|
+
class QMP:
|
145
|
+
"""QMP (QEMU Machine Protocol) constants."""
|
146
|
+
|
147
|
+
# Key hold time (milliseconds)
|
148
|
+
DEFAULT_KEY_HOLD_TIME = 100
|
149
|
+
|
150
|
+
# QMP connection
|
151
|
+
CONNECTION_TIMEOUT = 10
|
152
|
+
COMMAND_TIMEOUT = 30
|
153
|
+
|
154
|
+
# Screenshot formats
|
155
|
+
SCREENSHOT_FORMAT_PPM = "ppm"
|
156
|
+
SCREENSHOT_FORMAT_PNG = "png"
|
157
|
+
|
158
|
+
|
159
|
+
class ProcessManagement:
|
160
|
+
"""Process management constants."""
|
161
|
+
|
162
|
+
# Process states
|
163
|
+
STATE_RUNNING = "running"
|
164
|
+
STATE_STOPPED = "stopped"
|
165
|
+
STATE_CREATED = "created"
|
166
|
+
STATE_FAILED = "failed"
|
167
|
+
|
168
|
+
# Signal handling
|
169
|
+
SIGNAL_GRACEFUL = 15 # SIGTERM
|
170
|
+
SIGNAL_FORCE = 9 # SIGKILL
|
171
|
+
|
172
|
+
|
173
|
+
class Defaults:
|
174
|
+
"""Default values for various operations."""
|
175
|
+
|
176
|
+
# VM configuration defaults
|
177
|
+
VM_MEMORY = "2G"
|
178
|
+
VM_CPU_CORES = 2
|
179
|
+
VM_DISPLAY = "none" # Headless by default
|
180
|
+
VM_VGA = "none" # No VGA for headless
|
181
|
+
|
182
|
+
# Storage defaults
|
183
|
+
STORAGE_INTERFACE = "virtio"
|
184
|
+
STORAGE_FORMAT = "qcow2"
|
185
|
+
|
186
|
+
# Snapshot defaults
|
187
|
+
SNAPSHOT_TIMEOUT = 60 # seconds
|
188
|
+
|
189
|
+
# Binary detection
|
190
|
+
QEMU_BINARY_PATHS = [
|
191
|
+
"/usr/bin/qemu-system-x86_64",
|
192
|
+
"/usr/local/bin/qemu-system-x86_64",
|
193
|
+
"/opt/homebrew/bin/qemu-system-x86_64", # macOS Homebrew
|
194
|
+
]
|
195
|
+
|
196
|
+
QEMU_IMG_BINARY_PATHS = [
|
197
|
+
"/usr/bin/qemu-img",
|
198
|
+
"/usr/local/bin/qemu-img",
|
199
|
+
"/opt/homebrew/bin/qemu-img", # macOS Homebrew
|
200
|
+
]
|
maqet/exceptions.py
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
"""
|
2
|
+
Maqet Exception Hierarchy
|
3
|
+
|
4
|
+
Provides specific exception types for better error handling and debugging.
|
5
|
+
All exceptions inherit from MaqetError base class for easy catching.
|
6
|
+
|
7
|
+
Exception Categories:
|
8
|
+
- Configuration errors: Config file issues, validation failures
|
9
|
+
- VM lifecycle errors: VM creation, start, stop, not found
|
10
|
+
- QMP errors: QMP connection and command failures
|
11
|
+
- Storage errors: Storage device creation and management
|
12
|
+
- Snapshot errors: Snapshot operations (create, load, list)
|
13
|
+
- State management errors: Database and state tracking
|
14
|
+
- Process errors: VM runner process management
|
15
|
+
- IPC errors: Inter-process communication failures
|
16
|
+
"""
|
17
|
+
|
18
|
+
|
19
|
+
class MaqetError(Exception):
|
20
|
+
"""Base exception for all Maqet errors."""
|
21
|
+
|
22
|
+
|
23
|
+
# Configuration Errors
|
24
|
+
class ConfigurationError(MaqetError):
|
25
|
+
"""Configuration-related errors."""
|
26
|
+
|
27
|
+
|
28
|
+
class ConfigFileNotFoundError(ConfigurationError):
|
29
|
+
"""Configuration file not found."""
|
30
|
+
|
31
|
+
|
32
|
+
class ConfigValidationError(ConfigurationError):
|
33
|
+
"""Configuration validation failed."""
|
34
|
+
|
35
|
+
|
36
|
+
class InvalidConfigurationError(ConfigurationError):
|
37
|
+
"""Configuration is invalid or malformed."""
|
38
|
+
|
39
|
+
|
40
|
+
# VM Lifecycle Errors
|
41
|
+
class VMLifecycleError(MaqetError):
|
42
|
+
"""VM lifecycle operation errors."""
|
43
|
+
|
44
|
+
|
45
|
+
class VMNotFoundError(VMLifecycleError):
|
46
|
+
"""VM not found in database."""
|
47
|
+
|
48
|
+
|
49
|
+
class VMAlreadyExistsError(VMLifecycleError):
|
50
|
+
"""VM with this name already exists."""
|
51
|
+
|
52
|
+
|
53
|
+
class VMAlreadyRunningError(VMLifecycleError):
|
54
|
+
"""VM is already running."""
|
55
|
+
|
56
|
+
|
57
|
+
class VMNotRunningError(VMLifecycleError):
|
58
|
+
"""VM is not running."""
|
59
|
+
|
60
|
+
|
61
|
+
class VMStartError(VMLifecycleError):
|
62
|
+
"""Failed to start VM."""
|
63
|
+
|
64
|
+
|
65
|
+
class VMStopError(VMLifecycleError):
|
66
|
+
"""Failed to stop VM."""
|
67
|
+
|
68
|
+
|
69
|
+
# QMP Errors
|
70
|
+
class QMPError(MaqetError):
|
71
|
+
"""QMP command errors."""
|
72
|
+
|
73
|
+
|
74
|
+
class QMPConnectionError(QMPError):
|
75
|
+
"""Failed to connect to QMP socket."""
|
76
|
+
|
77
|
+
|
78
|
+
class QMPCommandError(QMPError):
|
79
|
+
"""QMP command execution failed."""
|
80
|
+
|
81
|
+
|
82
|
+
class QMPTimeoutError(QMPError):
|
83
|
+
"""QMP command timed out."""
|
84
|
+
|
85
|
+
|
86
|
+
# Storage Errors
|
87
|
+
class StorageError(MaqetError):
|
88
|
+
"""Storage operation errors."""
|
89
|
+
|
90
|
+
|
91
|
+
class StorageDeviceNotFoundError(StorageError):
|
92
|
+
"""Storage device not found."""
|
93
|
+
|
94
|
+
|
95
|
+
class StorageCreationError(StorageError):
|
96
|
+
"""Failed to create storage device."""
|
97
|
+
|
98
|
+
|
99
|
+
class StorageValidationError(StorageError):
|
100
|
+
"""Storage configuration validation failed."""
|
101
|
+
|
102
|
+
|
103
|
+
# Snapshot Errors
|
104
|
+
class SnapshotError(MaqetError):
|
105
|
+
"""Snapshot operation errors."""
|
106
|
+
|
107
|
+
|
108
|
+
class SnapshotNotFoundError(SnapshotError):
|
109
|
+
"""Snapshot not found."""
|
110
|
+
|
111
|
+
|
112
|
+
class SnapshotCreationError(SnapshotError):
|
113
|
+
"""Failed to create snapshot."""
|
114
|
+
|
115
|
+
|
116
|
+
class SnapshotLoadError(SnapshotError):
|
117
|
+
"""Failed to load snapshot."""
|
118
|
+
|
119
|
+
|
120
|
+
class SnapshotDeleteError(SnapshotError):
|
121
|
+
"""Failed to delete snapshot."""
|
122
|
+
|
123
|
+
|
124
|
+
# State Management Errors
|
125
|
+
class StateError(MaqetError):
|
126
|
+
"""State management errors."""
|
127
|
+
|
128
|
+
|
129
|
+
class DatabaseError(StateError):
|
130
|
+
"""Database operation failed."""
|
131
|
+
|
132
|
+
|
133
|
+
class DatabaseLockError(DatabaseError):
|
134
|
+
"""Database is locked (timeout waiting for lock)."""
|
135
|
+
|
136
|
+
|
137
|
+
# Process Management Errors
|
138
|
+
class ProcessError(MaqetError):
|
139
|
+
"""Process management errors."""
|
140
|
+
|
141
|
+
|
142
|
+
class RunnerProcessError(ProcessError):
|
143
|
+
"""VM runner process error."""
|
144
|
+
|
145
|
+
|
146
|
+
class RunnerSpawnError(ProcessError):
|
147
|
+
"""Failed to spawn VM runner."""
|
148
|
+
|
149
|
+
|
150
|
+
class ProcessNotFoundError(ProcessError):
|
151
|
+
"""Process not found or already dead."""
|
152
|
+
|
153
|
+
|
154
|
+
# IPC Errors
|
155
|
+
class IPCError(MaqetError):
|
156
|
+
"""Inter-process communication errors."""
|
157
|
+
|
158
|
+
|
159
|
+
class IPCConnectionError(IPCError):
|
160
|
+
"""Failed to connect to IPC socket."""
|
161
|
+
|
162
|
+
|
163
|
+
class IPCTimeoutError(IPCError):
|
164
|
+
"""IPC communication timed out."""
|
165
|
+
|
166
|
+
|
167
|
+
class IPCCommandError(IPCError):
|
168
|
+
"""IPC command execution failed."""
|
169
|
+
|
170
|
+
|
171
|
+
# Legacy Exception Aliases (for backward compatibility)
|
172
|
+
# These map old exception names to new hierarchy
|
173
|
+
|
174
|
+
# Old: StateManagerError -> New: StateError
|
175
|
+
class StateManagerError(StateError):
|
176
|
+
"""DEPRECATED: Use StateError instead."""
|
177
|
+
|
178
|
+
|
179
|
+
# Old: VMManagerError -> New: VMLifecycleError
|
180
|
+
class VMManagerError(VMLifecycleError):
|
181
|
+
"""DEPRECATED: Use VMLifecycleError or specific subclass instead."""
|
182
|
+
|
183
|
+
|
184
|
+
# Old: QMPManagerError -> New: QMPError
|
185
|
+
class QMPManagerError(QMPError):
|
186
|
+
"""DEPRECATED: Use QMPError or specific subclass instead."""
|
187
|
+
|
188
|
+
|
189
|
+
# Old: SnapshotCoordinatorError -> New: SnapshotError
|
190
|
+
class SnapshotCoordinatorError(SnapshotError):
|
191
|
+
"""DEPRECATED: Use SnapshotError or specific subclass instead."""
|
192
|
+
|
193
|
+
|
194
|
+
# Old: ProcessSpawnerError -> New: RunnerSpawnError
|
195
|
+
class ProcessSpawnerError(RunnerSpawnError):
|
196
|
+
"""DEPRECATED: Use RunnerSpawnError instead."""
|
197
|
+
|
198
|
+
|
199
|
+
# Old: VMRunnerError -> New: RunnerProcessError
|
200
|
+
class VMRunnerError(RunnerProcessError):
|
201
|
+
"""DEPRECATED: Use RunnerProcessError instead."""
|
202
|
+
|
203
|
+
|
204
|
+
# Old: MachineError -> New: VMLifecycleError
|
205
|
+
class MachineError(VMLifecycleError):
|
206
|
+
"""DEPRECATED: Use VMLifecycleError or specific subclass instead."""
|
207
|
+
|
208
|
+
|
209
|
+
# Old: UnixSocketIPCServerError -> New: IPCError
|
210
|
+
class UnixSocketIPCServerError(IPCError):
|
211
|
+
"""DEPRECATED: Use IPCError or specific subclass instead."""
|
212
|
+
|
213
|
+
|
214
|
+
# Old: RunnerClientError -> New: IPCError
|
215
|
+
class RunnerClientError(IPCError):
|
216
|
+
"""DEPRECATED: Use IPCError or specific subclass instead."""
|
217
|
+
|
218
|
+
|
219
|
+
# Old: KeyboardEmulatorError -> New: QMPError
|
220
|
+
class KeyboardEmulatorError(QMPError):
|
221
|
+
"""DEPRECATED: Use QMPError instead."""
|
222
|
+
|
223
|
+
|
224
|
+
# Old: ConfigError -> New: ConfigurationError
|
225
|
+
class ConfigError(ConfigurationError):
|
226
|
+
"""DEPRECATED: Use ConfigurationError instead."""
|