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.
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.4.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.4.dist-info → maqet-0.0.5.dist-info}/top_level.txt +0 -1
  56. maqet/core.py +0 -411
  57. maqet/functions.py +0 -104
  58. maqet-0.0.1.4.dist-info/METADATA +0 -6
  59. maqet-0.0.1.4.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
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."""