manta-node 0.5b0__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 (43) hide show
  1. manta_node/__init__.py +5 -0
  2. manta_node/__main__.py +57 -0
  3. manta_node/cli/__init__.py +6 -0
  4. manta_node/cli/commands/__init__.py +21 -0
  5. manta_node/cli/commands/cluster.py +419 -0
  6. manta_node/cli/commands/config.py +490 -0
  7. manta_node/cli/commands/logs.py +168 -0
  8. manta_node/cli/commands/start.py +459 -0
  9. manta_node/cli/commands/status.py +204 -0
  10. manta_node/cli/commands/stop.py +253 -0
  11. manta_node/cli/config_manager.py +139 -0
  12. manta_node/cli/main.py +133 -0
  13. manta_node/cli/version.py +106 -0
  14. manta_node/domain/__init__.py +8 -0
  15. manta_node/domain/task_lifecycle.py +90 -0
  16. manta_node/infrastructure/__init__.py +13 -0
  17. manta_node/infrastructure/config/__init__.py +31 -0
  18. manta_node/infrastructure/config/node_config_manager.py +918 -0
  19. manta_node/infrastructure/container/__init__.py +11 -0
  20. manta_node/infrastructure/container/docker_adapter.py +253 -0
  21. manta_node/infrastructure/container/image_executor.py +222 -0
  22. manta_node/infrastructure/container/manager.py +549 -0
  23. manta_node/infrastructure/filesystem/__init__.py +7 -0
  24. manta_node/infrastructure/filesystem/dataset_manager.py +469 -0
  25. manta_node/infrastructure/grpc/__init__.py +11 -0
  26. manta_node/infrastructure/grpc/client.py +373 -0
  27. manta_node/infrastructure/grpc/local_servicer.py +151 -0
  28. manta_node/infrastructure/grpc/world_servicer.py +284 -0
  29. manta_node/infrastructure/metrics/__init__.py +10 -0
  30. manta_node/infrastructure/metrics/collector.py +94 -0
  31. manta_node/infrastructure/metrics/metrics_collector.py +351 -0
  32. manta_node/infrastructure/mqtt/__init__.py +7 -0
  33. manta_node/infrastructure/mqtt/command_handler.py +450 -0
  34. manta_node/node_orchestrator.py +462 -0
  35. manta_node/task_manager.py +677 -0
  36. manta_node/tasks.py +273 -0
  37. manta_node/utils.py +52 -0
  38. manta_node-0.5b0.dist-info/METADATA +794 -0
  39. manta_node-0.5b0.dist-info/RECORD +43 -0
  40. manta_node-0.5b0.dist-info/WHEEL +5 -0
  41. manta_node-0.5b0.dist-info/entry_points.txt +2 -0
  42. manta_node-0.5b0.dist-info/licenses/LICENSE +683 -0
  43. manta_node-0.5b0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,351 @@
