kalavai-client 0.5.6__py2.py3-none-any.whl → 0.5.8__py2.py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- kalavai_client/__init__.py +1 -1
- kalavai_client/assets/docker-compose-template.yaml +89 -47
- kalavai_client/assets/nginx.conf +12 -0
- kalavai_client/cli.py +92 -78
- kalavai_client/cluster.py +26 -5
- kalavai_client/utils.py +3 -3
- {kalavai_client-0.5.6.dist-info → kalavai_client-0.5.8.dist-info}/METADATA +15 -4
- {kalavai_client-0.5.6.dist-info → kalavai_client-0.5.8.dist-info}/RECORD +11 -11
- kalavai_client/assets/vpn-template.yaml +0 -13
- {kalavai_client-0.5.6.dist-info → kalavai_client-0.5.8.dist-info}/LICENSE +0 -0
- {kalavai_client-0.5.6.dist-info → kalavai_client-0.5.8.dist-info}/WHEEL +0 -0
- {kalavai_client-0.5.6.dist-info → kalavai_client-0.5.8.dist-info}/entry_points.txt +0 -0
kalavai_client/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
|
2
|
-
__version__ = "0.5.
|
2
|
+
__version__ = "0.5.8"
|
@@ -1,53 +1,95 @@
|
|
1
1
|
services:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
{% if vpn %}
|
3
|
+
{{vpn_name}}:
|
4
|
+
image: gravitl/netclient:v0.30.0
|
5
|
+
container_name: {{vpn_name}}
|
6
|
+
cap_add:
|
7
|
+
- NET_ADMIN
|
8
|
+
- SYS_MODULE
|
9
|
+
network_mode: host
|
10
|
+
# networks:
|
11
|
+
# - custom-network
|
12
|
+
# ports:
|
13
|
+
# # https://docs.k3s.io/installation/requirements#inbound-rules-for-k3s-nodes
|
14
|
+
# - "6443:6443" # kube server
|
15
|
+
# - "10250:10250" # worker balancer
|
16
|
+
# - "8472:8472/udp" # flannel vxlan
|
17
|
+
# - "51820:51820/udp" # flannel wireguard
|
18
|
+
# {% if command == "server" %}
|
19
|
+
# - "30000-30500:30000-30500"
|
20
|
+
# {% endif %}
|
21
|
+
environment:
|
22
|
+
- HOST_NAME={{node_name}}
|
23
|
+
- IFACE_NAME={{flannel_iface}}
|
24
|
+
- PORT=51820
|
25
|
+
- TOKEN={{vpn_token}}
|
26
|
+
volumes:
|
27
|
+
- /dev/net/tun:/dev/net/tun
|
28
|
+
restart: unless-stopped
|
29
|
+
# nginx:
|
30
|
+
# image: nginx:latest
|
31
|
+
# ports:
|
32
|
+
# - "{{redirect_source_port}}:{{redirect_source_port}}"
|
33
|
+
# restart: unless-stopped
|
34
|
+
# networks:
|
35
|
+
# - custom-network
|
36
|
+
# volumes:
|
37
|
+
# - {{nginx_path}}/nginx.conf:/etc/nginx/nginx.conf
|
14
38
|
{% endif %}
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
{% else %}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
{% endif %}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
{%
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
{{service_name}}:
|
40
|
+
image: docker.io/bundenth/kalavai-runner:gpu-latest
|
41
|
+
container_name: {{service_name}}
|
42
|
+
{% if vpn %}
|
43
|
+
depends_on:
|
44
|
+
- {{vpn_name}}
|
45
|
+
network_mode: "service:{{vpn_name}}"
|
46
|
+
{% else %}
|
47
|
+
hostname: {{node_name}}
|
48
|
+
networks:
|
49
|
+
- custom-network
|
50
|
+
ports:
|
51
|
+
- "6443:6443" # kube server
|
52
|
+
- "10250:10250" # worker balancer
|
53
|
+
- "8472:8472" # flannel vxlan
|
54
|
+
- "51820:51820" # flannel wireguard
|
55
|
+
{% if command == "server" %}
|
56
|
+
- "30000-30500:30000-30500"
|
57
|
+
{% endif %}
|
58
|
+
{% endif %}
|
59
|
+
privileged: true
|
60
|
+
restart: unless-stopped
|
61
|
+
command: >
|
62
|
+
--command={{command}}
|
63
|
+
{% if command == "server" %}
|
64
|
+
--port_range="30000-30500"
|
65
|
+
{% else %}
|
66
|
+
--server_ip={{pool_ip}}
|
67
|
+
--token={{pool_token}}
|
68
|
+
{% endif %}
|
69
|
+
{%if vpn %}
|
70
|
+
--flannel_iface={{flannel_iface}}
|
71
|
+
{% endif %}
|
72
|
+
{% if num_gpus and num_gpus > 0 %}
|
73
|
+
--gpu=on
|
74
|
+
{% else %}
|
75
|
+
--gpu=off
|
76
|
+
{% endif %}
|
77
|
+
{% if node_labels %}
|
78
|
+
--extra="{{node_labels}}"
|
79
|
+
{% endif %}
|
80
|
+
|
81
|
+
volumes:
|
82
|
+
- {{k3s_path}}:/var/lib/rancher/k3s # Persist data
|
83
|
+
- {{etc_path}}:/etc/rancher/k3s # Config files
|
84
|
+
|
43
85
|
{% if num_gpus and num_gpus > 0 %}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
86
|
+
deploy:
|
87
|
+
resources:
|
88
|
+
reservations:
|
89
|
+
devices:
|
90
|
+
- driver: nvidia
|
91
|
+
count: {{num_gpus}}
|
92
|
+
capabilities: [gpu]
|
51
93
|
{% endif %}
|
52
94
|
|
53
95
|
networks:
|
kalavai_client/cli.py
CHANGED
@@ -31,6 +31,7 @@ from kalavai_client.utils import (
|
|
31
31
|
safe_remove,
|
32
32
|
leave_vpn,
|
33
33
|
join_vpn,
|
34
|
+
get_vpn_details,
|
34
35
|
load_server_info,
|
35
36
|
user_login,
|
36
37
|
user_logout,
|
@@ -81,15 +82,17 @@ STORAGE_ACCESS_MODE = ["ReadWriteOnce"]
|
|
81
82
|
STORAGE_CLASS_LABEL = "kalavai.storage.enabled"
|
82
83
|
DEFAULT_STORAGE_NAME = "pool-cache"
|
83
84
|
DEFAULT_STORAGE_SIZE = 20
|
85
|
+
DEFAULT_WATCHER_PORT = 30001
|
84
86
|
USER_NODE_LABEL = "kalavai.cluster.user"
|
85
87
|
KUBE_VERSION = os.getenv("KALAVAI_KUBE_VERSION", "v1.31.1+k3s1")
|
86
|
-
DEFAULT_FLANNEL_IFACE = os.getenv("KALAVAI_FLANNEL_IFACE", "netmaker")
|
88
|
+
DEFAULT_FLANNEL_IFACE = os.getenv("KALAVAI_FLANNEL_IFACE", "netmaker-1")
|
87
89
|
FORBIDEDEN_IPS = ["127.0.0.1"]
|
88
90
|
# kalavai templates
|
89
91
|
HELM_APPS_FILE = resource_path("kalavai_client/assets/apps.yaml")
|
90
92
|
HELM_APPS_VALUES = resource_path("kalavai_client/assets/apps_values.yaml")
|
91
93
|
# user specific config files
|
92
|
-
DEFAULT_CONTAINER_NAME = "kalavai
|
94
|
+
DEFAULT_CONTAINER_NAME = "kalavai"
|
95
|
+
DEFAULT_VPN_CONTAINER_NAME = "kalavai-vpn"
|
93
96
|
CONTAINER_HOST_PATH = user_path("pool/", create_path=True)
|
94
97
|
USER_COMPOSE_FILE = user_path("docker-compose-worker.yaml")
|
95
98
|
USER_VPN_COMPOSE_FILE = user_path("docker-compose-vpn.yaml")
|
@@ -130,7 +133,7 @@ def check_vpn_compatibility():
|
|
130
133
|
logs.append(" MacOS: https://docs.netmaker.io/docs/netclient#mac\n")
|
131
134
|
|
132
135
|
if len(logs) == 0:
|
133
|
-
console.log("[green]System is ready to join
|
136
|
+
console.log("[green]System is ready to join the vpn")
|
134
137
|
return True
|
135
138
|
else:
|
136
139
|
for log in logs:
|
@@ -179,16 +182,6 @@ def check_worker_compatibility():
|
|
179
182
|
|
180
183
|
|
181
184
|
def cleanup_local():
|
182
|
-
# disconnect from private network
|
183
|
-
console.log("Disconnecting from VPN...")
|
184
|
-
try:
|
185
|
-
vpns = leave_vpn()
|
186
|
-
if vpns is not None:
|
187
|
-
for vpn in vpns:
|
188
|
-
console.log(f"You have left {vpn} VPN")
|
189
|
-
except:
|
190
|
-
# no vpn
|
191
|
-
pass
|
192
185
|
console.log("Removing local cache files...")
|
193
186
|
safe_remove(CONTAINER_HOST_PATH)
|
194
187
|
safe_remove(USER_COMPOSE_FILE)
|
@@ -365,7 +358,7 @@ def select_token_type():
|
|
365
358
|
break
|
366
359
|
return {"admin": choice == 0, "user": choice == 1, "worker": choice == 2}
|
367
360
|
|
368
|
-
def generate_compose_config(role, node_name,
|
361
|
+
def generate_compose_config(role, node_name, node_labels, is_public, pool_ip=None, vpn_token=None, pool_token=None):
|
369
362
|
num_gpus = 0
|
370
363
|
try:
|
371
364
|
has_gpus = check_gpu_drivers()
|
@@ -380,17 +373,19 @@ def generate_compose_config(role, node_name, ip_address, node_labels, is_public,
|
|
380
373
|
compose_values = {
|
381
374
|
"user_path": user_path(""),
|
382
375
|
"service_name": DEFAULT_CONTAINER_NAME,
|
383
|
-
"
|
384
|
-
"
|
385
|
-
"
|
376
|
+
"vpn": is_public,
|
377
|
+
"vpn_name": DEFAULT_VPN_CONTAINER_NAME,
|
378
|
+
"pool_ip": pool_ip,
|
379
|
+
"pool_token": pool_token,
|
380
|
+
"vpn_token": vpn_token,
|
381
|
+
"node_name": node_name,
|
386
382
|
"command": role,
|
387
383
|
"storage_enabled": "True",
|
388
|
-
"ip_address": ip_address,
|
389
384
|
"num_gpus": num_gpus,
|
390
385
|
"k3s_path": f"{CONTAINER_HOST_PATH}/k3s",
|
391
386
|
"etc_path": f"{CONTAINER_HOST_PATH}/etc",
|
392
387
|
"node_labels": " ".join([f"--node-label {key}={value}" for key, value in node_labels.items()]),
|
393
|
-
"flannel_iface": DEFAULT_FLANNEL_IFACE if is_public else
|
388
|
+
"flannel_iface": DEFAULT_FLANNEL_IFACE if is_public else ""
|
394
389
|
}
|
395
390
|
# generate local config files
|
396
391
|
compose_yaml = load_template(
|
@@ -585,35 +580,56 @@ def pool__start(cluster_name, *others, only_registered_users: bool=False, ip_ad
|
|
585
580
|
STORAGE_CLASS_LABEL: is_storage_compatible()
|
586
581
|
}
|
587
582
|
if location is not None:
|
588
|
-
console.log("
|
583
|
+
console.log("Fetching VPN credentials")
|
589
584
|
try:
|
590
|
-
|
591
|
-
return
|
592
|
-
vpn = join_vpn(
|
585
|
+
vpn = get_vpn_details(
|
593
586
|
location=location,
|
594
587
|
user_cookie=USER_COOKIE)
|
595
588
|
node_labels[USER_NODE_LABEL] = user["username"]
|
596
589
|
except Exception as e:
|
597
590
|
console.log(f"[red]Error when joining network: {str(e)}")
|
598
591
|
return
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
592
|
+
|
593
|
+
# Generate docker compose recipe
|
594
|
+
generate_compose_config(
|
595
|
+
role="server",
|
596
|
+
vpn_token=vpn["key"],
|
597
|
+
node_name=socket.gethostname(),
|
598
|
+
node_labels=node_labels,
|
599
|
+
is_public=location is not None
|
600
|
+
)
|
601
|
+
|
602
|
+
# start server
|
603
|
+
console.log("Deploying seed...")
|
604
|
+
CLUSTER.start_seed_node()
|
605
|
+
|
606
|
+
while not CLUSTER.is_agent_running():
|
607
|
+
console.log("Waiting for seed to start...")
|
608
|
+
time.sleep(10)
|
609
|
+
|
610
|
+
# select IP address (for external discovery)
|
611
|
+
if ip_address is None and location is None:
|
612
|
+
# local IP
|
613
|
+
console.log(f"Scanning for valid IPs")
|
614
|
+
ip_address = select_ip_address()
|
615
|
+
else:
|
616
|
+
# load VPN ip
|
617
|
+
ip_address = CLUSTER.get_vpn_ip()
|
603
618
|
console.log(f"Using {ip_address} address for server")
|
604
619
|
|
620
|
+
# populate local cred files
|
605
621
|
auth_key = str(uuid.uuid4())
|
606
622
|
write_auth_key = str(uuid.uuid4())
|
607
623
|
readonly_auth_key = str(uuid.uuid4())
|
608
|
-
|
609
|
-
watcher_service = f"{ip_address}:{
|
624
|
+
|
625
|
+
watcher_service = f"{ip_address}:{DEFAULT_WATCHER_PORT}"
|
610
626
|
values = {
|
611
627
|
CLUSTER_NAME_KEY: cluster_name,
|
612
628
|
CLUSTER_IP_KEY: ip_address,
|
613
629
|
AUTH_KEY: auth_key,
|
614
630
|
READONLY_AUTH_KEY: readonly_auth_key,
|
615
631
|
WRITE_AUTH_KEY: write_auth_key,
|
616
|
-
WATCHER_PORT_KEY:
|
632
|
+
WATCHER_PORT_KEY: DEFAULT_WATCHER_PORT,
|
617
633
|
WATCHER_SERVICE_KEY: watcher_service,
|
618
634
|
USER_NODE_LABEL_KEY: USER_NODE_LABEL,
|
619
635
|
ALLOW_UNREGISTERED_USER_KEY: not only_registered_users
|
@@ -630,15 +646,6 @@ def pool__start(cluster_name, *others, only_registered_users: bool=False, ip_ad
|
|
630
646
|
cluster_name=cluster_name,
|
631
647
|
public_location=location,
|
632
648
|
user_api_key=user["api_key"])
|
633
|
-
|
634
|
-
# 1. Generate docker compose recipe
|
635
|
-
compose_yaml = generate_compose_config(
|
636
|
-
role="server",
|
637
|
-
node_name=socket.gethostname(),
|
638
|
-
ip_address=ip_address,
|
639
|
-
node_labels=node_labels,
|
640
|
-
is_public=location is not None
|
641
|
-
)
|
642
649
|
|
643
650
|
# Generate helmfile recipe
|
644
651
|
helm_yaml = load_template(
|
@@ -650,14 +657,6 @@ def pool__start(cluster_name, *others, only_registered_users: bool=False, ip_ad
|
|
650
657
|
f.write(helm_yaml)
|
651
658
|
|
652
659
|
console.log("[green]Config files have been generated in your local machine\n")
|
653
|
-
|
654
|
-
# # 1. start server
|
655
|
-
console.log("Deploying seed...")
|
656
|
-
CLUSTER.start_seed_node()
|
657
|
-
|
658
|
-
while not CLUSTER.is_agent_running():
|
659
|
-
console.log("Waiting for seed to start...")
|
660
|
-
time.sleep(10)
|
661
660
|
|
662
661
|
console.log("Setting pool dependencies...")
|
663
662
|
# set template values in helmfile
|
@@ -691,7 +690,6 @@ def pool__start(cluster_name, *others, only_registered_users: bool=False, ip_ad
|
|
691
690
|
|
692
691
|
return None
|
693
692
|
|
694
|
-
|
695
693
|
@arguably.command
|
696
694
|
def pool__token(*others, admin=False, user=False, worker=False):
|
697
695
|
"""
|
@@ -773,6 +771,7 @@ def pool__join(token, *others, node_name=None, ip_address: str=None):
|
|
773
771
|
if CLUSTER.is_agent_running():
|
774
772
|
console.log(f"[white] You are already connected to {load_server_info(data_key=CLUSTER_NAME_KEY, file=USER_LOCAL_SERVER_FILE)}. Enter [yellow]kalavai pool stop[white] to exit and join another one.")
|
775
773
|
return
|
774
|
+
|
776
775
|
# check that is not attached to another instance
|
777
776
|
if os.path.exists(USER_LOCAL_SERVER_FILE):
|
778
777
|
option = user_confirm(
|
@@ -810,20 +809,20 @@ def pool__join(token, *others, node_name=None, ip_address: str=None):
|
|
810
809
|
}
|
811
810
|
user = defaultdict(lambda: None)
|
812
811
|
if public_location is not None:
|
813
|
-
|
812
|
+
user = user_login(user_cookie=USER_COOKIE)
|
813
|
+
if user is None:
|
814
|
+
console.log("[red]Must be logged in to join public pools. Run [yellow]kalavai login[red] to authenticate")
|
815
|
+
exit()
|
816
|
+
console.log("Fetching VPN credentials")
|
814
817
|
try:
|
815
|
-
|
816
|
-
return
|
817
|
-
vpn = join_vpn(
|
818
|
+
vpn = get_vpn_details(
|
818
819
|
location=public_location,
|
819
820
|
user_cookie=USER_COOKIE)
|
820
|
-
user = user_login(user_cookie=USER_COOKIE)
|
821
821
|
node_labels[USER_NODE_LABEL] = user["username"]
|
822
822
|
except Exception as e:
|
823
823
|
console.log(f"[red]Error when joining network: {str(e)}")
|
824
824
|
console.log("Are you authenticated? Try [yellow]kalavai login")
|
825
825
|
return
|
826
|
-
# validate public seed
|
827
826
|
try:
|
828
827
|
validate_join_public_seed(
|
829
828
|
cluster_name=cluster_name,
|
@@ -832,31 +831,29 @@ def pool__join(token, *others, node_name=None, ip_address: str=None):
|
|
832
831
|
)
|
833
832
|
except Exception as e:
|
834
833
|
console.log(f"[red]Error when joining network: {str(e)}")
|
835
|
-
leave_vpn(vpn_file=USER_VPN_COMPOSE_FILE)
|
836
834
|
return
|
837
835
|
|
838
836
|
# send note to server to let them know the node is coming online
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
if ip_address is None:
|
845
|
-
console.log(f"Scanning for valid IPs (subnet {vpn['subnet']})...")
|
846
|
-
ip_address = select_ip_address(subnet=vpn["subnet"])
|
847
|
-
console.log(f"Using {ip_address} address for worker")
|
837
|
+
# TODO: won't be able to check for VPN pools...
|
838
|
+
# if not pre_join_check(node_name=node_name, server_url=watcher_service, server_key=auth_key):
|
839
|
+
# console.log(f"[red] Failed pre join checks. Server offline or node '{node_name}' may already exist. Please specify a different one with '--node-name'")
|
840
|
+
# leave_vpn(container_name=DEFAULT_VPN_CONTAINER_NAME)
|
841
|
+
# return
|
848
842
|
|
849
843
|
# local agent join
|
850
844
|
# 1. Generate local cache files
|
851
845
|
console.log("Generating config files...")
|
852
|
-
|
846
|
+
|
847
|
+
# Generate docker compose recipe
|
848
|
+
generate_compose_config(
|
853
849
|
role="agent",
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
850
|
+
pool_ip=f"https://{kalavai_seed_ip}:6443",
|
851
|
+
pool_token=kalavai_token,
|
852
|
+
vpn_token=vpn["key"],
|
853
|
+
node_name=node_name,
|
858
854
|
node_labels=node_labels,
|
859
855
|
is_public=public_location is not None)
|
856
|
+
|
860
857
|
store_server_info(
|
861
858
|
server_ip=kalavai_seed_ip,
|
862
859
|
auth_key=auth_key,
|
@@ -866,8 +863,6 @@ def pool__join(token, *others, node_name=None, ip_address: str=None):
|
|
866
863
|
cluster_name=cluster_name,
|
867
864
|
public_location=public_location,
|
868
865
|
user_api_key=user["api_key"])
|
869
|
-
|
870
|
-
init_user_workspace()
|
871
866
|
|
872
867
|
option = user_confirm(
|
873
868
|
question="Docker compose ready. Would you like Kalavai to deploy it?",
|
@@ -883,18 +878,23 @@ def pool__join(token, *others, node_name=None, ip_address: str=None):
|
|
883
878
|
CLUSTER.start_worker_node()
|
884
879
|
except Exception as e:
|
885
880
|
console.log(f"[red] Error connecting to {cluster_name} @ {kalavai_seed_ip}. Check with the admin if the token is still valid.")
|
886
|
-
leave_vpn(
|
881
|
+
leave_vpn(container_name=DEFAULT_VPN_CONTAINER_NAME)
|
887
882
|
exit()
|
888
883
|
|
889
|
-
|
890
|
-
|
891
|
-
|
884
|
+
# ensure we are connected
|
885
|
+
while True:
|
886
|
+
console.log("Waiting for core services to be ready, may take a few minutes...")
|
887
|
+
time.sleep(30)
|
888
|
+
if is_watcher_alive(server_creds=USER_LOCAL_SERVER_FILE, user_cookie=USER_COOKIE):
|
889
|
+
break
|
890
|
+
|
891
|
+
init_user_workspace()
|
892
892
|
|
893
893
|
# set status to schedulable
|
894
894
|
console.log(f"[green] You are connected to {cluster_name}")
|
895
895
|
|
896
896
|
@arguably.command
|
897
|
-
def pool__stop(*others):
|
897
|
+
def pool__stop(*others, skip_node_deletion=False):
|
898
898
|
"""
|
899
899
|
Stop sharing your device and clean up. DO THIS ONLY IF YOU WANT TO REMOVE KALAVAI-CLIENT from your device.
|
900
900
|
|
@@ -903,7 +903,8 @@ def pool__stop(*others):
|
|
903
903
|
"""
|
904
904
|
console.log("[white] Stopping kalavai app...")
|
905
905
|
# delete local node from server
|
906
|
-
|
906
|
+
if not skip_node_deletion:
|
907
|
+
node__delete(load_server_info(data_key=NODE_NAME_KEY, file=USER_LOCAL_SERVER_FILE))
|
907
908
|
# unpublish event (only if seed node)
|
908
909
|
# TODO: no, this should be done via the platform!!!
|
909
910
|
# try:
|
@@ -916,7 +917,20 @@ def pool__stop(*others):
|
|
916
917
|
# console.log(f"[red][WARNING]: (ignore if not a public pool) Error when unpublishing cluster. {str(e)}")
|
917
918
|
# remove local node agent
|
918
919
|
console.log("Removing agent and local cache")
|
920
|
+
|
921
|
+
# disconnect from VPN first, then remove agent, then remove local files
|
922
|
+
console.log("Disconnecting from VPN...")
|
923
|
+
try:
|
924
|
+
vpns = leave_vpn(container_name=DEFAULT_VPN_CONTAINER_NAME)
|
925
|
+
if vpns is not None:
|
926
|
+
for vpn in vpns:
|
927
|
+
console.log(f"You have left {vpn} VPN")
|
928
|
+
except:
|
929
|
+
# no vpn
|
930
|
+
pass
|
931
|
+
|
919
932
|
CLUSTER.remove_agent()
|
933
|
+
|
920
934
|
# clean local files
|
921
935
|
cleanup_local()
|
922
936
|
console.log("[white] Kalavai has stopped sharing your resources. Use [yellow]kalavai pool start[white] or [yellow]kalavai pool join[white] to start again!")
|
@@ -1151,7 +1165,7 @@ def pool__attach(token, *others, node_name=None):
|
|
1151
1165
|
)
|
1152
1166
|
except Exception as e:
|
1153
1167
|
console.log(f"[red]Error when joining network: {str(e)}")
|
1154
|
-
leave_vpn(
|
1168
|
+
leave_vpn(container_name=DEFAULT_VPN_CONTAINER_NAME)
|
1155
1169
|
return
|
1156
1170
|
|
1157
1171
|
store_server_info(
|
kalavai_client/cluster.py
CHANGED
@@ -7,7 +7,8 @@ from kalavai_client.utils import (
|
|
7
7
|
run_cmd,
|
8
8
|
check_gpu_drivers,
|
9
9
|
validate_poolconfig,
|
10
|
-
user_path
|
10
|
+
user_path,
|
11
|
+
populate_template
|
11
12
|
)
|
12
13
|
|
13
14
|
|
@@ -20,6 +21,9 @@ class Cluster(ABC):
|
|
20
21
|
def start_worker_node(self, url, token, node_name, auth_key, watcher_service, ip_address, labels, flannel_iface):
|
21
22
|
raise NotImplementedError()
|
22
23
|
|
24
|
+
@abstractmethod
|
25
|
+
def get_vpn_ip(self):
|
26
|
+
raise NotImplementedError()
|
23
27
|
|
24
28
|
@abstractmethod
|
25
29
|
def update_dependencies(self, dependencies_files):
|
@@ -79,11 +83,23 @@ class dockerCluster(Cluster):
|
|
79
83
|
def start_seed_node(self):
|
80
84
|
|
81
85
|
run_cmd(f"docker compose -f {self.compose_file} up -d")
|
82
|
-
|
83
|
-
|
86
|
+
# wait for container to be setup
|
87
|
+
while True:
|
88
|
+
try:
|
89
|
+
run_cmd(f"docker cp {self.container_name}:/etc/rancher/k3s/k3s.yaml {self.kubeconfig_file} >/dev/null 2>&1")
|
90
|
+
break
|
91
|
+
except:
|
92
|
+
pass
|
93
|
+
time.sleep(5)
|
84
94
|
|
85
95
|
def start_worker_node(self):
|
86
96
|
run_cmd(f"docker compose -f {self.compose_file} up -d")
|
97
|
+
|
98
|
+
def get_vpn_ip(self):
|
99
|
+
command = populate_template(
|
100
|
+
template_str="docker exec -it {{container_name}} ifconfig {{iface_name}} | grep 'inet ' | awk '{gsub(/^addr:/, \"\", $2); print $2}'",
|
101
|
+
values_dict={"container_name": self.container_name, "iface_name": self.default_flannel_iface})
|
102
|
+
return run_cmd(command).decode().strip()
|
87
103
|
|
88
104
|
|
89
105
|
def update_dependencies(self, dependencies_file=None, debug=False, retries=3):
|
@@ -122,8 +138,13 @@ class dockerCluster(Cluster):
|
|
122
138
|
def is_seed_node(self):
|
123
139
|
if not os.path.isfile(self.compose_file):
|
124
140
|
return False
|
125
|
-
|
126
|
-
|
141
|
+
if not self.is_agent_running():
|
142
|
+
return False
|
143
|
+
try:
|
144
|
+
run_cmd(f"docker container exec {self.container_name} cat /var/lib/rancher/k3s/server/node-token >/dev/null 2>&1")
|
145
|
+
return True
|
146
|
+
except:
|
147
|
+
return False
|
127
148
|
|
128
149
|
def is_cluster_init(self):
|
129
150
|
if not os.path.isfile(self.compose_file):
|
kalavai_client/utils.py
CHANGED
@@ -241,12 +241,12 @@ def join_vpn(location, user_cookie):
|
|
241
241
|
run_cmd(f"sudo netclient join -t {token} >/dev/null 2>&1")
|
242
242
|
return vpn
|
243
243
|
|
244
|
-
def leave_vpn():
|
244
|
+
def leave_vpn(container_name):
|
245
245
|
try:
|
246
|
-
vpns = json.loads(run_cmd("
|
246
|
+
vpns = json.loads(run_cmd(f"docker exec {container_name} netclient list").decode())
|
247
247
|
left_vpns = [vpn['network'] for vpn in vpns]
|
248
248
|
for vpn in left_vpns:
|
249
|
-
run_cmd(f"
|
249
|
+
run_cmd(f"docker exec {container_name} netclient leave {vpn}")
|
250
250
|
return left_vpns
|
251
251
|
except:
|
252
252
|
return None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: kalavai-client
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.8
|
4
4
|
Summary: Client app for kalavai platform
|
5
5
|
License: Apache-2.0
|
6
6
|
Keywords: LLM,platform
|
@@ -35,7 +35,7 @@ Requires-Dist: pyinstaller (==6.5.0) ; extra == "dev"
|
|
35
35
|
Requires-Dist: pyyaml (==6.0.2)
|
36
36
|
Requires-Dist: requests (>=2.25)
|
37
37
|
Requires-Dist: rich (==13.7.1)
|
38
|
-
Requires-Dist: setuptools (>
|
38
|
+
Requires-Dist: setuptools (>75.0.0)
|
39
39
|
Requires-Dist: twine ; extra == "dev"
|
40
40
|
Project-URL: Homepage, https://platform.kalavai.net
|
41
41
|
Project-URL: Website, https://kalavai.net
|
@@ -156,6 +156,16 @@ Make sure you also install python3-dev package. For ubuntu distros:
|
|
156
156
|
sudo apt install python3-dev
|
157
157
|
```
|
158
158
|
|
159
|
+
If you see:
|
160
|
+
```bash
|
161
|
+
AttributeError: install_layout. Did you mean: 'install_platlib'?
|
162
|
+
[end of output]
|
163
|
+
```
|
164
|
+
|
165
|
+
Upgrade your setuptools:
|
166
|
+
```bash
|
167
|
+
pip install -U setuptools
|
168
|
+
```
|
159
169
|
|
160
170
|
### Install the client
|
161
171
|
|
@@ -270,10 +280,11 @@ Python version <= 3.12.
|
|
270
280
|
```bash
|
271
281
|
sudo add-apt-repository ppa:deadsnakes/ppa
|
272
282
|
sudo apt update
|
273
|
-
sudo apt install python3.10 python3.10-dev
|
283
|
+
sudo apt install python3.10 python3.10-dev python3-virtualenv
|
274
284
|
virtualenv -p python3.10 env
|
275
285
|
source env/bin/activate
|
276
286
|
sudo apt install python3.10-venv python3.10-dev -y
|
287
|
+
pip install -U setuptools
|
277
288
|
pip install -e .[dev]
|
278
289
|
```
|
279
290
|
|
@@ -291,4 +302,4 @@ To run the unit tests, use:
|
|
291
302
|
python -m unittest
|
292
303
|
```
|
293
304
|
|
294
|
-
|
305
|
+
docker run --rm --net=host -v /root/.cache/kalavai/:/root/.cache/kalavai/ ghcr.io/helmfile/helmfile:v0.169.2 helmfile sync --file /root/.cache/kalavai/apps.yaml --kubeconfig /root/.cache/kalavai/kubeconfig
|
@@ -1,20 +1,20 @@
|
|
1
|
-
kalavai_client/__init__.py,sha256=
|
1
|
+
kalavai_client/__init__.py,sha256=SuLMwCDdGYDZgqjgKKaG_BDLw6Dn51HOAfdQVLphtOM,22
|
2
2
|
kalavai_client/__main__.py,sha256=WQUfxvRsBJH5gsCJg8pLz95QnZIj7Ol8psTO77m0QE0,73
|
3
3
|
kalavai_client/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
kalavai_client/assets/apps.yaml,sha256=aW9wKyvZhZFMHzBkZOsgVq-kpntED6U8B9XoHkm5F9Y,5963
|
5
5
|
kalavai_client/assets/apps_values.yaml,sha256=CjKVelPQHd-hm-DTMEuya92feKiphU9mh3HrosLYYPE,1676
|
6
|
-
kalavai_client/assets/docker-compose-template.yaml,sha256=
|
6
|
+
kalavai_client/assets/docker-compose-template.yaml,sha256=vZCxPemiKlAGW9ROZIzwUiPc1hHHBHD_08ULGS0Iw20,2459
|
7
|
+
kalavai_client/assets/nginx.conf,sha256=drVVCg8GHucz7hmt_BI6giAhK92OV71257NTs3LthwM,225
|
7
8
|
kalavai_client/assets/pool_config_template.yaml,sha256=fFz4w2-fMKD5KvyzFdfcWD_jSneRlmnjLc8hCctweX0,576
|
8
9
|
kalavai_client/assets/pool_config_values.yaml,sha256=VrM3XHQfQo6QLZ68qvagooUptaYgl1pszniY_JUtemk,233
|
9
10
|
kalavai_client/assets/user_workspace.yaml,sha256=wDvlMYknOPABAEo0dsQwU7bac8iubjAG9tdkFbJZ5Go,476
|
10
11
|
kalavai_client/assets/user_workspace_values.yaml,sha256=G0HOzQUxrDMCwuW9kbWUZaKMzDDPVwDwzBHCL2Xi2ZM,542
|
11
|
-
kalavai_client/assets/vpn-template.yaml,sha256=Hm7sevtrsakSxSKMJwl68hzOEWCaxwYytwkTgKhe_MM,397
|
12
12
|
kalavai_client/auth.py,sha256=QsBh28L2LwjBBK6pTUE4Xu36lLDTyetyU1YfS1Hbb6g,1717
|
13
|
-
kalavai_client/cli.py,sha256=
|
14
|
-
kalavai_client/cluster.py,sha256=
|
15
|
-
kalavai_client/utils.py,sha256=
|
16
|
-
kalavai_client-0.5.
|
17
|
-
kalavai_client-0.5.
|
18
|
-
kalavai_client-0.5.
|
19
|
-
kalavai_client-0.5.
|
20
|
-
kalavai_client-0.5.
|
13
|
+
kalavai_client/cli.py,sha256=Ab93qYKnKY-GPHKu5YPkobaoLQVyoX3483UKMn6PqVY,68374
|
14
|
+
kalavai_client/cluster.py,sha256=fULTAad4KXEGeWZmp4_VBoBwT5eED_HOBUsXIKmf0CU,12119
|
15
|
+
kalavai_client/utils.py,sha256=NOORAsRs9A84w8yyvhGwXcvshyZyf5wj86HT4HPzOcI,12405
|
16
|
+
kalavai_client-0.5.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
17
|
+
kalavai_client-0.5.8.dist-info/METADATA,sha256=B8hc4nvqsW5uBa-Jm-vCG3Ln58xfxqwKqWYUVFvsRMw,13013
|
18
|
+
kalavai_client-0.5.8.dist-info/WHEEL,sha256=_GR1VF9XYsw6EE9ATkyto4e6vRiOUBshR1STiZ5m1gE,92
|
19
|
+
kalavai_client-0.5.8.dist-info/entry_points.txt,sha256=9T6D45gxwzfVbglMm1r6XPdXuuZdHfy_7fCeu2jUphc,50
|
20
|
+
kalavai_client-0.5.8.dist-info/RECORD,,
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# https://docs.netmaker.io/docs/netclient#docker
|
2
|
-
services:
|
3
|
-
{{service_name}}:
|
4
|
-
network_mode: host
|
5
|
-
privileged: true
|
6
|
-
restart: always
|
7
|
-
environment:
|
8
|
-
- TOKEN={{vpn_token}}
|
9
|
-
- IFACE_NAME={{flannel_iface}}
|
10
|
-
volumes:
|
11
|
-
- '{{etc_path}}/netclient:/etc/netclient'
|
12
|
-
container_name: {{service_name}}
|
13
|
-
image: 'gravitl/netclient:latest'
|
File without changes
|
File without changes
|
File without changes
|