Skip to content

Commit 03f6358

Browse files
author
Ruslan Gainutdinov
committed
feat: clusters api
1 parent 41f331f commit 03f6358

File tree

5 files changed

+125
-116
lines changed

5 files changed

+125
-116
lines changed

examples/clusters_example.py

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import os
1414

1515
from verda import VerdaClient
16-
from verda.constants import Locations
16+
from verda.constants import Actions, Locations
1717

1818
# Get credentials from environment variables
1919
CLIENT_ID = os.environ.get('VERDA_CLIENT_ID')
@@ -30,20 +30,21 @@ def create_cluster_example():
3030

3131
# Create a cluster with 3 nodes
3232
cluster = verda.clusters.create(
33-
name='my-compute-cluster',
34-
instance_type='8V100.48V',
35-
node_count=3,
36-
image='ubuntu-24.04-cuda-12.8-open-docker',
33+
hostname='my-compute-cluster',
34+
cluster_type='16H200',
35+
image='ubuntu-22.04-cuda-12.4-cluster',
3736
description='Example compute cluster for distributed training',
3837
ssh_key_ids=ssh_keys,
3938
location=Locations.FIN_03,
39+
shared_volume_name='my-shared-volume',
40+
shared_volume_size=30000,
4041
)
4142

4243
print(f'Created cluster: {cluster.id}')
43-
print(f'Cluster name: {cluster.name}')
44+
print(f'Cluster hostname: {cluster.hostname}')
4445
print(f'Cluster status: {cluster.status}')
45-
print(f'Number of nodes: {cluster.node_count}')
46-
print(f'Instance type: {cluster.instance_type}')
46+
print(f'Cluster cluster_type: {cluster.cluster_type}')
47+
print(f'Cluster worker_nodes: {cluster.worker_nodes}')
4748
print(f'Location: {cluster.location}')
4849

4950
return cluster
@@ -56,7 +57,9 @@ def list_clusters_example():
5657

5758
print(f'\nFound {len(clusters)} cluster(s):')
5859
for cluster in clusters:
59-
print(f' - {cluster.name} ({cluster.id}): {cluster.status} - {cluster.node_count} nodes')
60+
print(
61+
f' - {cluster.hostname} ({cluster.id}): {cluster.status} - {len(cluster.worker_nodes)} nodes'
62+
)
6063

6164
# Get clusters with specific status
6265
running_clusters = verda.clusters.get(status=verda.constants.cluster_status.RUNNING)
@@ -71,45 +74,13 @@ def get_cluster_by_id_example(cluster_id: str):
7174

7275
print('\nCluster details:')
7376
print(f' ID: {cluster.id}')
74-
print(f' Name: {cluster.name}')
77+
print(f' Name: {cluster.hostname}')
7578
print(f' Description: {cluster.description}')
7679
print(f' Status: {cluster.status}')
77-
print(f' Instance type: {cluster.instance_type}')
78-
print(f' Node count: {cluster.node_count}')
80+
print(f' Cluster type: {cluster.cluster_type}')
7981
print(f' Created at: {cluster.created_at}')
80-
if cluster.master_ip:
81-
print(f' Master IP: {cluster.master_ip}')
82-
if cluster.endpoint:
83-
print(f' Endpoint: {cluster.endpoint}')
84-
85-
return cluster
86-
87-
88-
def get_cluster_nodes_example(cluster_id: str):
89-
"""Get all nodes in a cluster."""
90-
nodes = verda.clusters.get_nodes(cluster_id)
91-
92-
print(f'\nCluster has {len(nodes)} node(s):')
93-
for i, node in enumerate(nodes, 1):
94-
print(f'\n Node {i}:')
95-
print(f' ID: {node.id}')
96-
print(f' Hostname: {node.hostname}')
97-
print(f' Status: {node.status}')
98-
print(f' IP: {node.ip}')
99-
print(f' Instance type: {node.instance_type}')
100-
101-
return nodes
102-
103-
104-
def scale_cluster_example(cluster_id: str, new_node_count: int):
105-
"""Scale a cluster to a new number of nodes."""
106-
print(f'\nScaling cluster {cluster_id} to {new_node_count} nodes...')
107-
108-
cluster = verda.clusters.scale(cluster_id, new_node_count)
109-
110-
print('Cluster scaled successfully')
111-
print(f'Current node count: {cluster.node_count}')
112-
print(f'Cluster status: {cluster.status}')
82+
print(f' Public IP: {cluster.ip}')
83+
print(f' Worker nodes: {len(cluster.worker_nodes)}')
11384