1
+ import asyncio
2
+ import platform
3
+ import time
4
+ from abc import ABC, abstractmethod
5
+ from datetime import datetime, timezone
6
+ from logging import getLogger
7
+ from typing import Optional
8
+
9
+ import psutil
10
+
11
+ from manta_common.build.common.informations import (
12
+ AdditionalMetrics,
13
+ CpuMetrics,
14
+ DiskUsage,
15
+ GpuDeviceList,
16
+ MemoryMetrics,
17
+ MetricsSnapshot,
18
+ NetworkUsage,
19
+ PlatformInfo,
20
+ )
21
+ from manta_common.traces import Tracer
22
+
23
+ PSUTIL_AVAILABLE = True
24
+
25
+
26
+ class MetricsCollectorBase(ABC):
27
+ """
28
+ Abstract base class for metrics collection.
29
+
30
+ This class defines the interface for metrics collectors that gather
31
+ system metrics like CPU, memory, and other hardware usage.
32
+
33
+ Different implementations can be created for specific hardware platforms
34
+ (Linux, Jetson, Mac, etc.) by extending this class.
35
+
36
+ Parameters
37
+ ----------
38
+
39
+ The ID of the node where metrics are being collected
40
+ collection_interval : float
41
+ Time in seconds between metrics collection (default: 30.0)
42
+ """
43
+
44
+ def __init__(self, collection_interval: float = 30.0):
45
+ self.collection_interval = collection_interval
46
+ self.tracer = Tracer(getLogger(__name__), None)
47
+ self._latest_metrics: Optional[MetricsSnapshot] = None
48
+ self._running = False
49
+ self._collection_task: Optional[asyncio.Task] = None
50
+ self._lock = asyncio.Lock()
51
+
52
+ @abstractmethod
53
+ async def collect_cpu_metrics(self) -> CpuMetrics:
54
+ """
55
+ Collect CPU usage metrics.
56
+
57
+ Returns
58
+ -------
59
+ CpuMetrics
60
+ Protobuf message with CPU metrics
61
+ """
62
+ pass
63
+
64
+ @abstractmethod
65
+ async def collect_memory_metrics(self) -> MemoryMetrics:
66
+ """
67
+ Collect memory usage metrics.
68
+
69
+ Returns
70
+ -------
71
+ MemoryMetrics
72
+ Protobuf message with memory metrics
73
+ """
74
+ pass
75
+
76
+ @abstractmethod
77
+ async def collect_gpu_metrics(self) -> GpuDeviceList:
78
+ """
79
+ Collect GPU usage metrics if available.
80
+
81
+ Returns
82
+ -------
83
+ GpuDeviceList
84
+ Protobuf message with GPU metrics, or empty if no GPU or metrics unavailable
85
+ """
86
+ pass
87
+
88
+ @abstractmethod
89
+ async def collect_additional_metrics(self) -> AdditionalMetrics:
90
+ """
91
+ Collect disk and network metrics.
92
+
93
+ Returns
94
+ -------
95
+ AdditionalMetrics
96
+ Protobuf message with disk and network metrics
97
+ """
98
+ pass
99
+
100
+ @classmethod
101
+ def get_platform_info(cls) -> PlatformInfo:
102
+ """
103
+ Get platform information (system, version, etc.).
104
+
105
+ Returns
106
+ -------
107
+ PlatformInfo
108
+ Protobuf message with platform information
109
+ """
110
+ return PlatformInfo(
111
+ system=platform.system(),
112
+ release=platform.release(),
113
+ version=platform.version(),
114
+ machine=platform.machine(),
115
+ processor=platform.processor(),
116
+ hostname=platform.node(),
117
+ )
118
+
119
+ async def collect_all_metrics(self) -> MetricsSnapshot:
120
+ """
121
+ Collect all available metrics.
122
+
123
+ Returns
124
+ -------
125
+ MetricsSnapshot
126
+ Protobuf message with all collected metrics
127
+ """
128
+ cpu_metrics = await self.collect_cpu_metrics()
129
+ memory_metrics = await self.collect_memory_metrics()
130
+ # gpu_metrics = await self.collect_gpu_metrics()
131
+ # additional_metrics = await self.collect_additional_metrics()
132
+ # platform_info = self.get_platform_info()
133
+
134
+ # Combine all metrics into a snapshot
135
+ metrics = MetricsSnapshot(
136
+ timestamp=datetime.now(timezone.utc),
137
+ cpu=cpu_metrics,
138
+ memory=memory_metrics,
139
+ # gpu=gpu_metrics,
140
+ # additional=additional_metrics,
141
+ # platform=platform_info,
142
+ )
143
+
144
+ # Update latest metrics with thread safety
145
+ async with self._lock:
146
+ self._latest_metrics = metrics
147
+
148
+ return metrics
149
+
150
+ async def start_collection(self):
151
+ """
152
+ Start the metrics collection background task.
153
+ """
154
+ if self._running:
155
+ self.tracer.warning("Metrics collection already running")
156
+ return
157
+
158
+ self._running = True
159
+ self._collection_task = asyncio.create_task(self._collection_loop())
160
+ self.tracer.info(
161
+ f"Started metrics collection (interval: {self.collection_interval}s)"
162
+ )
163
+
164
+ async def stop_collection(self):
165
+ """
166
+ Stop the metrics collection background task.
167
+ """
168
+ if not self._running:
169
+ return
170
+
171
+ self._running = False
172
+ if self._collection_task:
173
+ self._collection_task.cancel()
174
+ try:
175
+ await self._collection_task
176
+ except asyncio.CancelledError:
177
+ pass
178
+ self._collection_task = None
179
+
180
+ self.tracer.info("Stopped metrics collection")
181
+
182
+ async def _collection_loop(self):
183
+ """
184
+ Background loop that periodically collects metrics.
185
+ """
186
+ while self._running:
187
+ try:
188
+ await self.collect_all_metrics()
189
+ await asyncio.sleep(self.collection_interval)
190
+ except asyncio.CancelledError:
191
+ break
192
+ except Exception as e:
193
+ self.tracer.error(f"Error in metrics collection loop: {e}")
194
+ await asyncio.sleep(self.collection_interval)
195
+
196
+ async def get_latest_metrics(self) -> Optional[MetricsSnapshot]:
197
+ """
198
+ Get the most recently collected metrics.
199
+
200
+ Returns
201
+ -------
202
+ Optional[MetricsSnapshot]
203
+ The latest collected metrics, or None if no metrics have been collected
204
+ """
205
+ async with self._lock:
206
+ return self._latest_metrics
207
+
208
+
209
+ class GenericMetricsCollector(MetricsCollectorBase):
210
+ """
211
+ Generic implementation of the metrics collector using psutil.
212
+
213
+ This implementation works on most platforms (Linux, macOS, Windows)
214
+ where psutil is available.
215
+
216
+ Parameters
217
+ ----------
218
+ node_id : Any
219
+ The ID of the node where metrics are being collected
220
+ collection_interval : float
221
+ Time in seconds between metrics collection (default: 30.0)
222
+ """
223
+
224
+ def __init__(self, collection_interval: float = 30.0):
225
+ super().__init__(collection_interval)
226
+
227
+ # psutil is now always available
228
+
229
+ async def collect_cpu_metrics(self) -> CpuMetrics:
230
+ """
231
+ Collect CPU usage metrics using psutil.
232
+
233
+ Returns
234
+ -------
235
+ CpuMetrics
236
+ Protobuf message with CPU metrics
237
+ """
238
+ # psutil is now always available
239
+
240
+ # Get CPU usage percentage (blocking call, so run in executor)
241
+ cpu_percent = await asyncio.to_thread(psutil.cpu_percent, interval=0.1)
242
+
243
+ # Get per-core CPU usage
244
+ per_cpu = await asyncio.to_thread(psutil.cpu_percent, interval=0.1, percpu=True)
245
+
246
+ # Get CPU times
247
+ cpu_times = await asyncio.to_thread(psutil.cpu_times_percent, interval=0.1)
248
+
249
+ return CpuMetrics(
250
+ usage_percent=cpu_percent,
251
+ per_cpu_percent=per_cpu,
252
+ user_percent=float(cpu_times.user),
253
+ system_percent=float(cpu_times.system),
254
+ idle_percent=float(cpu_times.idle),
255
+ count=psutil.cpu_count(logical=True) or 0,
256
+ physical_count=psutil.cpu_count(logical=False) or 0,
257
+ )
258
+
259
+ async def collect_memory_metrics(self) -> MemoryMetrics:
260
+ """
261
+ Collect memory usage metrics using psutil.
262
+
263
+ Returns
264
+ -------
265
+ MemoryMetrics
266
+ Protobuf message with memory metrics
267
+ """
268
+ # psutil is now always available
269
+
270
+ # Get virtual memory stats
271
+ memory = await asyncio.to_thread(psutil.virtual_memory)
272
+
273
+ # Get swap memory stats
274
+ swap = await asyncio.to_thread(psutil.swap_memory)
275
+
276
+ return MemoryMetrics(
277
+ total_bytes=memory.total,
278
+ available_bytes=memory.available,
279
+ used_bytes=memory.used,
280
+ free_bytes=memory.free,
281
+ percent_used=memory.percent,
282
+ swap_total_bytes=swap.total,
283
+ swap_used_bytes=swap.used,
284
+ swap_free_bytes=swap.free,
285
+ swap_percent_used=swap.percent,
286
+ )
287
+
288
+ async def collect_gpu_metrics(self) -> GpuDeviceList:
289
+ """
290
+ Collect GPU metrics if available.
291
+
292
+ This generic implementation doesn't collect GPU metrics.
293
+ Subclasses for specific platforms will override this method.
294
+
295
+ Returns
296
+ -------
297
+ GpuDeviceList
298
+ Empty build message (no GPU metrics in generic implementation)
299
+ """
300
+ # Generic implementation doesn't collect GPU metrics
301
+ # This will be overridden in platform-specific implementations
302
+ return GpuDeviceList(devices=[])
303
+
304
+ async def collect_additional_metrics(self) -> AdditionalMetrics:
305
+ """
306
+ Collect disk and network metrics using psutil.
307
+
308
+ Returns
309
+ -------
310
+ AdditionalMetrics
311
+ Protobuf message with disk and network metrics
312
+ """
313
+ # psutil is now always available
314
+
315
+ # Get disk usage
316
+ disk_usage = []
317
+ for partition in psutil.disk_partitions(all=False):
318
+ try:
319
+ usage = psutil.disk_usage(partition.mountpoint)
320
+ disk_usage.append(
321
+ DiskUsage(
322
+ mount_point=partition.mountpoint,
323
+ total_bytes=usage.total,
324
+ used_bytes=usage.used,
325
+ free_bytes=usage.free,
326
+ percent_used=usage.percent,
327
+ )
328
+ )
329
+ except (PermissionError, OSError):
330
+ # Some mountpoints may not be accessible
331
+ pass
332
+
333
+ # Get basic network info
334
+ net_io = psutil.net_io_counters()
335
+ network = NetworkUsage(
336
+ bytes_sent=net_io.bytes_sent,
337
+ bytes_recv=net_io.bytes_recv,
338
+ packets_sent=net_io.packets_sent,
339
+ packets_recv=net_io.packets_recv,
340
+ )
341
+
342
+ # Get system uptime
343
+ boot_time = psutil.boot_time()
344
+ uptime_seconds = time.time() - boot_time
345
+
346
+ # Combine all additional metrics
347
+ return AdditionalMetrics(
348
+ disk_usage=disk_usage,
349
+ network=network,
350
+ uptime_seconds=int(uptime_seconds),
351
+ )
@@ -0,0 +1,7 @@
1
+ """MQTT infrastructure - Message broker communication."""
2
+
3
+ from .command_handler import CommandHandler
4
+
5
+ __all__ = [
6
+ "CommandHandler",
7
+ ]