manta-node 0.6b5.dev707__py3-none-any.whl → 0.6b5.dev742__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.
- manta_node/cli/_version_generated.py +3 -3
- manta_node/infrastructure/metrics/metrics_collector.py +66 -35
- manta_node/seam.py +1 -0
- manta_node/supervisor/lifecycle.py +11 -1
- manta_node/supervisor/switch.py +20 -0
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/METADATA +2 -2
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/RECORD +11 -11
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/WHEEL +0 -0
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/entry_points.txt +0 -0
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/licenses/LICENSE +0 -0
- {manta_node-0.6b5.dev707.dist-info → manta_node-0.6b5.dev742.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ This file is auto-generated at build time by scripts/generate_version.py.
|
|
|
4
4
|
Do not edit manually.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "2026.09.
|
|
8
|
-
__build_date__ = "2026.09.
|
|
9
|
-
__commit_id__ = "
|
|
7
|
+
__version__ = "2026.09.29.6a0ccdc7"
|
|
8
|
+
__build_date__ = "2026.09.29"
|
|
9
|
+
__commit_id__ = "6a0ccdc7"
|
|
10
10
|
__package_version__ = "0.6b5"
|
|
@@ -132,16 +132,27 @@ class MetricsCollectorBase(ABC):
|
|
|
132
132
|
cpu_metrics = await self.collect_cpu_metrics()
|
|
133
133
|
memory_metrics = await self.collect_memory_metrics()
|
|
134
134
|
# gpu_metrics = await self.collect_gpu_metrics()
|
|
135
|
-
# additional_metrics = await self.collect_additional_metrics()
|
|
136
135
|
# platform_info = self.get_platform_info()
|
|
137
136
|
|
|
137
|
+
# Disk/network is best-effort: the manager is waiting on this snapshot
|
|
138
|
+
# for its heartbeat, so a failure collecting it must not cost the
|
|
139
|
+
# cpu/memory reading. `additional=None` and an unset field serialize
|
|
140
|
+
# identically (proto3 explicit presence), which is also what a build
|
|
141
|
+
# too old to collect it sends -- both cases correctly report "no
|
|
142
|
+
# disk/network reading this cycle", never a stale or partial one.
|
|
143
|
+
try:
|
|
144
|
+
additional_metrics = await self.collect_additional_metrics()
|
|
145
|
+
except Exception as e:
|
|
146
|
+
self.tracer.error(f"Error collecting additional metrics: {e}")
|
|
147
|
+
additional_metrics = None
|
|
148
|
+
|
|
138
149
|
# Combine all metrics into a snapshot
|
|
139
150
|
metrics = MetricsSnapshot(
|
|
140
151
|
timestamp=datetime.now(timezone.utc),
|
|
141
152
|
cpu=cpu_metrics,
|
|
142
153
|
memory=memory_metrics,
|
|
143
154
|
# gpu=gpu_metrics,
|
|
144
|
-
|
|
155
|
+
additional=additional_metrics,
|
|
145
156
|
# platform=platform_info,
|
|
146
157
|
)
|
|
147
158
|
|
|
@@ -322,40 +333,60 @@ class GenericMetricsCollector(MetricsCollectorBase):
|
|
|
322
333
|
"""
|
|
323
334
|
# psutil is now always available
|
|
324
335
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
336
|
+
def read_additional_metrics() -> AdditionalMetrics:
|
|
337
|
+
# Get disk usage. `all=False` already drops pseudo/virtual
|
|
338
|
+
# filesystems (overlay, tmpfs, proc, sysfs, ...): on Linux it
|
|
339
|
+
# keeps only fstypes absent from /proc/filesystems' `nodev` list,
|
|
340
|
+
# which excludes a container's own overlay root along with the
|
|
341
|
+
# rest. What it does NOT dedupe: Docker bind-mounts
|
|
342
|
+
# /etc/hostname, /etc/hosts and /etc/resolv.conf from one
|
|
343
|
+
# host-side file each, and psutil lists each bind mount as its
|
|
344
|
+
# own partition even though all three share one underlying
|
|
345
|
+
# device -- so every container reports that one disk three times
|
|
346
|
+
# over unless a device already seen is skipped.
|
|
347
|
+
disk_usage = []
|
|
348
|
+
seen_devices: set[str] = set()
|
|
349
|
+
for partition in psutil.disk_partitions(all=False):
|
|
350
|
+
if partition.device in seen_devices:
|
|
351
|
+
continue
|
|
352
|
+
seen_devices.add(partition.device)
|
|
353
|
+
try:
|
|
354
|
+
usage = psutil.disk_usage(partition.mountpoint)
|
|
355
|
+
disk_usage.append(
|
|
356
|
+
DiskUsage(
|
|
357
|
+
mount_point=partition.mountpoint,
|
|
358
|
+
total_bytes=usage.total,
|
|
359
|
+
used_bytes=usage.used,
|
|
360
|
+
free_bytes=usage.free,
|
|
361
|
+
percent_used=usage.percent,
|
|
362
|
+
)
|
|
337
363
|
)
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
364
|
+
except (PermissionError, OSError):
|
|
365
|
+
# Some mountpoints may not be accessible
|
|
366
|
+
pass
|
|
367
|
+
|
|
368
|
+
# Get basic network info
|
|
369
|
+
net_io = psutil.net_io_counters()
|
|
370
|
+
network = NetworkUsage(
|
|
371
|
+
bytes_sent=net_io.bytes_sent,
|
|
372
|
+
bytes_recv=net_io.bytes_recv,
|
|
373
|
+
packets_sent=net_io.packets_sent,
|
|
374
|
+
packets_recv=net_io.packets_recv,
|
|
375
|
+
)
|
|
342
376
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
bytes_sent=net_io.bytes_sent,
|
|
347
|
-
bytes_recv=net_io.bytes_recv,
|
|
348
|
-
packets_sent=net_io.packets_sent,
|
|
349
|
-
packets_recv=net_io.packets_recv,
|
|
350
|
-
)
|
|
377
|
+
# Get system uptime
|
|
378
|
+
boot_time = psutil.boot_time()
|
|
379
|
+
uptime_seconds = time.time() - boot_time
|
|
351
380
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
381
|
+
return AdditionalMetrics(
|
|
382
|
+
disk_usage=disk_usage,
|
|
383
|
+
network=network,
|
|
384
|
+
uptime_seconds=int(uptime_seconds),
|
|
385
|
+
)
|
|
355
386
|
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
)
|
|
387
|
+
# A stat per surviving partition plus two /proc reads, all blocking
|
|
388
|
+
# syscalls; this now runs on the ~1s production heartbeat
|
|
389
|
+
# (ping_interval, infrastructure/mqtt/command_handler.py), so it must
|
|
390
|
+
# not block the shared event loop -- the same reason
|
|
391
|
+
# collect_memory_metrics reads psutil off-thread.
|
|
392
|
+
return await asyncio.to_thread(read_additional_metrics)
|
manta_node/seam.py
CHANGED
|
@@ -99,7 +99,8 @@ def run_switch(
|
|
|
99
99
|
"""Run the lifecycle for one request and return its terminal outcome.
|
|
100
100
|
|
|
101
101
|
Terminal states: ``REPORTING`` (came back on the new version), ``REVERTED``
|
|
102
|
-
(no return within the window, reverted to the last good), ``
|
|
102
|
+
(no return within the window, reverted to the last good), ``SKIPPED`` (the
|
|
103
|
+
target is already current; nothing to do, no restart), ``FAILED`` (a
|
|
103
104
|
pre-switch step failed; nothing changed), ``DOWN`` (the switch happened and
|
|
104
105
|
the revert itself failed — the node is not running, surfaced honestly).
|
|
105
106
|
|
|
@@ -107,6 +108,15 @@ def run_switch(
|
|
|
107
108
|
lifecycle resolves, so a supervisor restart mid-window can re-evaluate it.
|
|
108
109
|
"""
|
|
109
110
|
bounds = bounds or Bounds()
|
|
111
|
+
|
|
112
|
+
# NO-OP — applying the pair already current changes nothing (NF-5). Return
|
|
113
|
+
# before fetch/verify/stage/commit, so the child is NOT restarted: under B1 a
|
|
114
|
+
# re-apply would otherwise be a full switch and restart the node for no change
|
|
115
|
+
# (the daily loop that never converges). `force` does not bypass this: it is
|
|
116
|
+
# the not-newer override, and a deliberate bounce is a unit restart.
|
|
117
|
+
if version_tree.is_current_pair(request.target):
|
|
118
|
+
return _outcome(request, SeamState.SKIPPED, "target is already current")
|
|
119
|
+
|
|
110
120
|
last_good_dir = version_tree.selected()
|
|
111
121
|
last_good = last_good_dir.name if last_good_dir else None
|
|
112
122
|
candidate_dir = request.target
|
manta_node/supervisor/switch.py
CHANGED
|
@@ -215,6 +215,26 @@ def is_pointer_target(target: Path) -> bool:
|
|
|
215
215
|
return link.is_symlink() and Path(os.path.realpath(link)) == target
|
|
216
216
|
|
|
217
217
|
|
|
218
|
+
def is_current_pair(pair: str) -> bool:
|
|
219
|
+
"""True when the pair named by ``pair`` is already the current version.
|
|
220
|
+
|
|
221
|
+
A request to apply the code already running is a no-op (NF-5): under B1 a
|
|
222
|
+
re-apply would otherwise fetch, verify, stage, commit and **restart** the
|
|
223
|
+
child, restarting the node for no change. The check is by pair identity, so it
|
|
224
|
+
holds whether the target names the version dir directly or a set id that
|
|
225
|
+
resolves to it. A node with no valid ``current`` is never "already current".
|
|
226
|
+
"""
|
|
227
|
+
version_dir = selected()
|
|
228
|
+
if version_dir is None:
|
|
229
|
+
return False
|
|
230
|
+
# The dir name and the manifest's pair are the same identity; either naming it
|
|
231
|
+
# is an exact match on what is running.
|
|
232
|
+
if version_dir.name == pair:
|
|
233
|
+
return True
|
|
234
|
+
manifest = read_manifest(version_dir)
|
|
235
|
+
return manifest is not None and manifest.pair == pair
|
|
236
|
+
|
|
237
|
+
|
|
218
238
|
def list_versions() -> list[Path]:
|
|
219
239
|
"""The version dirs, oldest first.
|
|
220
240
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: manta_node
|
|
3
|
-
Version: 0.6b5.
|
|
3
|
+
Version: 0.6b5.dev742
|
|
4
4
|
Summary: Node side software of the Manta platform. It is responsible for the communication with the Manta Core and the execution of the tasks.
|
|
5
5
|
Author-email: Hugo Miralles <hugo.miralles@manta-tech.io>, Matthew Thompson <matthew.thompson@manta-tech.io>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -28,7 +28,7 @@ Requires-Dist: pyyaml
|
|
|
28
28
|
Requires-Dist: psutil
|
|
29
29
|
Requires-Dist: msgpack
|
|
30
30
|
Requires-Dist: aiomqtt<3.0,>=2.5.1
|
|
31
|
-
Requires-Dist: manta-common-core<=0.6b5,>=0.6b5.
|
|
31
|
+
Requires-Dist: manta-common-core<=0.6b5,>=0.6b5.dev738
|
|
32
32
|
Requires-Dist: toml
|
|
33
33
|
Requires-Dist: tomli; python_version < "3.11"
|
|
34
34
|
Requires-Dist: tomli-w
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
manta_node/__init__.py,sha256=bgGWXH3yQVhNf0v1ZGUBAy5Y51fqb0Y-EaLnocbcino,153
|
|
2
2
|
manta_node/__main__.py,sha256=SjrJyuMg_ZFKV6WOVe3MrtWM8Qmu065dkKZYl4n2YLw,1665
|
|
3
3
|
manta_node/node_orchestrator.py,sha256=nfpNCM8wgnihKhZZ36GIizmyyaOdEOBhdfn7PqqTCrQ,29591
|
|
4
|
-
manta_node/seam.py,sha256=
|
|
4
|
+
manta_node/seam.py,sha256=npu2QdIqnybiz0h4Wb7aE4vPwXJIWTZW3z31FSk6sFk,4771
|
|
5
5
|
manta_node/task_manager.py,sha256=xRE-yKdUW0FFR8vtX1jDwl1AxTbqVD_JS7QVR62GA00,38002
|
|
6
6
|
manta_node/tasks.py,sha256=o837Hi-KFVJg9LF5iOtE8oD6UuTOfrEPWR-JOdhRGeY,6983
|
|
7
7
|
manta_node/utils.py,sha256=Hw4Iw2jYQYsfVLVJuBMt-_rMFBeml3nCDE2jiiXc8YM,1155
|
|
8
8
|
manta_node/cli/__init__.py,sha256=arzO3mXDJ-E2yeeytbZfN7mCswwxdQ43_QjyeL2E5yE,134
|
|
9
|
-
manta_node/cli/_version_generated.py,sha256=
|
|
9
|
+
manta_node/cli/_version_generated.py,sha256=SEyf_9vyzjLestxXRcjIeAys-zf8ukAgt9rRCNp9zpM,275
|
|
10
10
|
manta_node/cli/config_manager.py,sha256=BCju9zqzraviL3KrzRnB-vZQUY__Q5kuEqb7EdB8YdI,4409
|
|
11
11
|
manta_node/cli/main.py,sha256=dZa6zrypWBvpN8hd4qpxevvlyNFhxKINCg1537NJ36w,4318
|
|
12
12
|
manta_node/cli/version.py,sha256=3lrnIWpOosszBN-VsCBVLxDgpvCC7IB0aDIKx_3e7hI,3115
|
|
@@ -39,7 +39,7 @@ manta_node/infrastructure/grpc/local_servicer.py,sha256=9PFAwpKKFGy3P7HZfx2BHwhO
|
|
|
39
39
|
manta_node/infrastructure/grpc/world_servicer.py,sha256=nmyrMzYxzGDlZ1-oOeyALgd76mbeOmAOsjzoVN6f0SA,8222
|
|
40
40
|
manta_node/infrastructure/metrics/__init__.py,sha256=ODGAj9s63F5jba2c3dQRMfNK6I4WvMdcJUS_xApUN5Y,272
|
|
41
41
|
manta_node/infrastructure/metrics/collector.py,sha256=9ESw__Pc2tV6ldG5yhos2IS7T5Td59KxTIwDRZc_G4w,3067
|
|
42
|
-
manta_node/infrastructure/metrics/metrics_collector.py,sha256=
|
|
42
|
+
manta_node/infrastructure/metrics/metrics_collector.py,sha256=osIYrNzU3g9WCAxVQ14isM9YEQ3eJ7F3QgKBbpgeMJs,13077
|
|
43
43
|
manta_node/infrastructure/mqtt/__init__.py,sha256=riXo1sXgO4YV6DHCmWRqK61BAmuGLdHiVdQFunAJadA,140
|
|
44
44
|
manta_node/infrastructure/mqtt/command_handler.py,sha256=aGJMPF8uAdeEw5xfE_WlL3-ROiSV_LCUXf5EpmZrbtk,29728
|
|
45
45
|
manta_node/infrastructure/network/__init__.py,sha256=On3XLgycFQoc-fBCa5hFuFDfEJjmFy7Wl2CK3D2LkdI,478
|
|
@@ -56,14 +56,14 @@ manta_node/supervisor/__init__.py,sha256=kgdoNce1tM4e7jvdxkdmnNJV1L92-NI2cRfYSdm
|
|
|
56
56
|
manta_node/supervisor/bounds.py,sha256=MlUfj0tYY-US348JsxYA-Ph5pSpgoOPlRdVTwmrPtZA,3181
|
|
57
57
|
manta_node/supervisor/executor.py,sha256=a0JafVoTmtbIu87nwUtj08KAC-Q-u0Ajdn_ptyu9yoc,6833
|
|
58
58
|
manta_node/supervisor/inflight.py,sha256=JOqwXYM928fpcQtYdoK7596eAg28KM70bh85cyQgX3Q,2663
|
|
59
|
-
manta_node/supervisor/lifecycle.py,sha256=
|
|
59
|
+
manta_node/supervisor/lifecycle.py,sha256=HARQv3wYyK-ZjcBac-ixQMVlkjHvNtIpRdSMm2lNHCQ,10915
|
|
60
60
|
manta_node/supervisor/process.py,sha256=N5WvNCJnJR3c6I4uqBPPFqgEdCI9rFulHyGem9Shc-I,19155
|
|
61
61
|
manta_node/supervisor/records.py,sha256=fUlL1SfmWpGnCbJ9956cuy0H3a7-aEF-B-naqbJiYoU,6405
|
|
62
62
|
manta_node/supervisor/seam.py,sha256=HomMFTDbc0dZQ9VrfGVhQxjiU7E23-zwyjZnLsnq6dc,8031
|
|
63
|
-
manta_node/supervisor/switch.py,sha256=
|
|
64
|
-
manta_node-0.6b5.
|
|
65
|
-
manta_node-0.6b5.
|
|
66
|
-
manta_node-0.6b5.
|
|
67
|
-
manta_node-0.6b5.
|
|
68
|
-
manta_node-0.6b5.
|
|
69
|
-
manta_node-0.6b5.
|
|
63
|
+
manta_node/supervisor/switch.py,sha256=hFCWhZDoWN9KN0zkNepsQfkypDhhlkBKmCOltCqlb3w,17614
|
|
64
|
+
manta_node-0.6b5.dev742.dist-info/licenses/LICENSE,sha256=9mBgLhiB9goQPQjg9XQJ6FjgVxYw9Q8lyOZYkPGwF_c,34484
|
|
65
|
+
manta_node-0.6b5.dev742.dist-info/METADATA,sha256=kD0dvyj-vlf8iKCY3_M1Juc2IFWE_kqUsyk7IIDB930,4231
|
|
66
|
+
manta_node-0.6b5.dev742.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
67
|
+
manta_node-0.6b5.dev742.dist-info/entry_points.txt,sha256=uCwggRApalLEsYs1YxwTBN0-e9oMJAkMoBp01HaSdoY,110
|
|
68
|
+
manta_node-0.6b5.dev742.dist-info/top_level.txt,sha256=nbT5J5WETuXM9UPoQckl29uUOq8wMYdRb9QDx5kAFeo,11
|
|
69
|
+
manta_node-0.6b5.dev742.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|