vantage6-node 4.15.1__tar.gz → 5.0.0__tar.gz
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.
- vantage6_node-5.0.0/.gitignore +37 -0
- vantage6_node-5.0.0/Makefile +19 -0
- vantage6_node-5.0.0/PKG-INFO +50 -0
- vantage6_node-5.0.0/README.md +24 -0
- vantage6_node-5.0.0/dev_start.sh +43 -0
- vantage6_node-5.0.0/pyproject.toml +48 -0
- vantage6_node-5.0.0/tests_node/test_pod_status_mapping.py +131 -0
- vantage6_node-5.0.0/utest.py +13 -0
- vantage6_node-5.0.0/vantage6/dev_start.py +35 -0
- vantage6_node-5.0.0/vantage6/node/__init__.py +901 -0
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/cli/node.py +25 -40
- vantage6_node-5.0.0/vantage6/node/enum.py +10 -0
- vantage6_node-5.0.0/vantage6/node/globals.py +60 -0
- vantage6_node-5.0.0/vantage6/node/k8s/container_manager.py +1804 -0
- vantage6_node-5.0.0/vantage6/node/k8s/data_classes.py +46 -0
- vantage6_node-5.0.0/vantage6/node/k8s/exceptions.py +50 -0
- vantage6_node-5.0.0/vantage6/node/k8s/jobpod_state_to_run_status_mapper.py +222 -0
- vantage6_node-5.0.0/vantage6/node/k8s/run_io.py +254 -0
- vantage6_node-5.0.0/vantage6/node/k8s/session_manager.py +160 -0
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/proxy_server.py +66 -78
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/socket.py +57 -22
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/util/__init__.py +7 -0
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/util/colorer.py +1 -24
- vantage6_node-4.15.1/PKG-INFO +0 -241
- vantage6_node-4.15.1/setup.cfg +0 -4
- vantage6_node-4.15.1/setup.py +0 -65
- vantage6_node-4.15.1/tests/test_ssh_tunnel.py +0 -0
- vantage6_node-4.15.1/vantage6/node/__build__ +0 -1
- vantage6_node-4.15.1/vantage6/node/__init__.py +0 -1310
- vantage6_node-4.15.1/vantage6/node/_version.py +0 -24
- vantage6_node-4.15.1/vantage6/node/context.py +0 -67
- vantage6_node-4.15.1/vantage6/node/docker/docker_base.py +0 -51
- vantage6_node-4.15.1/vantage6/node/docker/docker_manager.py +0 -996
- vantage6_node-4.15.1/vantage6/node/docker/exceptions.py +0 -28
- vantage6_node-4.15.1/vantage6/node/docker/squid.py +0 -284
- vantage6_node-4.15.1/vantage6/node/docker/ssh_tunnel.py +0 -306
- vantage6_node-4.15.1/vantage6/node/docker/task_manager.py +0 -968
- vantage6_node-4.15.1/vantage6/node/docker/utils.py +0 -44
- vantage6_node-4.15.1/vantage6/node/docker/vpn_manager.py +0 -714
- vantage6_node-4.15.1/vantage6/node/globals.py +0 -55
- vantage6_node-4.15.1/vantage6_node.egg-info/PKG-INFO +0 -241
- vantage6_node-4.15.1/vantage6_node.egg-info/SOURCES.txt +0 -29
- vantage6_node-4.15.1/vantage6_node.egg-info/dependency_links.txt +0 -1
- vantage6_node-4.15.1/vantage6_node.egg-info/entry_points.txt +0 -2
- vantage6_node-4.15.1/vantage6_node.egg-info/requires.txt +0 -21
- vantage6_node-4.15.1/vantage6_node.egg-info/top_level.txt +0 -2
- {vantage6_node-4.15.1/tests → vantage6_node-5.0.0/tests/docker}/__init__.py +0 -0
- {vantage6_node-4.15.1/tests/docker → vantage6_node-5.0.0/tests_node}/__init__.py +0 -0
- {vantage6_node-4.15.1 → vantage6_node-5.0.0}/vantage6/node/cli/__init__.py +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
# documentation
|
|
3
|
+
docs/_build
|
|
4
|
+
docs/api-docs/_autosummary
|
|
5
|
+
|
|
6
|
+
# Python
|
|
7
|
+
.ipynb_checkpoints
|
|
8
|
+
**/__pycache__
|
|
9
|
+
**/.coverage
|
|
10
|
+
|
|
11
|
+
# IDE's
|
|
12
|
+
.idea/
|
|
13
|
+
*.sublime-project
|
|
14
|
+
*.sublime-workspace
|
|
15
|
+
.vscode/
|
|
16
|
+
|
|
17
|
+
# build files
|
|
18
|
+
**/build/
|
|
19
|
+
**/dist/
|
|
20
|
+
*.egg-info
|
|
21
|
+
*.code-workspace
|
|
22
|
+
|
|
23
|
+
# UI build files
|
|
24
|
+
**/node_modules/
|
|
25
|
+
|
|
26
|
+
# Ignore DevSpace cache and log folder
|
|
27
|
+
.devspace/
|
|
28
|
+
dev/.data/
|
|
29
|
+
dev/.tasks/
|
|
30
|
+
dev/.db/
|
|
31
|
+
dev/.log/
|
|
32
|
+
|
|
33
|
+
# Helm
|
|
34
|
+
charts/**/*.tgz
|
|
35
|
+
|
|
36
|
+
# MacOS
|
|
37
|
+
.DS_Store
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# `make` is expected to be called from the directory that contains
|
|
2
|
+
# this Makefile
|
|
3
|
+
|
|
4
|
+
TAG ?= latest
|
|
5
|
+
|
|
6
|
+
rebuild: clean build-dist
|
|
7
|
+
|
|
8
|
+
build-dist:
|
|
9
|
+
# Build the PyPI package
|
|
10
|
+
uv build
|
|
11
|
+
|
|
12
|
+
publish:
|
|
13
|
+
# Uploading to pypi.org
|
|
14
|
+
twine upload --repository pypi dist/*
|
|
15
|
+
|
|
16
|
+
clean:
|
|
17
|
+
# Cleaning ...
|
|
18
|
+
-rm -r build
|
|
19
|
+
-rm dist/*
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vantage6-node
|
|
3
|
+
Version: 5.0.0
|
|
4
|
+
Summary: vantage6 node
|
|
5
|
+
Author: Vantage6 Team
|
|
6
|
+
Maintainer-email: Frank Martin <f.martin@iknl.nl>, Bart van Beusekom <b.vanbeusekom@iknl.nl>
|
|
7
|
+
License: MIT
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Requires-Dist: click==8.1.3
|
|
10
|
+
Requires-Dist: gevent==25.4.2
|
|
11
|
+
Requires-Dist: jinja2==3.1.6
|
|
12
|
+
Requires-Dist: kubernetes==28.1.0
|
|
13
|
+
Requires-Dist: nvidia-ml-py==12.535.133
|
|
14
|
+
Requires-Dist: parquet-tools==0.2.16
|
|
15
|
+
Requires-Dist: psutil==7.0.0
|
|
16
|
+
Requires-Dist: python-socketio==5.15.0
|
|
17
|
+
Requires-Dist: requests==2.33.1
|
|
18
|
+
Requires-Dist: vantage6-client==5.0.0
|
|
19
|
+
Requires-Dist: vantage6-common==5.0.0
|
|
20
|
+
Requires-Dist: vantage6==5.0.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: black; extra == 'dev'
|
|
23
|
+
Requires-Dist: coverage==7.10.2; extra == 'dev'
|
|
24
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
<h1 align="center">
|
|
28
|
+
<br>
|
|
29
|
+
<a href="https://vantage6.ai"><img src="https://github.com/IKNL/guidelines/blob/master/resources/logos/vantage6.png?raw=true" alt="vantage6" width="350"></a>
|
|
30
|
+
</h1>
|
|
31
|
+
|
|
32
|
+
<h3 align=center> A Privacy Enhancing Technology (PET) Operations platform</h3>
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
# Vantage6 Node
|
|
37
|
+
|
|
38
|
+
This package contains the Vantage6 node application.
|
|
39
|
+
|
|
40
|
+
## Documentation
|
|
41
|
+
|
|
42
|
+
For complete documentation, installation instructions, and usage examples, please see
|
|
43
|
+
the **[main Vantage6 README](https://github.com/vantage6/vantage6/blob/main/README.md)**
|
|
44
|
+
.
|
|
45
|
+
|
|
46
|
+
## About Vantage6
|
|
47
|
+
|
|
48
|
+
Vantage6 is a Privacy Enhancing Technology (PET) Operations platform that enables
|
|
49
|
+
federated learning and multi-party computation. For more information, visit
|
|
50
|
+
[vantage6.ai](https://vantage6.ai) or our [documentation](https://docs.vantage6.ai).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<a href="https://vantage6.ai"><img src="https://github.com/IKNL/guidelines/blob/master/resources/logos/vantage6.png?raw=true" alt="vantage6" width="350"></a>
|
|
4
|
+
</h1>
|
|
5
|
+
|
|
6
|
+
<h3 align=center> A Privacy Enhancing Technology (PET) Operations platform</h3>
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Vantage6 Node
|
|
11
|
+
|
|
12
|
+
This package contains the Vantage6 node application.
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
For complete documentation, installation instructions, and usage examples, please see
|
|
17
|
+
the **[main Vantage6 README](https://github.com/vantage6/vantage6/blob/main/README.md)**
|
|
18
|
+
.
|
|
19
|
+
|
|
20
|
+
## About Vantage6
|
|
21
|
+
|
|
22
|
+
Vantage6 is a Privacy Enhancing Technology (PET) Operations platform that enables
|
|
23
|
+
federated learning and multi-party computation. For more information, visit
|
|
24
|
+
[vantage6.ai](https://vantage6.ai) or our [documentation](https://docs.vantage6.ai).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# start a node for each config file the provided directory
|
|
4
|
+
|
|
5
|
+
config_dir=$1
|
|
6
|
+
if [ -z "$config_dir" ]; then
|
|
7
|
+
echo "Provide a configuration directory as argument"
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
# Remove trailing slashes from config_dir
|
|
12
|
+
config_dir=${config_dir%/}
|
|
13
|
+
|
|
14
|
+
for dir in $config_dir/*; do
|
|
15
|
+
if [ -d "$dir" ]; then
|
|
16
|
+
echo "Looking for node configurations in: $dir"
|
|
17
|
+
|
|
18
|
+
config=$(find "$dir" -maxdepth 1 -name "*.yaml" -type f)
|
|
19
|
+
dotenv_file="$dir"/.env
|
|
20
|
+
|
|
21
|
+
# Check if the config file exists
|
|
22
|
+
if [ ! -f "$config" ]; then
|
|
23
|
+
echo "No yaml config file found in $dir/*.yaml"
|
|
24
|
+
continue
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Check if the .env file exists
|
|
28
|
+
if [ ! -f "$dotenv_file" ]; then
|
|
29
|
+
echo "No .env file found in $dir/.env"
|
|
30
|
+
continue
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Source the .env file to set environment variables in their own shell as we
|
|
34
|
+
# start a new shell for each node
|
|
35
|
+
bash -c "source \"$dotenv_file\" && python /vantage6/vantage6-node/vantage6/dev_start.py \"$config\" &"
|
|
36
|
+
fi
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# For development purposes, we put infinite sleep here. This has the advantage that
|
|
40
|
+
# once the node crashes, the container will keep running and therefore, the error will
|
|
41
|
+
# remain visible in the logs. A restart of the container would obfuscate the error
|
|
42
|
+
# which should not happen in development.
|
|
43
|
+
sleep infinity
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vantage6-node"
|
|
7
|
+
version = "5.0.0"
|
|
8
|
+
description = "vantage6 node"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Vantage6 Team"}
|
|
13
|
+
]
|
|
14
|
+
maintainers = [
|
|
15
|
+
{name = "Frank Martin", email = "f.martin@iknl.nl"},
|
|
16
|
+
{name = "Bart van Beusekom", email = "b.vanbeusekom@iknl.nl"}
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.13"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"click==8.1.3",
|
|
21
|
+
"gevent==25.4.2",
|
|
22
|
+
"jinja2==3.1.6",
|
|
23
|
+
"kubernetes==28.1.0",
|
|
24
|
+
"nvidia-ml-py==12.535.133",
|
|
25
|
+
"parquet-tools==0.2.16",
|
|
26
|
+
"psutil==7.0.0",
|
|
27
|
+
"python-socketio==5.15.0",
|
|
28
|
+
"requests==2.33.1",
|
|
29
|
+
"vantage6==5.0.0",
|
|
30
|
+
"vantage6-client==5.0.0",
|
|
31
|
+
"vantage6-common==5.0.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"coverage==7.10.2",
|
|
37
|
+
"black",
|
|
38
|
+
"pre-commit",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
vnode-local = "vantage6.node.cli.node:cli_node"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["vantage6"]
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel.sources]
|
|
48
|
+
"vantage6" = "vantage6"
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
from kubernetes.client import (
|
|
5
|
+
V1ContainerState,
|
|
6
|
+
V1ContainerStateRunning,
|
|
7
|
+
V1ContainerStateTerminated,
|
|
8
|
+
V1ContainerStateWaiting,
|
|
9
|
+
V1ContainerStatus,
|
|
10
|
+
V1Pod,
|
|
11
|
+
V1PodCondition,
|
|
12
|
+
V1PodStatus,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from vantage6.common.enum import RunStatus
|
|
16
|
+
|
|
17
|
+
from vantage6.node.k8s.jobpod_state_to_run_status_mapper import (
|
|
18
|
+
compute_run_pod_status,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_null_logger(name="null_logger"):
|
|
23
|
+
logger = logging.getLogger(name)
|
|
24
|
+
logger.addHandler(logging.NullHandler())
|
|
25
|
+
logger.propagate = False
|
|
26
|
+
return logger
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TestPodStatus(unittest.TestCase):
|
|
30
|
+
def setUp(self):
|
|
31
|
+
self.silent_logger = get_null_logger()
|
|
32
|
+
|
|
33
|
+
self.running_container_state = V1ContainerState(
|
|
34
|
+
running=V1ContainerStateRunning(started_at="")
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
self.waiting_container_state = V1ContainerState(
|
|
38
|
+
waiting=V1ContainerStateWaiting(reason="", message="")
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
self.terminated_container_state = V1ContainerState(
|
|
42
|
+
terminated=V1ContainerStateTerminated(exit_code=0, reason="")
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
self.mock_container_status = V1ContainerStatus(
|
|
46
|
+
name="",
|
|
47
|
+
ready=True,
|
|
48
|
+
restart_count=1,
|
|
49
|
+
image="",
|
|
50
|
+
image_id="",
|
|
51
|
+
container_id="",
|
|
52
|
+
state=None, # use running/waiting/terminated_container_state here
|
|
53
|
+
last_state=None,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
self.mock_condition = V1PodCondition(type="", status="", reason="", message="")
|
|
57
|
+
|
|
58
|
+
self.mock_pod_status = V1PodStatus(
|
|
59
|
+
phase="",
|
|
60
|
+
reason="",
|
|
61
|
+
conditions=[self.mock_condition],
|
|
62
|
+
container_statuses=[self.mock_container_status],
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
self.mock_pod = V1Pod(metadata={"name": ""}, status=self.mock_pod_status)
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
def test_running_job_pod(self):
|
|
69
|
+
self.mock_pod.status.phase = "Running"
|
|
70
|
+
self.assertEqual(
|
|
71
|
+
compute_run_pod_status(
|
|
72
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
73
|
+
),
|
|
74
|
+
RunStatus.ACTIVE,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def test_container_status_not_yet_defined(self):
|
|
78
|
+
self.mock_pod.status.phase = "Pending"
|
|
79
|
+
self.mock_pod.status.container_statuses = None
|
|
80
|
+
self.assertEqual(
|
|
81
|
+
compute_run_pod_status(
|
|
82
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
83
|
+
),
|
|
84
|
+
RunStatus.INITIALIZING,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def test_container_related_err(self):
|
|
88
|
+
self.mock_pod.status.phase = "Pending"
|
|
89
|
+
self.mock_pod.status.container_statuses[0].state = self.waiting_container_state
|
|
90
|
+
self.mock_pod.status.container_statuses[
|
|
91
|
+
0
|
|
92
|
+
].state.waiting.reason = "ImagePullBackOff"
|
|
93
|
+
self.assertEqual(
|
|
94
|
+
compute_run_pod_status(
|
|
95
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
96
|
+
),
|
|
97
|
+
RunStatus.NO_DOCKER_IMAGE,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def test_waiting_reason_not_ready_err(self):
|
|
101
|
+
self.mock_pod.status.phase = "Pending"
|
|
102
|
+
self.mock_pod.status.container_statuses[0].state = self.waiting_container_state
|
|
103
|
+
self.mock_pod.status.container_statuses[0].state.waiting = None
|
|
104
|
+
self.assertEqual(
|
|
105
|
+
compute_run_pod_status(
|
|
106
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
107
|
+
),
|
|
108
|
+
RunStatus.INITIALIZING,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def test_container_runtime_error(self):
|
|
112
|
+
self.mock_pod.status.phase = "Pending"
|
|
113
|
+
self.mock_pod.status.container_statuses[0].state = self.waiting_container_state
|
|
114
|
+
self.mock_pod.status.container_statuses[
|
|
115
|
+
0
|
|
116
|
+
].state.waiting.reason = "CrashLoopBackOff"
|
|
117
|
+
self.assertEqual(
|
|
118
|
+
compute_run_pod_status(
|
|
119
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
120
|
+
),
|
|
121
|
+
RunStatus.CRASHED,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def test_completed_job(self):
|
|
125
|
+
self.mock_pod.status.phase = "Succeded"
|
|
126
|
+
self.assertEqual(
|
|
127
|
+
compute_run_pod_status(
|
|
128
|
+
log=self.silent_logger, task_namespace="", label="", pod=self.mock_pod
|
|
129
|
+
),
|
|
130
|
+
RunStatus.COMPLETED,
|
|
131
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from vantage6.cli.context.node import NodeContext
|
|
6
|
+
|
|
7
|
+
from vantage6.node import run
|
|
8
|
+
|
|
9
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
10
|
+
log = logging.getLogger("vantage6.dev_start")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def run_function(config):
|
|
14
|
+
if not config:
|
|
15
|
+
log.critical("No config provided.")
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
name = Path(config).stem
|
|
19
|
+
ctx = NodeContext(name, True, config, logger_prefix=f"{name} | ", in_container=True)
|
|
20
|
+
|
|
21
|
+
run(ctx)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
config_file = Path(sys.argv[1]) if len(sys.argv) > 1 else None
|
|
26
|
+
if not config_file:
|
|
27
|
+
log.critical("No config file provided.")
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
if not config_file.exists():
|
|
31
|
+
log.critical("Config file does not exist: %s", config_file)
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
log.info("Starting node with config: %s", config_file)
|
|
35
|
+
run_function(config_file)
|