kailash 0.8.4__py3-none-any.whl → 0.8.6__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 (99) hide show
  1. kailash/__init__.py +5 -11
  2. kailash/channels/__init__.py +2 -1
  3. kailash/channels/mcp_channel.py +23 -4
  4. kailash/cli/__init__.py +11 -1
  5. kailash/cli/validate_imports.py +202 -0
  6. kailash/cli/validation_audit.py +570 -0
  7. kailash/core/actors/supervisor.py +1 -1
  8. kailash/core/resilience/bulkhead.py +15 -5
  9. kailash/core/resilience/circuit_breaker.py +74 -1
  10. kailash/core/resilience/health_monitor.py +433 -33
  11. kailash/edge/compliance.py +33 -0
  12. kailash/edge/consistency.py +609 -0
  13. kailash/edge/coordination/__init__.py +30 -0
  14. kailash/edge/coordination/global_ordering.py +355 -0
  15. kailash/edge/coordination/leader_election.py +217 -0
  16. kailash/edge/coordination/partition_detector.py +296 -0
  17. kailash/edge/coordination/raft.py +485 -0
  18. kailash/edge/discovery.py +63 -1
  19. kailash/edge/migration/__init__.py +19 -0
  20. kailash/edge/migration/edge_migration_service.py +384 -0
  21. kailash/edge/migration/edge_migrator.py +832 -0
  22. kailash/edge/monitoring/__init__.py +21 -0
  23. kailash/edge/monitoring/edge_monitor.py +736 -0
  24. kailash/edge/prediction/__init__.py +10 -0
  25. kailash/edge/prediction/predictive_warmer.py +591 -0
  26. kailash/edge/resource/__init__.py +102 -0
  27. kailash/edge/resource/cloud_integration.py +796 -0
  28. kailash/edge/resource/cost_optimizer.py +949 -0
  29. kailash/edge/resource/docker_integration.py +919 -0
  30. kailash/edge/resource/kubernetes_integration.py +893 -0
  31. kailash/edge/resource/platform_integration.py +913 -0
  32. kailash/edge/resource/predictive_scaler.py +959 -0
  33. kailash/edge/resource/resource_analyzer.py +824 -0
  34. kailash/edge/resource/resource_pools.py +610 -0
  35. kailash/integrations/dataflow_edge.py +261 -0
  36. kailash/mcp_server/registry_integration.py +1 -1
  37. kailash/mcp_server/server.py +351 -8
  38. kailash/mcp_server/transports.py +305 -0
  39. kailash/middleware/gateway/event_store.py +1 -0
  40. kailash/monitoring/__init__.py +18 -0
  41. kailash/monitoring/alerts.py +646 -0
  42. kailash/monitoring/metrics.py +677 -0
  43. kailash/nodes/__init__.py +2 -0
  44. kailash/nodes/ai/semantic_memory.py +2 -2
  45. kailash/nodes/base.py +622 -1
  46. kailash/nodes/code/python.py +44 -3
  47. kailash/nodes/data/async_sql.py +42 -20
  48. kailash/nodes/edge/__init__.py +36 -0
  49. kailash/nodes/edge/base.py +240 -0
  50. kailash/nodes/edge/cloud_node.py +710 -0
  51. kailash/nodes/edge/coordination.py +239 -0
  52. kailash/nodes/edge/docker_node.py +825 -0
  53. kailash/nodes/edge/edge_data.py +582 -0
  54. kailash/nodes/edge/edge_migration_node.py +396 -0
  55. kailash/nodes/edge/edge_monitoring_node.py +421 -0
  56. kailash/nodes/edge/edge_state.py +673 -0
  57. kailash/nodes/edge/edge_warming_node.py +393 -0
  58. kailash/nodes/edge/kubernetes_node.py +652 -0
  59. kailash/nodes/edge/platform_node.py +766 -0
  60. kailash/nodes/edge/resource_analyzer_node.py +378 -0
  61. kailash/nodes/edge/resource_optimizer_node.py +501 -0
  62. kailash/nodes/edge/resource_scaler_node.py +397 -0
  63. kailash/nodes/governance.py +410 -0
  64. kailash/nodes/ports.py +676 -0
  65. kailash/nodes/rag/registry.py +1 -1
  66. kailash/nodes/transaction/distributed_transaction_manager.py +48 -1
  67. kailash/nodes/transaction/saga_state_storage.py +2 -1
  68. kailash/nodes/validation.py +8 -8
  69. kailash/runtime/local.py +374 -1
  70. kailash/runtime/validation/__init__.py +12 -0
  71. kailash/runtime/validation/connection_context.py +119 -0
  72. kailash/runtime/validation/enhanced_error_formatter.py +202 -0
  73. kailash/runtime/validation/error_categorizer.py +164 -0
  74. kailash/runtime/validation/import_validator.py +446 -0
  75. kailash/runtime/validation/metrics.py +380 -0
  76. kailash/runtime/validation/performance.py +615 -0
  77. kailash/runtime/validation/suggestion_engine.py +212 -0
  78. kailash/testing/fixtures.py +2 -2
  79. kailash/utils/data_paths.py +74 -0
  80. kailash/workflow/builder.py +413 -8
  81. kailash/workflow/contracts.py +418 -0
  82. kailash/workflow/edge_infrastructure.py +369 -0
  83. kailash/workflow/mermaid_visualizer.py +3 -1
  84. kailash/workflow/migration.py +3 -3
  85. kailash/workflow/templates.py +6 -6
  86. kailash/workflow/type_inference.py +669 -0
  87. kailash/workflow/validation.py +134 -3
  88. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/METADATA +52 -34
  89. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/RECORD +93 -42
  90. kailash/nexus/__init__.py +0 -21
  91. kailash/nexus/cli/__init__.py +0 -5
  92. kailash/nexus/cli/__main__.py +0 -6
  93. kailash/nexus/cli/main.py +0 -176
  94. kailash/nexus/factory.py +0 -413
  95. kailash/nexus/gateway.py +0 -545
  96. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/WHEEL +0 -0
  97. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/entry_points.txt +0 -0
  98. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/licenses/LICENSE +0 -0
  99. {kailash-0.8.4.dist-info → kailash-0.8.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,396 @@
1
+ """Edge migration node for live workload migration between edge nodes.
2
+
3
+ This node integrates edge migration capabilities into workflows,
4
+ enabling zero-downtime migration of workloads and data.
5
+ """
6
+
7
+ import asyncio
8
+ from datetime import datetime
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from kailash.edge.migration.edge_migration_service import EdgeMigrationService
12
+ from kailash.edge.migration.edge_migrator import (
13
+ EdgeMigrator,
14
+ MigrationPhase,
15
+ MigrationPlan,
16
+ MigrationProgress,
17
+ MigrationStrategy,
18
+ )
19
+ from kailash.nodes.base import NodeParameter, register_node
20
+ from kailash.nodes.base_async import AsyncNode
21
+
22
+
23
+ @register_node()
24
+ class EdgeMigrationNode(AsyncNode):
25
+ """Node for edge migration operations.
26
+
27
+ This node provides capabilities for planning and executing live migrations
28
+ of workloads between edge nodes with minimal downtime.
29
+
30
+ Example:
31
+ >>> # Plan a migration
32
+ >>> result = await migration_node.execute_async(
33
+ ... operation="plan_migration",
34
+ ... source_edge="edge-west-1",
35
+ ... target_edge="edge-east-1",
36
+ ... workloads=["api-service", "cache-layer"],
37
+ ... strategy="live"
38
+ ... )
39
+
40
+ >>> # Execute the migration
41
+ >>> result = await migration_node.execute_async(
42
+ ... operation="execute_migration",
43
+ ... migration_id=result["plan"]["migration_id"]
44
+ ... )
45
+
46
+ >>> # Check progress
47
+ >>> result = await migration_node.execute_async(
48
+ ... operation="get_progress",
49
+ ... migration_id="migration_123"
50
+ ... )
51
+
52
+ >>> # Rollback if needed
53
+ >>> result = await migration_node.execute_async(
54
+ ... operation="rollback_migration",
55
+ ... migration_id="migration_123"
56
+ ... )
57
+ """
58
+
59
+ def __init__(self, **kwargs):
60
+ """Initialize edge migration node."""
61
+ super().__init__(**kwargs)
62
+
63
+ # Extract node-specific configuration
64
+ self.node_config = {
65
+ "checkpoint_interval": kwargs.get("checkpoint_interval", 60),
66
+ "sync_batch_size": kwargs.get("sync_batch_size", 1000),
67
+ "bandwidth_limit_mbps": kwargs.get("bandwidth_limit_mbps"),
68
+ "enable_compression": kwargs.get("enable_compression", True),
69
+ }
70
+
71
+ # Get reference to shared migration service
72
+ self.migration_service = EdgeMigrationService(self.node_config)
73
+
74
+ # Get migrator instance from shared service with node-specific config
75
+ self.node_id = f"edge_migration_node_{id(self)}"
76
+ self.migrator = self.migration_service.get_migrator_for_node(
77
+ self.node_id, self.node_config
78
+ )
79
+
80
+ self._migrator_started = False
81
+
82
+ @property
83
+ def input_parameters(self) -> Dict[str, NodeParameter]:
84
+ """Define input parameters."""
85
+ return {
86
+ "operation": NodeParameter(
87
+ name="operation",
88
+ type=str,
89
+ required=True,
90
+ description="Operation to perform (plan_migration, execute_migration, get_progress, pause_migration, resume_migration, rollback_migration, get_active_migrations, get_history, get_metrics, start_migrator, stop_migrator)",
91
+ ),
92
+ # For plan_migration
93
+ "source_edge": NodeParameter(
94
+ name="source_edge",
95
+ type=str,
96
+ required=False,
97
+ description="Source edge node",
98
+ ),
99
+ "target_edge": NodeParameter(
100
+ name="target_edge",
101
+ type=str,
102
+ required=False,
103
+ description="Target edge node",
104
+ ),
105
+ "workloads": NodeParameter(
106
+ name="workloads",
107
+ type=list,
108
+ required=False,
109
+ description="List of workloads to migrate",
110
+ ),
111
+ "strategy": NodeParameter(
112
+ name="strategy",
113
+ type=str,
114
+ required=False,
115
+ default="live",
116
+ description="Migration strategy (live, staged, bulk, incremental, emergency)",
117
+ ),
118
+ "constraints": NodeParameter(
119
+ name="constraints",
120
+ type=dict,
121
+ required=False,
122
+ default={},
123
+ description="Migration constraints (time_window, bandwidth, etc.)",
124
+ ),
125
+ "priority": NodeParameter(
126
+ name="priority",
127
+ type=int,
128
+ required=False,
129
+ default=5,
130
+ description="Migration priority (1-10)",
131
+ ),
132
+ # For other operations
133
+ "migration_id": NodeParameter(
134
+ name="migration_id",
135
+ type=str,
136
+ required=False,
137
+ description="Migration identifier",
138
+ ),
139
+ "checkpoint_id": NodeParameter(
140
+ name="checkpoint_id",
141
+ type=str,
142
+ required=False,
143
+ description="Checkpoint identifier for rollback",
144
+ ),
145
+ # Configuration
146
+ "checkpoint_interval": NodeParameter(
147
+ name="checkpoint_interval",
148
+ type=int,
149
+ required=False,
150
+ default=60,
151
+ description="Checkpoint creation interval (seconds)",
152
+ ),
153
+ "sync_batch_size": NodeParameter(
154
+ name="sync_batch_size",
155
+ type=int,
156
+ required=False,
157
+ default=1000,
158
+ description="Records per sync batch",
159
+ ),
160
+ "bandwidth_limit_mbps": NodeParameter(
161
+ name="bandwidth_limit_mbps",
162
+ type=float,
163
+ required=False,
164
+ description="Bandwidth limit in Mbps",
165
+ ),
166
+ "enable_compression": NodeParameter(
167
+ name="enable_compression",
168
+ type=bool,
169
+ required=False,
170
+ default=True,
171
+ description="Enable data compression",
172
+ ),
173
+ }
174
+
175
+ @property
176
+ def output_parameters(self) -> Dict[str, NodeParameter]:
177
+ """Define output parameters."""
178
+ return {
179
+ "status": NodeParameter(
180
+ name="status", type=str, description="Operation status"
181
+ ),
182
+ "plan": NodeParameter(
183
+ name="plan",
184
+ type=dict,
185
+ required=False,
186
+ description="Migration plan details",
187
+ ),
188
+ "progress": NodeParameter(
189
+ name="progress",
190
+ type=dict,
191
+ required=False,
192
+ description="Migration progress information",
193
+ ),
194
+ "result": NodeParameter(
195
+ name="result", type=dict, required=False, description="Operation result"
196
+ ),
197
+ "migrations": NodeParameter(
198
+ name="migrations",
199
+ type=list,
200
+ required=False,
201
+ description="List of migrations",
202
+ ),
203
+ "metrics": NodeParameter(
204
+ name="metrics",
205
+ type=dict,
206
+ required=False,
207
+ description="Migration metrics",
208
+ ),
209
+ "migrator_active": NodeParameter(
210
+ name="migrator_active",
211
+ type=bool,
212
+ required=False,
213
+ description="Whether migrator service is active",
214
+ ),
215
+ }
216
+
217
+ def get_parameters(self) -> Dict[str, NodeParameter]:
218
+ """Get all node parameters for compatibility."""
219
+ return self.input_parameters
220
+
221
+ async def async_run(self, **kwargs) -> Dict[str, Any]:
222
+ """Execute migration operation."""
223
+ operation = kwargs["operation"]
224
+
225
+ try:
226
+ if operation == "plan_migration":
227
+ return await self._plan_migration(kwargs)
228
+ elif operation == "execute_migration":
229
+ return await self._execute_migration(kwargs)
230
+ elif operation == "get_progress":
231
+ return await self._get_progress(kwargs)
232
+ elif operation == "pause_migration":
233
+ return await self._pause_migration(kwargs)
234
+ elif operation == "resume_migration":
235
+ return await self._resume_migration(kwargs)
236
+ elif operation == "rollback_migration":
237
+ return await self._rollback_migration(kwargs)
238
+ elif operation == "get_active_migrations":
239
+ return await self._get_active_migrations()
240
+ elif operation == "get_history":
241
+ return await self._get_history()
242
+ elif operation == "get_metrics":
243
+ return await self._get_metrics()
244
+ elif operation == "start_migrator":
245
+ return await self._start_migrator()
246
+ elif operation == "stop_migrator":
247
+ return await self._stop_migrator()
248
+ else:
249
+ raise ValueError(f"Unknown operation: {operation}")
250
+
251
+ except Exception as e:
252
+ self.logger.error(f"Edge migration operation failed: {str(e)}")
253
+ return {"status": "error", "error": str(e)}
254
+
255
+ async def _plan_migration(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
256
+ """Plan a migration."""
257
+ # Parse strategy
258
+ strategy_name = kwargs.get("strategy", "live")
259
+ try:
260
+ strategy = MigrationStrategy(strategy_name)
261
+ except ValueError:
262
+ strategy = MigrationStrategy.LIVE
263
+
264
+ # Create plan
265
+ plan = await self.migrator.plan_migration(
266
+ source_edge=kwargs.get("source_edge", "unknown"),
267
+ target_edge=kwargs.get("target_edge", "unknown"),
268
+ workloads=kwargs.get("workloads", []),
269
+ strategy=strategy,
270
+ constraints=kwargs.get("constraints", {}),
271
+ )
272
+
273
+ # Set priority
274
+ plan.priority = kwargs.get("priority", 5)
275
+
276
+ return {
277
+ "status": "success",
278
+ "plan": plan.to_dict(),
279
+ "estimated_duration": self._estimate_duration(plan),
280
+ }
281
+
282
+ async def _execute_migration(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
283
+ """Execute a migration."""
284
+ migration_id = kwargs.get("migration_id")
285
+ if not migration_id:
286
+ raise ValueError("migration_id is required")
287
+
288
+ # Start execution asynchronously
289
+ result = await self.migrator.execute_migration(migration_id)
290
+
291
+ return {"status": "success", "result": result}
292
+
293
+ async def _get_progress(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
294
+ """Get migration progress."""
295
+ migration_id = kwargs.get("migration_id")
296
+ if not migration_id:
297
+ raise ValueError("migration_id is required")
298
+
299
+ progress = await self.migrator.get_progress(migration_id)
300
+
301
+ return {"status": "success", "progress": progress.to_dict()}
302
+
303
+ async def _pause_migration(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
304
+ """Pause a migration."""
305
+ migration_id = kwargs.get("migration_id")
306
+ if not migration_id:
307
+ raise ValueError("migration_id is required")
308
+
309
+ result = await self.migrator.pause_migration(migration_id)
310
+
311
+ return {"status": "success", "result": result}
312
+
313
+ async def _resume_migration(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
314
+ """Resume a migration."""
315
+ migration_id = kwargs.get("migration_id")
316
+ if not migration_id:
317
+ raise ValueError("migration_id is required")
318
+
319
+ result = await self.migrator.resume_migration(migration_id)
320
+
321
+ return {"status": "success", "result": result}
322
+
323
+ async def _rollback_migration(self, kwargs: Dict[str, Any]) -> Dict[str, Any]:
324
+ """Rollback a migration."""
325
+ migration_id = kwargs.get("migration_id")
326
+ if not migration_id:
327
+ raise ValueError("migration_id is required")
328
+
329
+ checkpoint_id = kwargs.get("checkpoint_id")
330
+
331
+ result = await self.migrator.rollback_migration(migration_id, checkpoint_id)
332
+
333
+ return {"status": "success", "result": result}
334
+
335
+ async def _get_active_migrations(self) -> Dict[str, Any]:
336
+ """Get active migrations."""
337
+ migrations = self.migrator.get_active_migrations()
338
+
339
+ return {
340
+ "status": "success",
341
+ "migrations": [m.to_dict() for m in migrations],
342
+ "count": len(migrations),
343
+ }
344
+
345
+ async def _get_history(self) -> Dict[str, Any]:
346
+ """Get migration history."""
347
+ history = self.migrator.get_migration_history()
348
+
349
+ return {"status": "success", "migrations": history, "count": len(history)}
350
+
351
+ async def _get_metrics(self) -> Dict[str, Any]:
352
+ """Get migration metrics."""
353
+ metrics = self.migrator.get_migration_metrics()
354
+
355
+ return {"status": "success", "metrics": metrics}
356
+
357
+ async def _start_migrator(self) -> Dict[str, Any]:
358
+ """Start migrator service."""
359
+ if not self._migrator_started:
360
+ await self.migrator.start()
361
+ self._migrator_started = True
362
+
363
+ return {"status": "success", "migrator_active": True}
364
+
365
+ async def _stop_migrator(self) -> Dict[str, Any]:
366
+ """Stop migrator service."""
367
+ if self._migrator_started:
368
+ await self.migrator.stop()
369
+ self._migrator_started = False
370
+
371
+ return {"status": "success", "migrator_active": False}
372
+
373
+ def _estimate_duration(self, plan: MigrationPlan) -> float:
374
+ """Estimate migration duration in seconds."""
375
+ # Simple estimation based on data size and strategy
376
+ base_time = plan.data_size_estimate / (100 * 1024 * 1024) # 100MB/s baseline
377
+
378
+ strategy_multipliers = {
379
+ MigrationStrategy.LIVE: 1.5, # Extra time for live sync
380
+ MigrationStrategy.STAGED: 1.2, # Controlled phases
381
+ MigrationStrategy.BULK: 1.0, # Fastest
382
+ MigrationStrategy.INCREMENTAL: 2.0, # Multiple passes
383
+ MigrationStrategy.EMERGENCY: 0.8, # Fast but risky
384
+ }
385
+
386
+ multiplier = strategy_multipliers.get(plan.strategy, 1.0)
387
+
388
+ # Add overhead for validation and cleanup
389
+ overhead = 60 * len(plan.workloads) # 1 minute per workload
390
+
391
+ return base_time * multiplier + overhead
392
+
393
+ async def cleanup(self):
394
+ """Clean up resources."""
395
+ if self._migrator_started:
396
+ await self.migrator.stop()