11485
return cluster
11586

@@ -118,7 +89,7 @@ def delete_cluster_example(cluster_id: str):
11889
"""Delete a cluster."""
11990
print(f'\nDeleting cluster {cluster_id}...')
12091

121-
verda.clusters.delete(cluster_id)
92+
verda.clusters.action(cluster_id, Actions.DELETE)
12293

12394
print('Cluster deleted successfully')
12495

@@ -140,14 +111,6 @@ def main():
140111
print('\n3. Getting cluster details...')
141112
get_cluster_by_id_example(cluster_id)
142113

143-
# Get cluster nodes
144-
print('\n4. Getting cluster nodes...')
145-
get_cluster_nodes_example(cluster_id)
146-
147-
# Scale the cluster
148-
print('\n5. Scaling the cluster...')
149-
scale_cluster_example(cluster_id, 5)
150-
151114
# Delete the cluster
152115
print('\n6. Deleting the cluster...')
153116
delete_cluster_example(cluster_id)

tests/integration_tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Make sure to run the server and the account has enough balance before running the tests
1010
"""
1111

12-
BASE_URL = 'http://localhost:3010/v1'
12+
BASE_URL = os.getenv('VERDA_BASE_URL', 'https://api.verda.com/v1')
1313

1414
# Load env variables, make sure there's an env file with valid client credentials
1515
load_dotenv()
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import os
2+
3+
import pytest
4+
5+
from verda import VerdaClient
6+
from verda.constants import Locations
7+
8+
IN_GITHUB_ACTIONS = os.getenv('GITHUB_ACTIONS') == 'true'
9+
10+
11+
@pytest.mark.skipif(IN_GITHUB_ACTIONS, reason="Test doesn't work in Github Actions.")
12+
@pytest.mark.withoutresponses
13+
class TestClusters:
14+
def test_create_cluster(self, verda_client: VerdaClient):
15+
# get ssh key
16+
ssh_key = verda_client.ssh_keys.get()[0]
17+
18+
# create instance
19+
cluster = verda_client.clusters.create(
20+
hostname='test-instance',
21+
location=Locations.FIN_03,
22+
cluster_type='16H200',
23+
description='test instance',
24+
image='ubuntu-22.04-cuda-12.4-cluster',
25+
ssh_key_ids=[ssh_key.id],
26+
)
27+
28+
# assert instance is created
29+
assert cluster.id is not None
30+
assert (
31+
cluster.status == verda_client.constants.instance_status.PROVISIONING
32+
or cluster.status == verda_client.constants.instance_status.RUNNING
33+
)
34+
35+
assert cluster.worker_nodes is not None
36+
assert len(cluster.worker_nodes) == 2
37+
assert cluster.ip is not None
38+
39+
print(cluster)
40+
41+
# delete instance
42+
# verda_client.clusters.action(cluster.id, 'delete')

verda/clusters/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Clusters service for managing compute clusters."""
22

3-
from verda.clusters._clusters import Cluster, ClusterNode, ClustersService
3+
from verda.clusters._clusters import Cluster, ClusterWorkerNode, ClustersService
44

5-
__all__ = ['Cluster', 'ClusterNode', 'ClustersService']
5+
__all__ = ['Cluster', 'ClusterWorkerNode', 'ClustersService']

0 commit comments

Comments
 (0)