Manage GPU sessions on Clouditia platform
Project description
Clouditia Manager SDK
Python SDK to manage remote GPU sessions on Clouditia via the Computing API (sk_compute_).
Installation
pip install clouditia-manager
This automatically installs the
clouditiaSDK (for code execution) andboto3(for S3 uploads).
1. Configuration
from clouditia_manager import GPUManager
# Default configuration (URL: https://clouditia.com/jobs)
manager = GPUManager(api_key="sk_compute_xxxxx")
# Advanced configuration
manager = GPUManager(
api_key="sk_compute_xxxxx",
base_url="https://clouditia.com/jobs", # API URL (default)
timeout=120 # Timeout in seconds (default: 60)
)
# Your API key is verified automatically
print(f"User: {manager.user['username']}")
print(f"Email: {manager.user['email']}")
Where to find your API key? Go to clouditia.com/manage/api-keys/ to create a
sk_compute_key.
2. Check available GPUs
Before launching a session, check GPU inventory in real-time:
inventory = manager.get_inventory()
if not inventory:
print("No GPUs available")
else:
for gpu in inventory:
print(f"{gpu.gpu_name} ({gpu.price_per_hour}EUR/h) : "
f"{gpu.available} available, {gpu.on_demand} on-demand || "
f"datacenter : {gpu.datacenter}, "
f"[datacenter_id : {gpu.datacenter_id}]")
Example output:
NVIDIA RTX 3090 (1.0EUR/h) : 1 available, 0 on-demand || datacenter : France-Poissy, [datacenter_id : e7aabe3c-...]
NVIDIA RTX 3060 Ti (0.5EUR/h) : 0 available, 4 on-demand || datacenter : France-vo8, [datacenter_id : 487754eb-...]
Status meanings:
- available: GPUs on powered-on machines, ready immediately
- on_demand: GPUs on powered-off machines, startup in ~2-5 minutes
- in_use: GPUs currently used by active sessions
Filter by datacenter
Use the datacenter_id (UUID) to filter inventory for a specific datacenter:
inventory = manager.get_inventory(datacenter_id="487754eb-a676-4502-a0f4-21a88e52c25a")
for gpu in inventory:
print(f"{gpu.gpu_name}: {gpu.available} available, {gpu.on_demand} on-demand")
List datacenters
datacenters = manager.list_datacenters()
for dc in datacenters:
print(f"{dc.name} (datacenter_id={dc.datacenter_id}) , GPUs: {dc.gpu_count}")
# Example output:
# France-Poissy (datacenter_id=e7aabe3c-...) , GPUs: 2
# France-vo8 (datacenter_id=487754eb-...) , GPUs: 4
3. Create a GPU session
Once you've chosen a GPU, launch a session. The SDK automatically waits until the session is ready:
session = manager.create_session(
gpu_type="nvidia-rtx-3090", # GPU type slug (from inventory)
vcpu=2, # Number of vCPUs
ram=4, # RAM in GB
storage=20 # Storage in GB
)
print(f"Session ready: {session.name}")
print(f"VS Code URL: {session.url}")
print(f"Password: {session.password}")
Target a specific datacenter
Use datacenter_id to launch the session on a specific datacenter:
session = manager.create_session(
gpu_type="nvidia-rtx-3060-ti",
vcpu=2, ram=4, storage=20,
datacenter_id="487754eb-a676-4502-a0f4-21a88e52c25a" # France-vo8
)
Progress tracking
The SDK monitors each creation step (power on, deployment, etc.) and displays progress in real-time. No need to set a timeout — the SDK detects real errors and returns them immediately:
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
vcpu=4, ram=16, storage=20,
wait_ready=True, # Wait for session to be ready (default: True)
verbose=True # Show steps in real-time (default: True)
)
# Typical output (on-demand node):
# Waiting for session f091ef1c to be ready...
# [powering_on] Powering on node...
# [waiting_nodes] Waiting for nodes...
# [deploying] Deploying GPU session...
# [waiting_ready] Waiting for pod ready...
#
# SESSION READY
# ...
# Silent mode (no waiting, no output)
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
vcpu=2, ram=4, storage=20,
wait_ready=False,
verbose=False
)
4. Stop a session
# Standard stop (waits for pod deletion)
result = manager.stop_session(f"{session.short_id}") # ex: "0e4c713a"
print(f"Session stopped: {result.name}")
# Silent mode
result = manager.stop_session(f"{session.short_id}", wait_stopped=False, verbose=False)
5. Execute code in a session
To execute code in an active session, generate a sk_live_ key and use the clouditia SDK.
Step 1: Generate an execution key
# Generate a sk_live_ key linked to the session
sdk_key = manager.generate_sdk_key(
session_id=session.short_id, # ex: "0e4c713a"
name="My Execution Key"
)
print(f"Key: {sdk_key}") # sk_live_xxxxx...
Step 2: Execute shell commands
from clouditia import GPUSession
session_live_gpu = GPUSession(api_key=sdk_key)
# Install system packages
result = session_live_gpu.shell("sudo apt update && sudo apt install -y ffmpeg")
print(result)
# Verify installation
result = session_live_gpu.shell("ffmpeg -version")
print(result)
# Install Python packages
result = session_live_gpu.shell("pip install transformers accelerate")
print(result)
# Verify installation
result = session_live_gpu.shell("python3 -c 'import transformers; print(transformers.__version__)'")
print(result)
# Execute a script from the workspace
result = session_live_gpu.shell("cd /home/coder/workspace && python3 train.py")
print(result)
Step 3: Execute Python code
# Execute Python code directly (via session_live_gpu.run)
result = session_live_gpu.run("""
import torch
print(f'CUDA: {torch.cuda.is_available()}')
print(f'GPU: {torch.cuda.get_device_name(0)}')
a = torch.randn(1000, 1000, device='cuda')
b = torch.randn(1000, 1000, device='cuda')
c = torch.matmul(a, b)
print(f'Result: {c.shape}')
""")
print(result)
Alternative: Lambda GPU (no session management)
For quick execution without creating a session manually, use lambda_gpu() (see section 10).
6. Manage sessions
List sessions
# All sessions
sessions = manager.list_sessions()
# Filter by status
running = manager.list_sessions(status="running")
stopped = manager.list_sessions(status="stopped")
for session in sessions:
print(f"{session.name} ({session.short_id}): {session.status} - {session.gpu_type}")
Get session details
session = manager.get_session("0e4c713a")
print(f"Name: {session.name}")
print(f"Status: {session.status}")
print(f"GPU: {session.gpu_type}")
print(f"URL: {session.url}")
print(f"Password: {session.password}")
Rename a session
session = manager.rename_session("0e4c713a", "my-ml-project-v1")
print(f"New name: {session.name}")
Session cost and duration
cost_info = manager.get_session_cost("0e4c713a")
print(f"Current cost: {cost_info['cost']} EUR")
print(f"Hourly rate: {cost_info['hourly_rate']} EUR/h")
print(f"Duration: {cost_info['duration_display']}")
Check credit balance
balance = manager.get_balance()
print(f"Balance: {balance['balance']} {balance['currency']}")
7. Multi-GPU sessions
Create a session with multiple GPUs, optionally of different types:
session = manager.create_session(
gpus=[
{'type': 'nvidia-rtx-3090', 'count': 1},
{'type': 'nvidia-rtx-3060-ti', 'count': 1}
],
vcpu=4,
ram=16,
storage=20
)
print(f"GPU Count: {session.gpu_count}")
print(f"GPUs: {session.gpus}")
GPU availability (allow_partial, auto_add_gpus)
If some requested GPUs are not available:
# Default: raises an error if any GPU is unavailable
session = manager.create_session(
gpus=[
{'type': 'nvidia-rtx-3090', 'count': 1},
{'type': 'nvidia-rtx-4090', 'count': 1} # If unavailable -> error
],
vcpu=4, ram=16, storage=20
)
# InsufficientResourcesError: Some GPUs unavailable: nvidia-rtx-4090.
# Use allow_partial=True to create with available GPUs only.
# allow_partial=True: create immediately with available GPUs only
session = manager.create_session(
gpus=[
{'type': 'nvidia-rtx-3090', 'count': 1},
{'type': 'nvidia-rtx-4090', 'count': 1}
],
vcpu=4, ram=16, storage=20,
allow_partial=True # Starts with 3090 only, no error
)
# auto_add_gpus=True: start with available GPUs, then automatically
# add missing GPUs when they become available (checks every 30s)
session = manager.create_session(
gpus=[
{'type': 'nvidia-rtx-3090', 'count': 1},
{'type': 'nvidia-rtx-4090', 'count': 1}
],
vcpu=4, ram=16, storage=20,
allow_partial=True,
auto_add_gpus=True # Background thread watches for nvidia-rtx-4090
)
8. Auto-stop limits
Set limits to automatically stop a session:
# Cost limit: auto-stop at 5 EUR
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
vcpu=4, ram=16,
cost_limit=5.0
)
# Duration limit: auto-stop after 2 hours
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
vcpu=4, ram=16,
duration_limit=7200 # seconds
)
# Both: stop when either limit is reached
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
vcpu=4, ram=16,
cost_limit=10.0,
duration_limit=3600
)
print(f"Auto-stop enabled: {session.auto_stop_enabled}")
print(f"Cost limit: {session.cost_limit} EUR")
print(f"Duration limit: {session.duration_limit} seconds")
9. Queue
If GPUs are not immediately available, place your request in a queue:
result = manager.create_session(
gpu_type="nvidia-rtx-4090",
vcpu=4, ram=16, storage=20,
queue_if_unavailable=True
)
if hasattr(result, 'name'):
print(f"Session created: {result.name}")
elif isinstance(result, dict) and result.get('queued'):
print(f"Queued! Position: #{result['position']}")
print(f"Queue ID: {result['queue_id']}")
Manage the queue
# List queue jobs
queue_jobs = manager.list_queue_jobs()
for job in queue_jobs:
print(f"Position #{job.position}: {job.status_display}")
# Job details with history
result = manager.get_queue_job("a1b2c3d4", verbose=True)
# Cancel a job
manager.cancel_queue_job("a1b2c3d4")
10. Lambda GPU (Serverless Execution)
Execute Python code directly on a remote GPU, without managing a session:
result = manager.lambda_gpu(
script="""
import torch
print(f"CUDA: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
a = torch.randn(5000, 5000, device='cuda')
b = torch.randn(5000, 5000, device='cuda')
c = torch.matmul(a, b)
print(f"5000x5000 matmul OK, shape: {c.shape}")
""",
gpu_type="nvidia-rtx-3060-ti",
vcpu=2,
ram=4,
storage=20
)
print(f"Exit code: {result.exit_code}")
print(f"Output: {result.stdout}")
print(f"Cost: {result.cost} EUR")
print(f"Duration: {result.duration_seconds}s")
Lambda with custom Docker environment
result = manager.lambda_gpu(
script="import torch; print(torch.cuda.is_available())",
gpu_type="nvidia-rtx-3090",
environment_id="3a07d1e9-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
vcpu=8, ram=32, storage=100
)
run_and_stop() (Full session with S3 upload)
Creates a session, uploads local files, executes a script on remote GPU, uploads results to S3, then stops the session automatically.
Step 1: Create local files
# Create train.py locally
with open("train.py", "w") as f:
f.write("""
import torch
import torch.nn as nn
import torch.optim as optim
import pandas as pd
import time
print("=" * 50)
print(" CLOUDITIA GPU TRAINING")
print("=" * 50)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"Device: {device}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
# Load data
df = pd.read_csv('/home/coder/workspace/data.csv')
print(f"Data loaded: {len(df)} rows, {len(df.columns)} columns")
# Simple model
model = nn.Sequential(
nn.Linear(len(df.columns) - 1, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 3)
).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
print(f"Model parameters: {sum(p.numel() for p in model.parameters()):,}")
# Training loop
epochs = 10
for epoch in range(epochs):
x = torch.randn(64, len(df.columns) - 1).to(device)
y = torch.randint(0, 3, (64,)).to(device)
optimizer.zero_grad()
output = model(x)
loss = criterion(output, y)
loss.backward()
optimizer.step()
acc = (output.argmax(1) == y).float().mean().item()
print(f"Epoch {epoch+1}/{epochs} | Loss: {loss.item():.4f} | Acc: {acc:.2%}")
# Save model
torch.save(model.state_dict(), '/home/coder/workspace/model.pt')
print(f"Model saved to /home/coder/workspace/model.pt")
print("Training complete!")
""")
# Create a small data.csv locally
with open("data.csv", "w") as f:
f.write("sepal_length,sepal_width,petal_length,petal_width,species\\n")
f.write("5.1,3.5,1.4,0.2,0\\n")
f.write("4.9,3.0,1.4,0.2,0\\n")
f.write("7.0,3.2,4.7,1.4,1\\n")
f.write("6.4,3.2,4.5,1.5,1\\n")
f.write("6.3,3.3,6.0,2.5,2\\n")
f.write("5.8,2.7,5.1,1.9,2\\n")
Step 2: Run on remote GPU with S3 output
result = manager.run_and_stop(
script="python train.py",
gpu_type="nvidia-rtx-3090",
input_files=["train.py", "data.csv"], # local files uploaded to remote session
output_files=["model.pt"], # remote files uploaded to S3 after execution
s3_bucket="my-bucket",
s3_prefix="training-results/run-001/",
s3_access_key="YOUR_S3_ACCESS_KEY",
s3_secret_key="YOUR_S3_SECRET_KEY",
s3_endpoint="https://s3.amazonaws.com", # optional, default: AWS S3
s3_region="us-east-1" # optional, default: us-east-1
)
print(f"Success: {result.success}")
print(f"Exit code: {result.exit_code}")
print(f"Output: {result.stdout}")
print(f"Cost: {result.cost} EUR")
print(f"Duration: {result.duration_seconds}s")
11. Sessions resumed from custom environment
When you resume a session saved as a custom environment, the workspace must be re-downloaded from S3. The SDK handles this automatically:
session = manager.create_session(
gpu_type="nvidia-rtx-3090",
environment_id="3a07d1e9-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
vcpu=8, ram=32
)
# Displays a progress bar:
# Workspace restore [========............] 28.4% 3.12/10.98 GB ETA 124s
# Check progress manually
session = manager.get_session("0e4c713a")
print(f"Ready: {session.ready}")
if session.workspace_sync and session.workspace_sync.get("in_progress"):
print(f"Progress: {session.workspace_sync['pct']:.0f}%")
12. Notifications and costs
Send an email
# Send to yourself (default: your account email)
manager.send_email(
subject="Training Complete",
message="Accuracy: 95%, Model saved to S3"
)
# Send to a specific recipient
manager.send_email(
subject="Training Complete",
message="Accuracy: 95%",
to="colleague@company.com"
)
Generate an SDK key (sk_live_)
sdk_key = manager.generate_sdk_key("0e4c713a", name="My SDK key")
print(f"SDK key: {sdk_key}")
# Use with the clouditia SDK
from clouditia import GPUSession
session_live_gpu = GPUSession(api_key=sdk_key)
result = session_live_gpu.run("print('Hello!')")
Cost of multiple sessions
# Specific sessions
costs = manager.get_sessions_cost(["0e4c713a", "f0b09214"])
print(f"Total cost: {costs['total_cost']} EUR")
# All active sessions
active_costs = manager.get_active_sessions_cost()
print(f"Active sessions: {active_costs['session_count']}")
print(f"Total cost: {active_costs['total_cost']} EUR")
Error handling
from clouditia_manager import (
GPUManager,
AuthenticationError,
SessionNotFoundError,
InsufficientResourcesError,
APIError
)
try:
manager = GPUManager(api_key="sk_compute_xxxxx")
session = manager.create_session(gpu_type="nvidia-rtx-4090")
except AuthenticationError:
print("Invalid API key")
except InsufficientResourcesError:
print("No GPUs available")
except SessionNotFoundError:
print("Session not found")
except APIError as e:
print(f"API error: {e}")
API Reference
| Method | Description |
|---|---|
GPUManager(api_key, base_url, timeout) |
Initialize the SDK |
| Inventory | |
get_inventory(datacenter_id) |
Real-time GPU availability (available, on_demand, in_use) per datacenter |
list_datacenters() |
List available datacenters |
| Sessions | |
create_session(gpu_type, gpus, vcpu, ram, storage, datacenter_id, allow_partial, auto_add_gpus, ...) |
Create a GPU session |
stop_session(session_id, ...) |
Stop a session |
get_session(session_id) |
Session details |
list_sessions(status) |
List sessions |
rename_session(session_id, new_name) |
Rename a session |
generate_sdk_key(session_id, name) |
Generate a sk_live_ key for code execution |
| Lambda GPU | |
lambda_gpu(script, gpu_type, ...) |
Serverless execution on GPU |
run_and_stop(script, gpu_type, input_files, output_files, s3_bucket, ...) |
Full session with S3 upload |
| Queue | |
list_queue_jobs(status) |
List queue jobs |
get_queue_job(queue_id, verbose) |
Queue job details |
cancel_queue_job(queue_id) |
Cancel a queue job |
| Billing | |
get_balance() |
Credit balance |
get_session_cost(session_id) |
Session cost |
get_session_duration(session_id) |
Session duration |
get_sessions_cost(session_ids) |
Cost of multiple sessions |
get_active_sessions_cost() |
Cost of all active sessions |
| Other | |
send_email(subject, message, to=None) |
Send email notification (default: your email, or specify recipient) |
Object attributes
GPUSession
| Attribute | Type | Description |
|---|---|---|
id |
str | Full UUID |
short_id |
str | Short ID (8 characters) |
name |
str | Session name |
status |
str | running, stopped, pending, failed |
ready |
bool | True only if session is fully usable |
gpu_type |
str | GPU type(s) |
gpu_count |
int | Total number of GPUs |
gpus |
list | List of GPU configs (multi-GPU) |
vcpu |
int | Number of vCPUs |
ram |
str | Allocated RAM |
storage |
str | Allocated storage |
url |
str | VS Code access URL |
password |
str | VS Code password |
cost_limit |
float | Cost limit (EUR) |
duration_limit |
int | Duration limit (seconds) |
auto_stop_enabled |
bool | Auto-stop enabled |
estimated_ready_in_seconds |
int | ETA before ready |
workspace_sync |
dict | Workspace restore progress |
creation_step |
str | Current creation step |
creation_error |
str | Creation error message |
GPUInventory
| Attribute | Type | Description |
|---|---|---|
gpu_type |
str | GPU slug (ex: nvidia-rtx-3090) |
gpu_name |
str | Full name (ex: NVIDIA RTX 3090) |
available |
int | GPUs ready immediately (online nodes) |
on_demand |
int | GPUs startable in ~2-5 min (offline nodes) |
in_use |
int | GPUs used by active sessions |
total |
int | available + on_demand + in_use |
datacenter |
str | Datacenter name |
datacenter_code |
str | Datacenter code |
datacenter_id |
str | Datacenter UUID (for filtering) |
cluster_name |
str | Cluster name |
price_per_hour |
float | Hourly price (EUR) |
Datacenter
| Attribute | Type | Description |
|---|---|---|
datacenter_id |
str | Datacenter UUID |
name |
str | Datacenter name |
is_primary |
bool | Primary datacenter |
gpu_count |
int | Total GPUs |
LambdaResult
| Attribute | Type | Description |
|---|---|---|
success |
bool | True if exit_code == 0 |
exit_code |
int | Exit code |
stdout |
str | Standard output |
stderr |
str | Error output |
duration_seconds |
float | Total duration |
cost |
float | Cost (EUR) |
session_id |
str | Session ID used |
output_files |
list | Uploaded files |
error |
str | Error message |
QueueJob
| Attribute | Type | Description |
|---|---|---|
queue_id |
str | Job UUID |
position |
int | Queue position |
status |
str | pending, processing, completed, failed, cancelled |
status_display |
str | Status label |
gpu_config |
dict | Requested GPU configuration |
attempt_count |
int | Number of attempts |
last_attempt_at |
datetime | Last attempt date |
created_at |
datetime | Creation date |
created_session_id |
str | Created session ID (if successful) |
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clouditia_manager-1.17.0.tar.gz.
File metadata
- Download URL: clouditia_manager-1.17.0.tar.gz
- Upload date:
- Size: 36.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e8da2be80f31a94fc43922732b52691f5b57610fd9a35e0324149c396854431
|
|
| MD5 |
50aebccea8bfb38d73f21bf5e95e852b
|
|
| BLAKE2b-256 |
e3049cf88ee6135e71adfe3dd83355408471a214bf62104bc70ef117760125f9
|
File details
Details for the file clouditia_manager-1.17.0-py3-none-any.whl.
File metadata
- Download URL: clouditia_manager-1.17.0-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43fb09a806818961904069a956a4135354a38ffac57248d5b30974948d0d9930
|
|
| MD5 |
d7949afb13b8b92530985348680096bc
|
|
| BLAKE2b-256 |
c135384ca9b1807f8fb6086d8f6f0cf46b8d45db3aaa41d75f4f3e3b186e6009
|