kailash 0.8.3__py3-none-any.whl → 0.8.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.
- kailash/__init__.py +1 -7
- kailash/cli/__init__.py +11 -1
- kailash/cli/validation_audit.py +570 -0
- kailash/core/actors/supervisor.py +1 -1
- kailash/core/resilience/circuit_breaker.py +71 -1
- kailash/core/resilience/health_monitor.py +172 -0
- kailash/edge/compliance.py +33 -0
- kailash/edge/consistency.py +609 -0
- kailash/edge/coordination/__init__.py +30 -0
- kailash/edge/coordination/global_ordering.py +355 -0
- kailash/edge/coordination/leader_election.py +217 -0
- kailash/edge/coordination/partition_detector.py +296 -0
- kailash/edge/coordination/raft.py +485 -0
- kailash/edge/discovery.py +63 -1
- kailash/edge/migration/__init__.py +19 -0
- kailash/edge/migration/edge_migrator.py +832 -0
- kailash/edge/monitoring/__init__.py +21 -0
- kailash/edge/monitoring/edge_monitor.py +736 -0
- kailash/edge/prediction/__init__.py +10 -0
- kailash/edge/prediction/predictive_warmer.py +591 -0
- kailash/edge/resource/__init__.py +102 -0
- kailash/edge/resource/cloud_integration.py +796 -0
- kailash/edge/resource/cost_optimizer.py +949 -0
- kailash/edge/resource/docker_integration.py +919 -0
- kailash/edge/resource/kubernetes_integration.py +893 -0
- kailash/edge/resource/platform_integration.py +913 -0
- kailash/edge/resource/predictive_scaler.py +959 -0
- kailash/edge/resource/resource_analyzer.py +824 -0
- kailash/edge/resource/resource_pools.py +610 -0
- kailash/integrations/dataflow_edge.py +261 -0
- kailash/mcp_server/registry_integration.py +1 -1
- kailash/monitoring/__init__.py +18 -0
- kailash/monitoring/alerts.py +646 -0
- kailash/monitoring/metrics.py +677 -0
- kailash/nodes/__init__.py +2 -0
- kailash/nodes/ai/__init__.py +17 -0
- kailash/nodes/ai/a2a.py +1914 -43
- kailash/nodes/ai/a2a_backup.py +1807 -0
- kailash/nodes/ai/hybrid_search.py +972 -0
- kailash/nodes/ai/semantic_memory.py +558 -0
- kailash/nodes/ai/streaming_analytics.py +947 -0
- kailash/nodes/base.py +545 -0
- kailash/nodes/edge/__init__.py +36 -0
- kailash/nodes/edge/base.py +240 -0
- kailash/nodes/edge/cloud_node.py +710 -0
- kailash/nodes/edge/coordination.py +239 -0
- kailash/nodes/edge/docker_node.py +825 -0
- kailash/nodes/edge/edge_data.py +582 -0
- kailash/nodes/edge/edge_migration_node.py +392 -0
- kailash/nodes/edge/edge_monitoring_node.py +421 -0
- kailash/nodes/edge/edge_state.py +673 -0
- kailash/nodes/edge/edge_warming_node.py +393 -0
- kailash/nodes/edge/kubernetes_node.py +652 -0
- kailash/nodes/edge/platform_node.py +766 -0
- kailash/nodes/edge/resource_analyzer_node.py +378 -0
- kailash/nodes/edge/resource_optimizer_node.py +501 -0
- kailash/nodes/edge/resource_scaler_node.py +397 -0
- kailash/nodes/ports.py +676 -0
- kailash/runtime/local.py +344 -1
- kailash/runtime/validation/__init__.py +20 -0
- kailash/runtime/validation/connection_context.py +119 -0
- kailash/runtime/validation/enhanced_error_formatter.py +202 -0
- kailash/runtime/validation/error_categorizer.py +164 -0
- kailash/runtime/validation/metrics.py +380 -0
- kailash/runtime/validation/performance.py +615 -0
- kailash/runtime/validation/suggestion_engine.py +212 -0
- kailash/testing/fixtures.py +2 -2
- kailash/workflow/builder.py +234 -8
- kailash/workflow/contracts.py +418 -0
- kailash/workflow/edge_infrastructure.py +369 -0
- kailash/workflow/migration.py +3 -3
- kailash/workflow/type_inference.py +669 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/METADATA +44 -27
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/RECORD +78 -28
- kailash/nexus/__init__.py +0 -21
- kailash/nexus/cli/__init__.py +0 -5
- kailash/nexus/cli/__main__.py +0 -6
- kailash/nexus/cli/main.py +0 -176
- kailash/nexus/factory.py +0 -413
- kailash/nexus/gateway.py +0 -545
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/WHEEL +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/entry_points.txt +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,825 @@
|
|
1
|
+
"""Docker integration node for edge resource management."""
|
2
|
+
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
|
5
|
+
from kailash.edge.resource.docker_integration import (
|
6
|
+
ContainerSpec,
|
7
|
+
ContainerState,
|
8
|
+
DockerIntegration,
|
9
|
+
NetworkMode,
|
10
|
+
RestartPolicyType,
|
11
|
+
ServiceSpec,
|
12
|
+
)
|
13
|
+
from kailash.nodes.base import NodeParameter, register_node
|
14
|
+
from kailash.nodes.base_async import AsyncNode
|
15
|
+
|
16
|
+
|
17
|
+
@register_node()
|
18
|
+
class DockerNode(AsyncNode):
|
19
|
+
"""Node for Docker container and service management."""
|
20
|
+
|
21
|
+
def __init__(self, **kwargs):
|
22
|
+
super().__init__(**kwargs)
|
23
|
+
self.docker_integration: Optional[DockerIntegration] = None
|
24
|
+
|
25
|
+
@property
|
26
|
+
def input_parameters(self) -> Dict[str, NodeParameter]:
|
27
|
+
"""Define input parameters."""
|
28
|
+
return {
|
29
|
+
"operation": NodeParameter(
|
30
|
+
name="operation",
|
31
|
+
type=str,
|
32
|
+
required=True,
|
33
|
+
description="Operation to perform",
|
34
|
+
enum=[
|
35
|
+
"initialize",
|
36
|
+
"create_container",
|
37
|
+
"start_container",
|
38
|
+
"stop_container",
|
39
|
+
"remove_container",
|
40
|
+
"get_container_status",
|
41
|
+
"list_containers",
|
42
|
+
"create_service",
|
43
|
+
"update_service",
|
44
|
+
"scale_service",
|
45
|
+
"get_service_status",
|
46
|
+
"collect_metrics",
|
47
|
+
"get_system_info",
|
48
|
+
"start_monitoring",
|
49
|
+
"stop_monitoring",
|
50
|
+
],
|
51
|
+
),
|
52
|
+
"docker_host": NodeParameter(
|
53
|
+
name="docker_host",
|
54
|
+
type=str,
|
55
|
+
required=False,
|
56
|
+
description="Docker daemon socket URL",
|
57
|
+
),
|
58
|
+
"api_version": NodeParameter(
|
59
|
+
name="api_version",
|
60
|
+
type=str,
|
61
|
+
required=False,
|
62
|
+
description="Docker API version",
|
63
|
+
),
|
64
|
+
"timeout": NodeParameter(
|
65
|
+
name="timeout",
|
66
|
+
type=int,
|
67
|
+
required=False,
|
68
|
+
description="API timeout in seconds",
|
69
|
+
),
|
70
|
+
# Container operations
|
71
|
+
"container_name": NodeParameter(
|
72
|
+
name="container_name",
|
73
|
+
type=str,
|
74
|
+
required=False,
|
75
|
+
description="Container name",
|
76
|
+
),
|
77
|
+
"container_id": NodeParameter(
|
78
|
+
name="container_id",
|
79
|
+
type=str,
|
80
|
+
required=False,
|
81
|
+
description="Container ID",
|
82
|
+
),
|
83
|
+
"image": NodeParameter(
|
84
|
+
name="image", type=str, required=False, description="Docker image"
|
85
|
+
),
|
86
|
+
"command": NodeParameter(
|
87
|
+
name="command",
|
88
|
+
type=list,
|
89
|
+
required=False,
|
90
|
+
description="Container command",
|
91
|
+
),
|
92
|
+
"environment": NodeParameter(
|
93
|
+
name="environment",
|
94
|
+
type=dict,
|
95
|
+
required=False,
|
96
|
+
description="Environment variables",
|
97
|
+
),
|
98
|
+
"ports": NodeParameter(
|
99
|
+
name="ports",
|
100
|
+
type=dict,
|
101
|
+
required=False,
|
102
|
+
description="Port mappings (container_port -> host_port)",
|
103
|
+
),
|
104
|
+
"volumes": NodeParameter(
|
105
|
+
name="volumes",
|
106
|
+
type=dict,
|
107
|
+
required=False,
|
108
|
+
description="Volume mappings (host_path -> container_path)",
|
109
|
+
),
|
110
|
+
"restart_policy": NodeParameter(
|
111
|
+
name="restart_policy",
|
112
|
+
type=str,
|
113
|
+
required=False,
|
114
|
+
description="Container restart policy",
|
115
|
+
enum=["no", "always", "unless-stopped", "on-failure"],
|
116
|
+
),
|
117
|
+
"memory_limit": NodeParameter(
|
118
|
+
name="memory_limit",
|
119
|
+
type=str,
|
120
|
+
required=False,
|
121
|
+
description="Memory limit (e.g., '512m', '1g')",
|
122
|
+
),
|
123
|
+
"cpu_limit": NodeParameter(
|
124
|
+
name="cpu_limit",
|
125
|
+
type=float,
|
126
|
+
required=False,
|
127
|
+
description="CPU limit in cores",
|
128
|
+
),
|
129
|
+
"network_mode": NodeParameter(
|
130
|
+
name="network_mode",
|
131
|
+
type=str,
|
132
|
+
required=False,
|
133
|
+
description="Network mode",
|
134
|
+
enum=["bridge", "host", "none", "container", "custom"],
|
135
|
+
),
|
136
|
+
"labels": NodeParameter(
|
137
|
+
name="labels", type=dict, required=False, description="Container labels"
|
138
|
+
),
|
139
|
+
"edge_node": NodeParameter(
|
140
|
+
name="edge_node",
|
141
|
+
type=str,
|
142
|
+
required=False,
|
143
|
+
description="Target edge node for container placement",
|
144
|
+
),
|
145
|
+
"healthcheck": NodeParameter(
|
146
|
+
name="healthcheck",
|
147
|
+
type=dict,
|
148
|
+
required=False,
|
149
|
+
description="Container health check configuration",
|
150
|
+
),
|
151
|
+
# Service operations (Docker Swarm)
|
152
|
+
"service_name": NodeParameter(
|
153
|
+
name="service_name",
|
154
|
+
type=str,
|
155
|
+
required=False,
|
156
|
+
description="Service name",
|
157
|
+
),
|
158
|
+
"service_id": NodeParameter(
|
159
|
+
name="service_id", type=str, required=False, description="Service ID"
|
160
|
+
),
|
161
|
+
"replicas": NodeParameter(
|
162
|
+
name="replicas",
|
163
|
+
type=int,
|
164
|
+
required=False,
|
165
|
+
description="Number of service replicas",
|
166
|
+
),
|
167
|
+
"constraints": NodeParameter(
|
168
|
+
name="constraints",
|
169
|
+
type=list,
|
170
|
+
required=False,
|
171
|
+
description="Service placement constraints",
|
172
|
+
),
|
173
|
+
"placement_preferences": NodeParameter(
|
174
|
+
name="placement_preferences",
|
175
|
+
type=list,
|
176
|
+
required=False,
|
177
|
+
description="Service placement preferences",
|
178
|
+
),
|
179
|
+
"update_config": NodeParameter(
|
180
|
+
name="update_config",
|
181
|
+
type=dict,
|
182
|
+
required=False,
|
183
|
+
description="Service update configuration",
|
184
|
+
),
|
185
|
+
"rollback_config": NodeParameter(
|
186
|
+
name="rollback_config",
|
187
|
+
type=dict,
|
188
|
+
required=False,
|
189
|
+
description="Service rollback configuration",
|
190
|
+
),
|
191
|
+
# List operations
|
192
|
+
"all_containers": NodeParameter(
|
193
|
+
name="all_containers",
|
194
|
+
type=bool,
|
195
|
+
required=False,
|
196
|
+
description="Include stopped containers in list",
|
197
|
+
),
|
198
|
+
"filters": NodeParameter(
|
199
|
+
name="filters",
|
200
|
+
type=dict,
|
201
|
+
required=False,
|
202
|
+
description="Container filters",
|
203
|
+
),
|
204
|
+
# Control operations
|
205
|
+
"force": NodeParameter(
|
206
|
+
name="force", type=bool, required=False, description="Force operation"
|
207
|
+
),
|
208
|
+
"stop_timeout": NodeParameter(
|
209
|
+
name="stop_timeout",
|
210
|
+
type=int,
|
211
|
+
required=False,
|
212
|
+
description="Container stop timeout in seconds",
|
213
|
+
),
|
214
|
+
}
|
215
|
+
|
216
|
+
@property
|
217
|
+
def output_parameters(self) -> Dict[str, NodeParameter]:
|
218
|
+
"""Define output parameters."""
|
219
|
+
return {
|
220
|
+
"status": NodeParameter(
|
221
|
+
name="status", type=str, description="Operation status"
|
222
|
+
),
|
223
|
+
"result": NodeParameter(
|
224
|
+
name="result", type=dict, description="Operation result"
|
225
|
+
),
|
226
|
+
"containers": NodeParameter(
|
227
|
+
name="containers", type=list, description="List of containers"
|
228
|
+
),
|
229
|
+
"services": NodeParameter(
|
230
|
+
name="services", type=list, description="List of services"
|
231
|
+
),
|
232
|
+
"metrics": NodeParameter(
|
233
|
+
name="metrics", type=dict, description="Container metrics"
|
234
|
+
),
|
235
|
+
"system_info": NodeParameter(
|
236
|
+
name="system_info", type=dict, description="Docker system information"
|
237
|
+
),
|
238
|
+
"container_created": NodeParameter(
|
239
|
+
name="container_created",
|
240
|
+
type=bool,
|
241
|
+
description="Whether container was created",
|
242
|
+
),
|
243
|
+
"container_started": NodeParameter(
|
244
|
+
name="container_started",
|
245
|
+
type=bool,
|
246
|
+
description="Whether container was started",
|
247
|
+
),
|
248
|
+
"container_stopped": NodeParameter(
|
249
|
+
name="container_stopped",
|
250
|
+
type=bool,
|
251
|
+
description="Whether container was stopped",
|
252
|
+
),
|
253
|
+
"container_removed": NodeParameter(
|
254
|
+
name="container_removed",
|
255
|
+
type=bool,
|
256
|
+
description="Whether container was removed",
|
257
|
+
),
|
258
|
+
"service_created": NodeParameter(
|
259
|
+
name="service_created",
|
260
|
+
type=bool,
|
261
|
+
description="Whether service was created",
|
262
|
+
),
|
263
|
+
"service_updated": NodeParameter(
|
264
|
+
name="service_updated",
|
265
|
+
type=bool,
|
266
|
+
description="Whether service was updated",
|
267
|
+
),
|
268
|
+
"service_scaled": NodeParameter(
|
269
|
+
name="service_scaled",
|
270
|
+
type=bool,
|
271
|
+
description="Whether service was scaled",
|
272
|
+
),
|
273
|
+
"monitoring_started": NodeParameter(
|
274
|
+
name="monitoring_started",
|
275
|
+
type=bool,
|
276
|
+
description="Whether monitoring was started",
|
277
|
+
),
|
278
|
+
"monitoring_stopped": NodeParameter(
|
279
|
+
name="monitoring_stopped",
|
280
|
+
type=bool,
|
281
|
+
description="Whether monitoring was stopped",
|
282
|
+
),
|
283
|
+
}
|
284
|
+
|
285
|
+
def get_parameters(self) -> Dict[str, NodeParameter]:
|
286
|
+
"""Get all parameters for this node."""
|
287
|
+
return self.input_parameters
|
288
|
+
|
289
|
+
async def async_run(self, **kwargs) -> Dict[str, Any]:
|
290
|
+
"""Execute Docker operation.
|
291
|
+
|
292
|
+
Args:
|
293
|
+
**kwargs: Operation parameters
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
Operation result
|
297
|
+
"""
|
298
|
+
operation = kwargs.get("operation")
|
299
|
+
|
300
|
+
if not operation:
|
301
|
+
return {"status": "error", "error": "Operation is required"}
|
302
|
+
|
303
|
+
try:
|
304
|
+
if operation == "initialize":
|
305
|
+
return await self._initialize_docker(**kwargs)
|
306
|
+
elif operation == "create_container":
|
307
|
+
return await self._create_container(**kwargs)
|
308
|
+
elif operation == "start_container":
|
309
|
+
return await self._start_container(**kwargs)
|
310
|
+
elif operation == "stop_container":
|
311
|
+
return await self._stop_container(**kwargs)
|
312
|
+
elif operation == "remove_container":
|
313
|
+
return await self._remove_container(**kwargs)
|
314
|
+
elif operation == "get_container_status":
|
315
|
+
return await self._get_container_status(**kwargs)
|
316
|
+
elif operation == "list_containers":
|
317
|
+
return await self._list_containers(**kwargs)
|
318
|
+
elif operation == "create_service":
|
319
|
+
return await self._create_service(**kwargs)
|
320
|
+
elif operation == "update_service":
|
321
|
+
return await self._update_service(**kwargs)
|
322
|
+
elif operation == "scale_service":
|
323
|
+
return await self._scale_service(**kwargs)
|
324
|
+
elif operation == "get_service_status":
|
325
|
+
return await self._get_service_status(**kwargs)
|
326
|
+
elif operation == "collect_metrics":
|
327
|
+
return await self._collect_metrics(**kwargs)
|
328
|
+
elif operation == "get_system_info":
|
329
|
+
return await self._get_system_info(**kwargs)
|
330
|
+
elif operation == "start_monitoring":
|
331
|
+
return await self._start_monitoring(**kwargs)
|
332
|
+
elif operation == "stop_monitoring":
|
333
|
+
return await self._stop_monitoring(**kwargs)
|
334
|
+
else:
|
335
|
+
return {"status": "error", "error": f"Unknown operation: {operation}"}
|
336
|
+
|
337
|
+
except Exception as e:
|
338
|
+
return {"status": "error", "error": f"Docker operation failed: {str(e)}"}
|
339
|
+
|
340
|
+
async def _initialize_docker(self, **kwargs) -> Dict[str, Any]:
|
341
|
+
"""Initialize Docker integration."""
|
342
|
+
docker_host = kwargs.get("docker_host")
|
343
|
+
api_version = kwargs.get("api_version", "auto")
|
344
|
+
timeout = kwargs.get("timeout", 60)
|
345
|
+
|
346
|
+
try:
|
347
|
+
self.docker_integration = DockerIntegration(
|
348
|
+
docker_host=docker_host, api_version=api_version, timeout=timeout
|
349
|
+
)
|
350
|
+
|
351
|
+
await self.docker_integration.initialize()
|
352
|
+
|
353
|
+
return {
|
354
|
+
"status": "success",
|
355
|
+
"docker_initialized": True,
|
356
|
+
"result": {
|
357
|
+
"message": "Docker integration initialized successfully",
|
358
|
+
"docker_host": docker_host,
|
359
|
+
"api_version": api_version,
|
360
|
+
"swarm_enabled": self.docker_integration.swarm_enabled,
|
361
|
+
},
|
362
|
+
}
|
363
|
+
|
364
|
+
except Exception as e:
|
365
|
+
return {
|
366
|
+
"status": "error",
|
367
|
+
"docker_initialized": False,
|
368
|
+
"error": f"Failed to initialize Docker: {str(e)}",
|
369
|
+
}
|
370
|
+
|
371
|
+
async def _create_container(self, **kwargs) -> Dict[str, Any]:
|
372
|
+
"""Create Docker container."""
|
373
|
+
if not self.docker_integration:
|
374
|
+
await self._initialize_docker(**kwargs)
|
375
|
+
|
376
|
+
container_name = kwargs.get("container_name")
|
377
|
+
image = kwargs.get("image")
|
378
|
+
|
379
|
+
if not container_name or not image:
|
380
|
+
return {
|
381
|
+
"status": "error",
|
382
|
+
"container_created": False,
|
383
|
+
"error": "container_name and image are required",
|
384
|
+
}
|
385
|
+
|
386
|
+
try:
|
387
|
+
# Create container specification
|
388
|
+
container_spec = ContainerSpec(
|
389
|
+
name=container_name,
|
390
|
+
image=image,
|
391
|
+
command=kwargs.get("command"),
|
392
|
+
environment=kwargs.get("environment", {}),
|
393
|
+
ports=kwargs.get("ports", {}),
|
394
|
+
volumes=kwargs.get("volumes", {}),
|
395
|
+
restart_policy=RestartPolicyType(
|
396
|
+
kwargs.get("restart_policy", "unless-stopped")
|
397
|
+
),
|
398
|
+
memory_limit=kwargs.get("memory_limit"),
|
399
|
+
cpu_limit=kwargs.get("cpu_limit"),
|
400
|
+
network_mode=NetworkMode(kwargs.get("network_mode", "bridge")),
|
401
|
+
labels=kwargs.get("labels", {}),
|
402
|
+
edge_node=kwargs.get("edge_node"),
|
403
|
+
healthcheck=kwargs.get("healthcheck"),
|
404
|
+
)
|
405
|
+
|
406
|
+
# Create container
|
407
|
+
result = await self.docker_integration.create_container(container_spec)
|
408
|
+
|
409
|
+
return {
|
410
|
+
"status": result.get("status", "unknown"),
|
411
|
+
"container_created": result.get("status") == "created",
|
412
|
+
"result": result,
|
413
|
+
}
|
414
|
+
|
415
|
+
except Exception as e:
|
416
|
+
return {
|
417
|
+
"status": "error",
|
418
|
+
"container_created": False,
|
419
|
+
"error": f"Failed to create container: {str(e)}",
|
420
|
+
}
|
421
|
+
|
422
|
+
async def _start_container(self, **kwargs) -> Dict[str, Any]:
|
423
|
+
"""Start Docker container."""
|
424
|
+
if not self.docker_integration:
|
425
|
+
await self._initialize_docker(**kwargs)
|
426
|
+
|
427
|
+
container_id = kwargs.get("container_id") or kwargs.get("container_name")
|
428
|
+
|
429
|
+
if not container_id:
|
430
|
+
return {
|
431
|
+
"status": "error",
|
432
|
+
"container_started": False,
|
433
|
+
"error": "container_id or container_name is required",
|
434
|
+
}
|
435
|
+
|
436
|
+
try:
|
437
|
+
result = await self.docker_integration.start_container(container_id)
|
438
|
+
|
439
|
+
return {
|
440
|
+
"status": result.get("status", "unknown"),
|
441
|
+
"container_started": result.get("status") == "started",
|
442
|
+
"result": result,
|
443
|
+
}
|
444
|
+
|
445
|
+
except Exception as e:
|
446
|
+
return {
|
447
|
+
"status": "error",
|
448
|
+
"container_started": False,
|
449
|
+
"error": f"Failed to start container: {str(e)}",
|
450
|
+
}
|
451
|
+
|
452
|
+
async def _stop_container(self, **kwargs) -> Dict[str, Any]:
|
453
|
+
"""Stop Docker container."""
|
454
|
+
if not self.docker_integration:
|
455
|
+
await self._initialize_docker(**kwargs)
|
456
|
+
|
457
|
+
container_id = kwargs.get("container_id") or kwargs.get("container_name")
|
458
|
+
stop_timeout = kwargs.get("stop_timeout", 10)
|
459
|
+
|
460
|
+
if not container_id:
|
461
|
+
return {
|
462
|
+
"status": "error",
|
463
|
+
"container_stopped": False,
|
464
|
+
"error": "container_id or container_name is required",
|
465
|
+
}
|
466
|
+
|
467
|
+
try:
|
468
|
+
result = await self.docker_integration.stop_container(
|
469
|
+
container_id, stop_timeout
|
470
|
+
)
|
471
|
+
|
472
|
+
return {
|
473
|
+
"status": result.get("status", "unknown"),
|
474
|
+
"container_stopped": result.get("status") == "stopped",
|
475
|
+
"result": result,
|
476
|
+
}
|
477
|
+
|
478
|
+
except Exception as e:
|
479
|
+
return {
|
480
|
+
"status": "error",
|
481
|
+
"container_stopped": False,
|
482
|
+
"error": f"Failed to stop container: {str(e)}",
|
483
|
+
}
|
484
|
+
|
485
|
+
async def _remove_container(self, **kwargs) -> Dict[str, Any]:
|
486
|
+
"""Remove Docker container."""
|
487
|
+
if not self.docker_integration:
|
488
|
+
await self._initialize_docker(**kwargs)
|
489
|
+
|
490
|
+
container_id = kwargs.get("container_id") or kwargs.get("container_name")
|
491
|
+
force = kwargs.get("force", False)
|
492
|
+
|
493
|
+
if not container_id:
|
494
|
+
return {
|
495
|
+
"status": "error",
|
496
|
+
"container_removed": False,
|
497
|
+
"error": "container_id or container_name is required",
|
498
|
+
}
|
499
|
+
|
500
|
+
try:
|
501
|
+
result = await self.docker_integration.remove_container(container_id, force)
|
502
|
+
|
503
|
+
return {
|
504
|
+
"status": result.get("status", "unknown"),
|
505
|
+
"container_removed": result.get("status") == "removed",
|
506
|
+
"result": result,
|
507
|
+
}
|
508
|
+
|
509
|
+
except Exception as e:
|
510
|
+
return {
|
511
|
+
"status": "error",
|
512
|
+
"container_removed": False,
|
513
|
+
"error": f"Failed to remove container: {str(e)}",
|
514
|
+
}
|
515
|
+
|
516
|
+
async def _get_container_status(self, **kwargs) -> Dict[str, Any]:
|
517
|
+
"""Get Docker container status."""
|
518
|
+
if not self.docker_integration:
|
519
|
+
await self._initialize_docker(**kwargs)
|
520
|
+
|
521
|
+
container_id = kwargs.get("container_id") or kwargs.get("container_name")
|
522
|
+
|
523
|
+
if not container_id:
|
524
|
+
return {
|
525
|
+
"status": "error",
|
526
|
+
"error": "container_id or container_name is required",
|
527
|
+
}
|
528
|
+
|
529
|
+
try:
|
530
|
+
status = await self.docker_integration.get_container_status(container_id)
|
531
|
+
|
532
|
+
return {"status": "success", "result": status}
|
533
|
+
|
534
|
+
except Exception as e:
|
535
|
+
return {
|
536
|
+
"status": "error",
|
537
|
+
"error": f"Failed to get container status: {str(e)}",
|
538
|
+
}
|
539
|
+
|
540
|
+
async def _list_containers(self, **kwargs) -> Dict[str, Any]:
|
541
|
+
"""List Docker containers."""
|
542
|
+
if not self.docker_integration:
|
543
|
+
await self._initialize_docker(**kwargs)
|
544
|
+
|
545
|
+
all_containers = kwargs.get("all_containers", False)
|
546
|
+
filters = kwargs.get("filters", {})
|
547
|
+
|
548
|
+
try:
|
549
|
+
containers = await self.docker_integration.list_containers(
|
550
|
+
all_containers, filters
|
551
|
+
)
|
552
|
+
|
553
|
+
return {
|
554
|
+
"status": "success",
|
555
|
+
"containers": containers,
|
556
|
+
"result": {
|
557
|
+
"container_count": len(containers),
|
558
|
+
"containers": containers,
|
559
|
+
},
|
560
|
+
}
|
561
|
+
|
562
|
+
except Exception as e:
|
563
|
+
return {
|
564
|
+
"status": "error",
|
565
|
+
"containers": [],
|
566
|
+
"error": f"Failed to list containers: {str(e)}",
|
567
|
+
}
|
568
|
+
|
569
|
+
async def _create_service(self, **kwargs) -> Dict[str, Any]:
|
570
|
+
"""Create Docker Swarm service."""
|
571
|
+
if not self.docker_integration:
|
572
|
+
await self._initialize_docker(**kwargs)
|
573
|
+
|
574
|
+
service_name = kwargs.get("service_name")
|
575
|
+
image = kwargs.get("image")
|
576
|
+
|
577
|
+
if not service_name or not image:
|
578
|
+
return {
|
579
|
+
"status": "error",
|
580
|
+
"service_created": False,
|
581
|
+
"error": "service_name and image are required",
|
582
|
+
}
|
583
|
+
|
584
|
+
try:
|
585
|
+
# Create service specification
|
586
|
+
service_spec = ServiceSpec(
|
587
|
+
name=service_name,
|
588
|
+
image=image,
|
589
|
+
replicas=kwargs.get("replicas", 1),
|
590
|
+
command=kwargs.get("command"),
|
591
|
+
environment=kwargs.get("environment", {}),
|
592
|
+
ports=kwargs.get("ports", []),
|
593
|
+
volumes=kwargs.get("volumes", []),
|
594
|
+
constraints=kwargs.get("constraints", []),
|
595
|
+
placement_preferences=kwargs.get("placement_preferences", []),
|
596
|
+
restart_policy=kwargs.get("restart_policy"),
|
597
|
+
update_config=kwargs.get("update_config"),
|
598
|
+
rollback_config=kwargs.get("rollback_config"),
|
599
|
+
labels=kwargs.get("labels", {}),
|
600
|
+
edge_node=kwargs.get("edge_node"),
|
601
|
+
)
|
602
|
+
|
603
|
+
# Create service
|
604
|
+
result = await self.docker_integration.create_service(service_spec)
|
605
|
+
|
606
|
+
return {
|
607
|
+
"status": result.get("status", "unknown"),
|
608
|
+
"service_created": result.get("status") == "created",
|
609
|
+
"result": result,
|
610
|
+
}
|
611
|
+
|
612
|
+
except Exception as e:
|
613
|
+
return {
|
614
|
+
"status": "error",
|
615
|
+
"service_created": False,
|
616
|
+
"error": f"Failed to create service: {str(e)}",
|
617
|
+
}
|
618
|
+
|
619
|
+
async def _update_service(self, **kwargs) -> Dict[str, Any]:
|
620
|
+
"""Update Docker Swarm service."""
|
621
|
+
if not self.docker_integration:
|
622
|
+
await self._initialize_docker(**kwargs)
|
623
|
+
|
624
|
+
service_id = kwargs.get("service_id") or kwargs.get("service_name")
|
625
|
+
|
626
|
+
if not service_id:
|
627
|
+
return {
|
628
|
+
"status": "error",
|
629
|
+
"service_updated": False,
|
630
|
+
"error": "service_id or service_name is required",
|
631
|
+
}
|
632
|
+
|
633
|
+
try:
|
634
|
+
# Get current service spec and update it
|
635
|
+
# For simplicity, we'll create a new spec with updated values
|
636
|
+
service_spec = ServiceSpec(
|
637
|
+
name=kwargs.get("service_name", service_id),
|
638
|
+
image=kwargs.get("image", ""),
|
639
|
+
replicas=kwargs.get("replicas", 1),
|
640
|
+
command=kwargs.get("command"),
|
641
|
+
environment=kwargs.get("environment", {}),
|
642
|
+
labels=kwargs.get("labels", {}),
|
643
|
+
edge_node=kwargs.get("edge_node"),
|
644
|
+
)
|
645
|
+
|
646
|
+
result = await self.docker_integration.update_service(
|
647
|
+
service_id, service_spec
|
648
|
+
)
|
649
|
+
|
650
|
+
return {
|
651
|
+
"status": result.get("status", "unknown"),
|
652
|
+
"service_updated": result.get("status") == "updated",
|
653
|
+
"result": result,
|
654
|
+
}
|
655
|
+
|
656
|
+
except Exception as e:
|
657
|
+
return {
|
658
|
+
"status": "error",
|
659
|
+
"service_updated": False,
|
660
|
+
"error": f"Failed to update service: {str(e)}",
|
661
|
+
}
|
662
|
+
|
663
|
+
async def _scale_service(self, **kwargs) -> Dict[str, Any]:
|
664
|
+
"""Scale Docker Swarm service."""
|
665
|
+
if not self.docker_integration:
|
666
|
+
await self._initialize_docker(**kwargs)
|
667
|
+
|
668
|
+
service_id = kwargs.get("service_id") or kwargs.get("service_name")
|
669
|
+
replicas = kwargs.get("replicas")
|
670
|
+
|
671
|
+
if not service_id or replicas is None:
|
672
|
+
return {
|
673
|
+
"status": "error",
|
674
|
+
"service_scaled": False,
|
675
|
+
"error": "service_id (or service_name) and replicas are required",
|
676
|
+
}
|
677
|
+
|
678
|
+
try:
|
679
|
+
result = await self.docker_integration.scale_service(service_id, replicas)
|
680
|
+
|
681
|
+
return {
|
682
|
+
"status": result.get("status", "unknown"),
|
683
|
+
"service_scaled": result.get("status") == "scaled",
|
684
|
+
"result": result,
|
685
|
+
}
|
686
|
+
|
687
|
+
except Exception as e:
|
688
|
+
return {
|
689
|
+
"status": "error",
|
690
|
+
"service_scaled": False,
|
691
|
+
"error": f"Failed to scale service: {str(e)}",
|
692
|
+
}
|
693
|
+
|
694
|
+
async def _get_service_status(self, **kwargs) -> Dict[str, Any]:
|
695
|
+
"""Get Docker Swarm service status."""
|
696
|
+
if not self.docker_integration:
|
697
|
+
await self._initialize_docker(**kwargs)
|
698
|
+
|
699
|
+
service_id = kwargs.get("service_id") or kwargs.get("service_name")
|
700
|
+
|
701
|
+
if not service_id:
|
702
|
+
return {
|
703
|
+
"status": "error",
|
704
|
+
"error": "service_id or service_name is required",
|
705
|
+
}
|
706
|
+
|
707
|
+
try:
|
708
|
+
status = await self.docker_integration.get_service_status(service_id)
|
709
|
+
|
710
|
+
return {"status": "success", "result": status}
|
711
|
+
|
712
|
+
except Exception as e:
|
713
|
+
return {
|
714
|
+
"status": "error",
|
715
|
+
"error": f"Failed to get service status: {str(e)}",
|
716
|
+
}
|
717
|
+
|
718
|
+
async def _collect_metrics(self, **kwargs) -> Dict[str, Any]:
|
719
|
+
"""Collect container metrics."""
|
720
|
+
if not self.docker_integration:
|
721
|
+
await self._initialize_docker(**kwargs)
|
722
|
+
|
723
|
+
container_id = kwargs.get("container_id") or kwargs.get("container_name")
|
724
|
+
|
725
|
+
if not container_id:
|
726
|
+
return {
|
727
|
+
"status": "error",
|
728
|
+
"error": "container_id or container_name is required",
|
729
|
+
}
|
730
|
+
|
731
|
+
try:
|
732
|
+
metrics = await self.docker_integration.collect_container_metrics(
|
733
|
+
container_id
|
734
|
+
)
|
735
|
+
|
736
|
+
if metrics:
|
737
|
+
return {
|
738
|
+
"status": "success",
|
739
|
+
"metrics": metrics.to_dict(),
|
740
|
+
"result": metrics.to_dict(),
|
741
|
+
}
|
742
|
+
else:
|
743
|
+
return {
|
744
|
+
"status": "error",
|
745
|
+
"metrics": {},
|
746
|
+
"error": "Failed to collect metrics",
|
747
|
+
}
|
748
|
+
|
749
|
+
except Exception as e:
|
750
|
+
return {
|
751
|
+
"status": "error",
|
752
|
+
"metrics": {},
|
753
|
+
"error": f"Failed to collect metrics: {str(e)}",
|
754
|
+
}
|
755
|
+
|
756
|
+
async def _get_system_info(self, **kwargs) -> Dict[str, Any]:
|
757
|
+
"""Get Docker system information."""
|
758
|
+
if not self.docker_integration:
|
759
|
+
await self._initialize_docker(**kwargs)
|
760
|
+
|
761
|
+
try:
|
762
|
+
system_info = await self.docker_integration.get_system_info()
|
763
|
+
|
764
|
+
return {
|
765
|
+
"status": "success",
|
766
|
+
"system_info": system_info,
|
767
|
+
"result": system_info,
|
768
|
+
}
|
769
|
+
|
770
|
+
except Exception as e:
|
771
|
+
return {
|
772
|
+
"status": "error",
|
773
|
+
"system_info": {},
|
774
|
+
"error": f"Failed to get system info: {str(e)}",
|
775
|
+
}
|
776
|
+
|
777
|
+
async def _start_monitoring(self, **kwargs) -> Dict[str, Any]:
|
778
|
+
"""Start Docker monitoring."""
|
779
|
+
if not self.docker_integration:
|
780
|
+
await self._initialize_docker(**kwargs)
|
781
|
+
|
782
|
+
try:
|
783
|
+
await self.docker_integration.start_monitoring()
|
784
|
+
|
785
|
+
return {
|
786
|
+
"status": "success",
|
787
|
+
"monitoring_started": True,
|
788
|
+
"result": {
|
789
|
+
"message": "Docker monitoring started",
|
790
|
+
"monitoring_interval": self.docker_integration.monitoring_interval,
|
791
|
+
"metrics_interval": self.docker_integration.metrics_interval,
|
792
|
+
},
|
793
|
+
}
|
794
|
+
|
795
|
+
except Exception as e:
|
796
|
+
return {
|
797
|
+
"status": "error",
|
798
|
+
"monitoring_started": False,
|
799
|
+
"error": f"Failed to start monitoring: {str(e)}",
|
800
|
+
}
|
801
|
+
|
802
|
+
async def _stop_monitoring(self, **kwargs) -> Dict[str, Any]:
|
803
|
+
"""Stop Docker monitoring."""
|
804
|
+
if not self.docker_integration:
|
805
|
+
return {
|
806
|
+
"status": "error",
|
807
|
+
"monitoring_stopped": False,
|
808
|
+
"error": "Docker integration not initialized",
|
809
|
+
}
|
810
|
+
|
811
|
+
try:
|
812
|
+
await self.docker_integration.stop_monitoring()
|
813
|
+
|
814
|
+
return {
|
815
|
+
"status": "success",
|
816
|
+
"monitoring_stopped": True,
|
817
|
+
"result": {"message": "Docker monitoring stopped"},
|
818
|
+
}
|
819
|
+
|
820
|
+
except Exception as e:
|
821
|
+
return {
|
822
|
+
"status": "error",
|
823
|
+
"monitoring_stopped": False,
|
824
|
+
"error": f"Failed to stop monitoring: {str(e)}",
|
825
|
+
}
|