clonebox 1.1.13__py3-none-any.whl → 1.1.14__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.
@@ -0,0 +1,319 @@
1
+ """
2
+ Base classes for CloneBox plugins.
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ from dataclasses import dataclass, field
6
+ from enum import Enum
7
+ from typing import Optional, Dict, Any, List, Callable, Type
8
+
9
+
10
+ class PluginHook(Enum):
11
+ """Available plugin hooks."""
12
+ # VM Lifecycle
13
+ PRE_VM_CREATE = "pre_vm_create"
14
+ POST_VM_CREATE = "post_vm_create"
15
+ PRE_VM_START = "pre_vm_start"
16
+ POST_VM_START = "post_vm_start"
17
+ PRE_VM_STOP = "pre_vm_stop"
18
+ POST_VM_STOP = "post_vm_stop"
19
+ PRE_VM_DELETE = "pre_vm_delete"
20
+ POST_VM_DELETE = "post_vm_delete"
21
+
22
+ # Snapshot
23
+ PRE_SNAPSHOT_CREATE = "pre_snapshot_create"
24
+ POST_SNAPSHOT_CREATE = "post_snapshot_create"
25
+ PRE_SNAPSHOT_RESTORE = "pre_snapshot_restore"
26
+ POST_SNAPSHOT_RESTORE = "post_snapshot_restore"
27
+
28
+ # Health
29
+ PRE_HEALTH_CHECK = "pre_health_check"
30
+ POST_HEALTH_CHECK = "post_health_check"
31
+ ON_HEALTH_FAILURE = "on_health_failure"
32
+
33
+ # Config
34
+ PRE_CONFIG_LOAD = "pre_config_load"
35
+ POST_CONFIG_LOAD = "post_config_load"
36
+ CONFIG_VALIDATE = "config_validate"
37
+
38
+ # Cloud-init
39
+ CLOUD_INIT_CUSTOMIZE = "cloud_init_customize"
40
+
41
+ # Export/Import
42
+ PRE_EXPORT = "pre_export"
43
+ POST_EXPORT = "post_export"
44
+ PRE_IMPORT = "pre_import"
45
+ POST_IMPORT = "post_import"
46
+
47
+ # CLI
48
+ CLI_COMMAND_REGISTER = "cli_command_register"
49
+
50
+ # System
51
+ ON_ERROR = "on_error"
52
+ ON_STARTUP = "on_startup"
53
+ ON_SHUTDOWN = "on_shutdown"
54
+
55
+
56
+ @dataclass
57
+ class PluginMetadata:
58
+ """Metadata about a plugin."""
59
+ name: str
60
+ version: str
61
+ description: str = ""
62
+ author: str = ""
63
+ url: str = ""
64
+ dependencies: List[str] = field(default_factory=list)
65
+ hooks: List[PluginHook] = field(default_factory=list)
66
+ config_schema: Optional[Dict[str, Any]] = None
67
+
68
+ def to_dict(self) -> Dict[str, Any]:
69
+ """Convert to dictionary."""
70
+ return {
71
+ "name": self.name,
72
+ "version": self.version,
73
+ "description": self.description,
74
+ "author": self.author,
75
+ "url": self.url,
76
+ "dependencies": self.dependencies,
77
+ "hooks": [h.value for h in self.hooks],
78
+ }
79
+
80
+
81
+ @dataclass
82
+ class PluginContext:
83
+ """Context passed to plugin hooks."""
84
+ hook: PluginHook
85
+ vm_name: Optional[str] = None
86
+ config: Optional[Dict[str, Any]] = None
87
+ cloner: Optional[Any] = None
88
+ console: Optional[Any] = None
89
+ user_session: bool = False
90
+ extra: Dict[str, Any] = field(default_factory=dict)
91
+
92
+ # For modification by plugins
93
+ should_continue: bool = True
94
+ modified_config: Optional[Dict[str, Any]] = None
95
+ errors: List[str] = field(default_factory=list)
96
+ warnings: List[str] = field(default_factory=list)
97
+
98
+ def add_error(self, message: str) -> None:
99
+ """Add an error message."""
100
+ self.errors.append(message)
101
+
102
+ def add_warning(self, message: str) -> None:
103
+ """Add a warning message."""
104
+ self.warnings.append(message)
105
+
106
+ def cancel(self, reason: str = "") -> None:
107
+ """Cancel the operation."""
108
+ self.should_continue = False
109
+ if reason:
110
+ self.add_error(reason)
111
+
112
+ def add_detail(self, key: str, value: Any) -> None:
113
+ """Add a detail to the context's extra dict."""
114
+ self.extra[key] = value
115
+
116
+
117
+ class Plugin(ABC):
118
+ """
119
+ Base class for CloneBox plugins.
120
+
121
+ Plugins can hook into various points of CloneBox's lifecycle to:
122
+ - Modify configuration before VM creation
123
+ - Add custom cloud-init scripts
124
+ - Perform actions after VM operations
125
+ - Add custom CLI commands
126
+ - Integrate with external systems
127
+
128
+ Example:
129
+ class MyPlugin(Plugin):
130
+ @property
131
+ def metadata(self) -> PluginMetadata:
132
+ return PluginMetadata(
133
+ name="my-plugin",
134
+ version="1.0.0",
135
+ description="My custom plugin",
136
+ hooks=[PluginHook.POST_VM_CREATE],
137
+ )
138
+
139
+ def on_post_vm_create(self, ctx: PluginContext) -> None:
140
+ # Do something after VM is created
141
+ print(f"VM {ctx.vm_name} created!")
142
+ """
143
+
144
+ @property
145
+ @abstractmethod
146
+ def metadata(self) -> PluginMetadata:
147
+ """Return plugin metadata."""
148
+ pass
149
+
150
+ def initialize(self, config: Dict[str, Any]) -> None:
151
+ """
152
+ Initialize the plugin with configuration.
153
+ Called when plugin is loaded.
154
+ """
155
+ pass
156
+
157
+ def shutdown(self) -> None:
158
+ """
159
+ Cleanup when plugin is unloaded.
160
+ """
161
+ pass
162
+
163
+ # VM Lifecycle hooks
164
+ def on_pre_vm_create(self, ctx: PluginContext) -> None:
165
+ """Called before VM creation."""
166
+ pass
167
+
168
+ def on_post_vm_create(self, ctx: PluginContext) -> None:
169
+ """Called after VM creation."""
170
+ pass
171
+
172
+ def on_pre_vm_start(self, ctx: PluginContext) -> None:
173
+ """Called before VM start."""
174
+ pass
175
+
176
+ def on_post_vm_start(self, ctx: PluginContext) -> None:
177
+ """Called after VM start."""
178
+ pass
179
+
180
+ def on_pre_vm_stop(self, ctx: PluginContext) -> None:
181
+ """Called before VM stop."""
182
+ pass
183
+
184
+ def on_post_vm_stop(self, ctx: PluginContext) -> None:
185
+ """Called after VM stop."""
186
+ pass
187
+
188
+ def on_pre_vm_delete(self, ctx: PluginContext) -> None:
189
+ """Called before VM deletion."""
190
+ pass
191
+
192
+ def on_post_vm_delete(self, ctx: PluginContext) -> None:
193
+ """Called after VM deletion."""
194
+ pass
195
+
196
+ # Snapshot hooks
197
+ def on_pre_snapshot_create(self, ctx: PluginContext) -> None:
198
+ """Called before snapshot creation."""
199
+ pass
200
+
201
+ def on_post_snapshot_create(self, ctx: PluginContext) -> None:
202
+ """Called after snapshot creation."""
203
+ pass
204
+
205
+ def on_pre_snapshot_restore(self, ctx: PluginContext) -> None:
206
+ """Called before snapshot restore."""
207
+ pass
208
+
209
+ def on_post_snapshot_restore(self, ctx: PluginContext) -> None:
210
+ """Called after snapshot restore."""
211
+ pass
212
+
213
+ # Health hooks
214
+ def on_pre_health_check(self, ctx: PluginContext) -> None:
215
+ """Called before health check."""
216
+ pass
217
+
218
+ def on_post_health_check(self, ctx: PluginContext) -> None:
219
+ """Called after health check."""
220
+ pass
221
+
222
+ def on_health_failure(self, ctx: PluginContext) -> None:
223
+ """Called when health check fails."""
224
+ pass
225
+
226
+ # Config hooks
227
+ def on_pre_config_load(self, ctx: PluginContext) -> None:
228
+ """Called before config is loaded."""
229
+ pass
230
+
231
+ def on_post_config_load(self, ctx: PluginContext) -> None:
232
+ """Called after config is loaded. Can modify ctx.modified_config."""
233
+ pass
234
+
235
+ def on_config_validate(self, ctx: PluginContext) -> None:
236
+ """Called to validate config. Add errors to ctx.errors if invalid."""
237
+ pass
238
+
239
+ # Cloud-init hooks
240
+ def on_cloud_init_customize(self, ctx: PluginContext) -> None:
241
+ """
242
+ Called to customize cloud-init.
243
+ Modify ctx.extra['cloud_init'] to add custom cloud-init content.
244
+ """
245
+ pass
246
+
247
+ # Export/Import hooks
248
+ def on_pre_export(self, ctx: PluginContext) -> None:
249
+ """Called before VM export."""
250
+ pass
251
+
252
+ def on_post_export(self, ctx: PluginContext) -> None:
253
+ """Called after VM export."""
254
+ pass
255
+
256
+ def on_pre_import(self, ctx: PluginContext) -> None:
257
+ """Called before VM import."""
258
+ pass
259
+
260
+ def on_post_import(self, ctx: PluginContext) -> None:
261
+ """Called after VM import."""
262
+ pass
263
+
264
+ # CLI hooks
265
+ def on_cli_command_register(self, ctx: PluginContext) -> None:
266
+ """
267
+ Called to register custom CLI commands.
268
+ Add commands to ctx.extra['commands'].
269
+ """
270
+ pass
271
+
272
+ # System hooks
273
+ def on_error(self, ctx: PluginContext) -> None:
274
+ """Called when an error occurs."""
275
+ pass
276
+
277
+ def on_startup(self, ctx: PluginContext) -> None:
278
+ """Called on CloneBox startup."""
279
+ pass
280
+
281
+ def on_shutdown(self, ctx: PluginContext) -> None:
282
+ """Called on CloneBox shutdown."""
283
+ pass
284
+
285
+ def handle_hook(self, hook: PluginHook, ctx: PluginContext) -> None:
286
+ """Dispatch hook to appropriate handler method."""
287
+ handler_map: Dict[PluginHook, Callable[[PluginContext], None]] = {
288
+ PluginHook.PRE_VM_CREATE: self.on_pre_vm_create,
289
+ PluginHook.POST_VM_CREATE: self.on_post_vm_create,
290
+ PluginHook.PRE_VM_START: self.on_pre_vm_start,
291
+ PluginHook.POST_VM_START: self.on_post_vm_start,
292
+ PluginHook.PRE_VM_STOP: self.on_pre_vm_stop,
293
+ PluginHook.POST_VM_STOP: self.on_post_vm_stop,
294
+ PluginHook.PRE_VM_DELETE: self.on_pre_vm_delete,
295
+ PluginHook.POST_VM_DELETE: self.on_post_vm_delete,
296
+ PluginHook.PRE_SNAPSHOT_CREATE: self.on_pre_snapshot_create,
297
+ PluginHook.POST_SNAPSHOT_CREATE: self.on_post_snapshot_create,
298
+ PluginHook.PRE_SNAPSHOT_RESTORE: self.on_pre_snapshot_restore,
299
+ PluginHook.POST_SNAPSHOT_RESTORE: self.on_post_snapshot_restore,
300
+ PluginHook.PRE_HEALTH_CHECK: self.on_pre_health_check,
301
+ PluginHook.POST_HEALTH_CHECK: self.on_post_health_check,
302
+ PluginHook.ON_HEALTH_FAILURE: self.on_health_failure,
303
+ PluginHook.PRE_CONFIG_LOAD: self.on_pre_config_load,
304
+ PluginHook.POST_CONFIG_LOAD: self.on_post_config_load,
305
+ PluginHook.CONFIG_VALIDATE: self.on_config_validate,
306
+ PluginHook.CLOUD_INIT_CUSTOMIZE: self.on_cloud_init_customize,
307
+ PluginHook.PRE_EXPORT: self.on_pre_export,
308
+ PluginHook.POST_EXPORT: self.on_post_export,
309
+ PluginHook.PRE_IMPORT: self.on_pre_import,
310
+ PluginHook.POST_IMPORT: self.on_post_import,
311
+ PluginHook.CLI_COMMAND_REGISTER: self.on_cli_command_register,
312
+ PluginHook.ON_ERROR: self.on_error,
313
+ PluginHook.ON_STARTUP: self.on_startup,
314
+ PluginHook.ON_SHUTDOWN: self.on_shutdown,
315
+ }
316
+
317
+ handler = handler_map.get(hook)
318
+ if handler:
319
+ handler(ctx)