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,284 @@
1
+ from logging import getLogger
2
+ from typing import AsyncIterator
3
+
4
+ from manta_common.build.common.results import (
5
+ ChunkResultValues,
6
+ GlobalTag,
7
+ GlobalUpdate,
8
+ GlobalValue,
9
+ Result,
10
+ ResultQuery,
11
+ )
12
+ from manta_common.build.common.system import EnvId, Ok
13
+ from manta_common.build.common.tasks import TaskScheduling, TaskUpdate
14
+ from manta_common.build.node.light_service import (
15
+ GetGlobalRequest,
16
+ LightResult,
17
+ LightResultQuery,
18
+ SetGlobalRequest,
19
+ WorldBase,
20
+ )
21
+ from manta_common.build.node.node_service import StopSwarmProcess
22
+ from manta_common.conversions import ID
23
+ from manta_common.decorators import catch_batch_errors, catch_streaming_errors
24
+ from manta_common.traces import Tracer
25
+ from ...tasks import TaskProgressions
26
+ from ..grpc.client import NodeClient
27
+
28
+ __all__ = ["WorldServicer"]
29
+
30
+
31
+ class WorldServicer(WorldBase):
32
+ """
33
+ World Servicer allows containers to access data stored in the Manager
34
+
35
+ Parameters
36
+ ----------
37
+
38
+ Node ID
39
+ node_client : NodeClient
40
+ Node client
41
+ tasks : TaskProgressions
42
+ Task Progressions from Task Manager
43
+ """
44
+
45
+ __slots__ = ["tracer", "node_client", "tasks"]
46
+
47
+ def __init__(self, node_client: NodeClient, tasks: TaskProgressions):
48
+ self.tracer = Tracer(getLogger(__name__))
49
+ self.node_client = node_client
50
+ self.tasks = tasks
51
+ super().__init__()
52
+
53
+ def task_update(self, swarm_id: ID, task_id: ID) -> TaskUpdate:
54
+ """
55
+ Convenient method to access task update from tasks
56
+ given a task ID
57
+
58
+ Parameters
59
+ ----------
60
+ swarm_id : PairId
61
+ Swarm ID
62
+ task_id : PairId
63
+ Task ID
64
+
65
+ Returns
66
+ -------
67
+ TaskUpdate
68
+ Task Update
69
+ """
70
+ return self.tasks[(swarm_id.tid, task_id.tid)].task_update
71
+
72
+ @catch_streaming_errors
73
+ async def get_task_result(
74
+ self, light_request: LightResultQuery
75
+ ) -> AsyncIterator[ChunkResultValues]:
76
+ """
77
+ Get the swarm results
78
+
79
+ Parameters
80
+ ----------
81
+ request : LightResultQuery
82
+ Result query from the container
83
+
84
+ Returns
85
+ -------
86
+ AsyncIterator[ChunkResultValues]
87
+ Result values
88
+ """
89
+ task_id = ID(light_request.task_id)
90
+ swarm_id = ID(light_request.swarm_id)
91
+ task_update = self.task_update(swarm_id, task_id)
92
+ iteration = task_update.iteration
93
+ circular = task_update.circular
94
+ self.tracer.set_metadata(
95
+ task_id=task_id,
96
+ swarm_id=swarm_id,
97
+ iteration=iteration,
98
+ circular=circular,
99
+ )
100
+
101
+ async for chunk in self.node_client.get_task_result(
102
+ ResultQuery(
103
+ swarm_id=swarm_id.oid,
104
+ task_id=task_id.oid,
105
+ node_id=self.tracer.metadata.node_id,
106
+ iteration=iteration,
107
+ tag=light_request.tag,
108
+ size=light_request.size,
109
+ method=light_request.method,
110
+ )
111
+ ):
112
+ self.tracer.set_metadata(
113
+ task_id=task_id,
114
+ swarm_id=swarm_id,
115
+ iteration=iteration,
116
+ circular=circular,
117
+ )
118
+ yield chunk
119
+
120
+ @catch_batch_errors
121
+ async def add_task_result(self, stream: AsyncIterator[LightResult]) -> Ok:
122
+ """
123
+ Set a swarm result
124
+
125
+ Parameters
126
+ ----------
127
+ request : LightResult
128
+ Result from the container
129
+
130
+ Returns
131
+ -------
132
+ Ok
133
+ Response
134
+ """
135
+
136
+ async def stream_generator(
137
+ stream: AsyncIterator[LightResult],
138
+ ) -> AsyncIterator[Result]:
139
+ async for light_request in stream:
140
+ task_id = ID(light_request.task_id)
141
+ swarm_id = ID(light_request.swarm_id)
142
+ task_update = self.task_update(swarm_id, task_id)
143
+ self.tracer.set_metadata(
144
+ task_id=task_id,
145
+ swarm_id=swarm_id,
146
+ iteration=task_update.iteration,
147
+ circular=task_update.circular,
148
+ )
149
+
150
+ yield Result(
151
+ swarm_id=swarm_id.oid,
152
+ task_id=task_id.oid,
153
+ node_id=self.tracer.metadata.node_id,
154
+ iteration=task_update.iteration,
155
+ tag=light_request.tag,
156
+ data=light_request.data,
157
+ )
158
+
159
+ return await self.node_client.add_task_result(stream_generator(stream))
160
+
161
+ @catch_streaming_errors
162
+ async def get_global(self, request: GetGlobalRequest) -> AsyncIterator[GlobalValue]:
163
+ """
164
+ Set a swarm global value
165
+
166
+ Parameters
167
+ ----------
168
+ request : GlobalTag
169
+ Task ID and global tag
170
+
171
+ Returns
172
+ -------
173
+ GlobalValue
174
+ Global value
175
+ """
176
+ task_id = ID(request.task_id)
177
+ swarm_id = ID(request.swarm_id)
178
+ task_update = self.task_update(swarm_id, task_id)
179
+ circular = task_update.circular
180
+ iteration = task_update.iteration
181
+
182
+ async for chunk in self.node_client.get_global(
183
+ GlobalTag(swarm_id=swarm_id.oid, tag=request.tag)
184
+ ):
185
+ self.tracer.set_metadata(
186
+ task_id=task_id,
187
+ swarm_id=swarm_id,
188
+ iteration=iteration,
189
+ circular=circular,
190
+ )
191
+ self.tracer.info(f"Received chunk for global of size {len(chunk.data)}")
192
+ yield chunk
193
+
194
+ @catch_batch_errors
195
+ async def set_global(self, stream: AsyncIterator[SetGlobalRequest]) -> Ok:
196
+ """
197
+ Set a swarm result
198
+
199
+ Parameters
200
+ ----------
201
+ request : SetGlobalRequest
202
+ Task ID, global tag and value
203
+
204
+ Returns
205
+ -------
206
+ Ok
207
+ Response
208
+ """
209
+
210
+ async def stream_generator(
211
+ stream: AsyncIterator[SetGlobalRequest],
212
+ ) -> AsyncIterator[GlobalUpdate]:
213
+ async for request in stream:
214
+ swarm_id = ID(request.swarm_id)
215
+ task_id = ID(request.task_id)
216
+ task_update = self.task_update(swarm_id, task_id)
217
+ self.tracer.set_metadata(
218
+ task_id=task_id,
219
+ swarm_id=swarm_id,
220
+ iteration=task_update.iteration,
221
+ circular=task_update.circular,
222
+ )
223
+
224
+ yield GlobalUpdate(
225
+ swarm_id=swarm_id.oid,
226
+ tag=request.tag,
227
+ data=request.data,
228
+ )
229
+
230
+ return await self.node_client.set_global(stream_generator(stream))
231
+
232
+ @catch_batch_errors
233
+ async def stop_swarm(self, request: EnvId) -> Ok:
234
+ """
235
+ Stop the swarm
236
+
237
+ Parameters
238
+ ----------
239
+ request : EnvId
240
+ Task ID
241
+
242
+ Returns
243
+ -------
244
+ Ok
245
+ Response
246
+ """
247
+ swarm_id = ID(request.swarm_id)
248
+ task_id = ID(request.task_id)
249
+ task_update = self.task_update(swarm_id, task_id)
250
+ self.tracer.set_metadata(
251
+ task_id=task_id,
252
+ swarm_id=swarm_id,
253
+ iteration=task_update.iteration,
254
+ circular=task_update.circular,
255
+ )
256
+ return await self.node_client.stop_swarm(
257
+ StopSwarmProcess(swarm_id=task_update.swarm_id)
258
+ )
259
+
260
+ @catch_batch_errors
261
+ async def schedule_task(self, light_request: TaskScheduling) -> Ok:
262
+ """
263
+ Schedule a task
264
+
265
+ Parameters
266
+ ----------
267
+ request : TaskScheduling
268
+ Task Scheduling from container
269
+
270
+ Returns
271
+ -------
272
+ Ok
273
+ Response
274
+ """
275
+ swarm_id = ID(light_request.swarm_id)
276
+ task_id = ID(light_request.task_id)
277
+ task_update = self.task_update(swarm_id, task_id)
278
+ self.tracer.set_metadata(
279
+ task_id=task_id,
280
+ swarm_id=swarm_id,
281
+ iteration=task_update.iteration,
282
+ circular=task_update.circular,
283
+ )
284
+ return await self.node_client.schedule_task(light_request)
@@ -0,0 +1,10 @@
1
+ """Metrics infrastructure - System monitoring and data collection."""
2
+
3
+ from .collector import Collector
4
+ from .metrics_collector import GenericMetricsCollector, MetricsCollectorBase
5
+
6
+ __all__ = [
7
+ "Collector",
8
+ "GenericMetricsCollector",
9
+ "MetricsCollectorBase",
10
+ ]
@@ -0,0 +1,94 @@
1
+ from manta_common.build.common.informations import NodeStatus, NodeStatusEnum
2
+ from manta_common.errors import (
3
+ MantaError,
4
+ MantaGRPCError,
5
+ MantaMQTTError,
6
+ MantaNodeError,
7
+ )
8
+ from manta_common.traces import Tracer
9
+ from ..filesystem.dataset_manager import DatasetManager
10
+ from ..grpc.client import NodeClient
11
+ from ..metrics.metrics_collector import MetricsCollectorBase
12
+
13
+
14
+ class Collector:
15
+ """
16
+ Collector class to collect information from the node
17
+
18
+ Parameters
19
+ ----------
20
+ tracer : Tracer
21
+ Tracer for the collector
22
+ """
23
+
24
+ tracer: Tracer
25
+ node_client: NodeClient
26
+ metrics_collector: MetricsCollectorBase
27
+ dataset_manager: DatasetManager
28
+
29
+ async def collect_information(self, payload: bytes):
30
+ """
31
+ Send the node information to the Manager
32
+
33
+ Parameters
34
+ ----------
35
+ payload : bytes
36
+ Payload
37
+
38
+ Raises
39
+ ------
40
+ TaskManagerException
41
+ Exception when the method requested is not allowed
42
+ """
43
+ try:
44
+ method = payload.decode("utf-8")
45
+ if method == "set_node_status":
46
+ await self.set_node_status()
47
+ elif method == "set_system_summary":
48
+ await self.set_system_summary()
49
+ elif method == "set_overviews":
50
+ await self.set_overviews()
51
+ else:
52
+ raise MantaMQTTError(
53
+ f"Not allowed method: {method}", metadata=self.tracer.metadata
54
+ )
55
+ except MantaGRPCError as e:
56
+ self.tracer.exception(f"Error when collecting information: {e}")
57
+ except MantaError as manta_error:
58
+ self.tracer.exception(repr(manta_error))
59
+ await self.node_client.send_error(manta_error)
60
+ except Exception as exc:
61
+ message = f"Error for collecting information: {repr(exc)}"
62
+ self.tracer.exception(message)
63
+ await self.node_client.send_error(
64
+ MantaNodeError(message, metadata=self.tracer.metadata)
65
+ )
66
+
67
+ async def set_node_status(self): # DEAD CODE
68
+ """
69
+ Send the node information to the Manager
70
+ """
71
+ self.tracer.info("Sending NodeInfo to the Manager")
72
+ await self.node_client.set_node_status(
73
+ NodeStatus(status=NodeStatusEnum.CONNECTED)
74
+ )
75
+
76
+ async def set_system_summary(self):
77
+ """
78
+ Send the system information to the Manager
79
+ """
80
+ self.tracer.info("Sending SystemInfo to the Manager")
81
+ metrics = await self.metrics_collector.collect_all_metrics()
82
+ await self.node_client.set_system_summary(metrics)
83
+
84
+ async def set_overviews(self):
85
+ """
86
+ Send the data information to the Manager
87
+ """
88
+ self.tracer.info("Sending DataInfo to the Manager")
89
+
90
+ # Refresh the dataset metadata before sending
91
+ self.dataset_manager.refresh()
92
+
93
+ # Use the dataset_manager to get the overview information
94
+ await self.node_client.set_overviews(self.dataset_manager.to_proto())