|
| 1 | +# Verda Python SDK |
| 2 | + |
| 3 | +> Official Python SDK for Verda (formerly DataCrunch) cloud computing platform |
| 4 | +> Documentation: https://datacrunch-python.readthedocs.io/en/latest/ |
| 5 | +> API Documentation: https://api.verda.com/v1/docs |
| 6 | +> GitHub: https://github.com/verda-cloud/sdk-python |
| 7 | +> PyPI: https://pypi.org/project/verda/ |
| 8 | + |
| 9 | +## Installation |
| 10 | + |
| 11 | +```bash |
| 12 | +# via pip |
| 13 | +pip install verda |
| 14 | + |
| 15 | +# via uv |
| 16 | +uv add verda |
| 17 | +``` |
| 18 | + |
| 19 | +## Authentication |
| 20 | + |
| 21 | +Generate client credentials through the Verda dashboard (see API docs for details). |
| 22 | + |
| 23 | +```python |
| 24 | +from verda import VerdaClient |
| 25 | + |
| 26 | +CLIENT_ID = 'your-client-id' |
| 27 | +CLIENT_SECRET = 'your-client-secret' |
| 28 | + |
| 29 | +verda = VerdaClient(CLIENT_ID, CLIENT_SECRET) |
| 30 | + |
| 31 | +# With custom base URL (for development) |
| 32 | +verda = VerdaClient(CLIENT_ID, CLIENT_SECRET) |
| 33 | + |
| 34 | +# With inference key for container inference (optional) |
| 35 | +verda = VerdaClient(CLIENT_ID, CLIENT_SECRET, inference_key='your-inference-key') |
| 36 | +``` |
| 37 | + |
| 38 | +## Available Services |
| 39 | + |
| 40 | +### Instances Service (`verda.instances`) |
| 41 | +Deploy, manage, and monitor compute instances. |
| 42 | + |
| 43 | +Methods: |
| 44 | +- `get()` - List all instances |
| 45 | +- `get_by_id(instance_id)` - Get specific instance |
| 46 | +- `create(instance_type, image, ssh_key_ids, hostname, description, ...)` - Create new instance |
| 47 | +- `action(instance_id, action, volume_ids=None)` - Perform action on instance |
| 48 | + |
| 49 | +### Volumes Service (`verda.volumes`) |
| 50 | +Create and manage storage volumes. |
| 51 | + |
| 52 | +Methods: |
| 53 | +- `get()` - List all volumes |
| 54 | +- `get_by_id(volume_id)` - Get specific volume |
| 55 | +- `create(volume_type, name, size, location)` - Create new volume |
| 56 | +- `action(volume_id, action, ...)` - Perform action on volume |
| 57 | + |
| 58 | +### SSH Keys Service (`verda.ssh_keys`) |
| 59 | +Manage SSH keys for instance access. |
| 60 | + |
| 61 | +Methods: |
| 62 | +- `get()` - List all SSH keys |
| 63 | +- `get_by_id(key_id)` - Get specific SSH key |
| 64 | +- `create(name, public_key)` - Add new SSH key |
| 65 | +- `delete(key_id)` - Delete SSH key |
| 66 | + |
| 67 | +### Startup Scripts Service (`verda.startup_scripts`) |
| 68 | +Manage startup scripts for instances. |
| 69 | + |
| 70 | +Methods: |
| 71 | +- `get()` - List all startup scripts |
| 72 | +- `get_by_id(script_id)` - Get specific script |
| 73 | +- `create(name, script_content)` - Create new script |
| 74 | +- `delete(script_id)` - Delete script |
| 75 | + |
| 76 | +### Containers Service (`verda.containers`) |
| 77 | +Deploy and manage container deployments for inference and services. |
| 78 | + |
| 79 | +Methods: |
| 80 | +- `deployments.get()` - List all deployments |
| 81 | +- `deployments.get_by_id(deployment_id)` - Get specific deployment |
| 82 | +- `deployments.create(...)` - Create new deployment |
| 83 | +- `deployments.update(deployment_id, ...)` - Update deployment |
| 84 | +- `deployments.delete(deployment_id)` - Delete deployment |
| 85 | +- `inference(deployment_id, ...)` - Send inference request |
| 86 | + |
| 87 | +### Instance Types Service (`verda.instance_types`) |
| 88 | +Get available instance types and their specifications. |
| 89 | + |
| 90 | +Methods: |
| 91 | +- `get()` - List all instance types |
| 92 | + |
| 93 | +### Volume Types Service (`verda.volume_types`) |
| 94 | +Get available volume types. |
| 95 | + |
| 96 | +Methods: |
| 97 | +- `get()` - List all volume types |
| 98 | + |
| 99 | +### Images Service (`verda.images`) |
| 100 | +Get available OS images. |
| 101 | + |
| 102 | +Methods: |
| 103 | +- `get()` - List all images |
| 104 | + |
| 105 | +### Balance Service (`verda.balance`) |
| 106 | +Check account balance. |
| 107 | + |
| 108 | +Methods: |
| 109 | +- `get()` - Get current balance |
| 110 | + |
| 111 | +### Locations Service (`verda.locations`) |
| 112 | +Get available datacenter locations. |
| 113 | + |
| 114 | +Methods: |
| 115 | +- `get()` - List all locations |
| 116 | + |
| 117 | +## Constants |
| 118 | + |
| 119 | +Import constants from `verda.constants`: |
| 120 | + |
| 121 | +```python |
| 122 | +from verda.constants import Actions, VolumeActions, InstanceStatus, VolumeStatus, VolumeTypes, Locations, ErrorCodes |
| 123 | +``` |
| 124 | + |
| 125 | +### Actions (Instance Actions) |
| 126 | +- `Actions.START` - Start instance |
| 127 | +- `Actions.SHUTDOWN` - Shutdown instance |
| 128 | +- `Actions.DELETE` - Delete instance |
| 129 | +- `Actions.HIBERNATE` - Hibernate instance |
| 130 | +- `Actions.RESTORE` - Restore hibernated instance |
| 131 | + |
| 132 | +### VolumeActions |
| 133 | +- `VolumeActions.ATTACH` - Attach volume to instance |
| 134 | +- `VolumeActions.DETACH` - Detach volume from instance |
| 135 | +- `VolumeActions.RENAME` - Rename volume |
| 136 | +- `VolumeActions.INCREASE_SIZE` - Increase volume size |
| 137 | +- `VolumeActions.DELETE` - Delete volume |
| 138 | +- `VolumeActions.CLONE` - Clone volume |
| 139 | + |
| 140 | +### InstanceStatus |
| 141 | +- `InstanceStatus.ORDERED` - Instance ordered |
| 142 | +- `InstanceStatus.RUNNING` - Instance running |
| 143 | +- `InstanceStatus.PROVISIONING` - Instance provisioning |
| 144 | +- `InstanceStatus.OFFLINE` - Instance offline |
| 145 | +- `InstanceStatus.STARTING_HIBERNATION` - Starting hibernation |
| 146 | +- `InstanceStatus.HIBERNATING` - Instance hibernating |
| 147 | +- `InstanceStatus.RESTORING` - Restoring from hibernation |
| 148 | +- `InstanceStatus.ERROR` - Instance in error state |
| 149 | + |
| 150 | +### VolumeStatus |
| 151 | +- `VolumeStatus.ORDERED` - Volume ordered |
| 152 | +- `VolumeStatus.CREATING` - Volume creating |
| 153 | +- `VolumeStatus.ATTACHED` - Volume attached |
| 154 | +- `VolumeStatus.DETACHED` - Volume detached |
| 155 | +- `VolumeStatus.DELETING` - Volume deleting |
| 156 | +- `VolumeStatus.DELETED` - Volume deleted |
| 157 | +- `VolumeStatus.CLONING` - Volume cloning |
| 158 | + |
| 159 | +### VolumeTypes |
| 160 | +- `VolumeTypes.NVMe` - NVMe SSD storage |
| 161 | +- `VolumeTypes.HDD` - HDD storage |
| 162 | +- `VolumeTypes.SFS` - Shared filesystem (NVMe_Shared) |
| 163 | + |
| 164 | +### Locations |
| 165 | +- `Locations.FIN_01` - Finland datacenter 1 |
| 166 | +- `Locations.FIN_02` - Finland datacenter 2 |
| 167 | +- `Locations.FIN_03` - Finland datacenter 3 |
| 168 | +- `Locations.ICE_01` - Iceland datacenter 1 |
| 169 | + |
| 170 | +### ErrorCodes |
| 171 | +- `ErrorCodes.INVALID_REQUEST` - Invalid request |
| 172 | +- `ErrorCodes.UNAUTHORIZED_REQUEST` - Unauthorized request |
| 173 | +- `ErrorCodes.INSUFFICIENT_FUNDS` - Insufficient funds |
| 174 | +- `ErrorCodes.FORBIDDEN_ACTION` - Forbidden action |
| 175 | +- `ErrorCodes.NOT_FOUND` - Resource not found |
| 176 | +- `ErrorCodes.SERVER_ERROR` - Server error |
| 177 | +- `ErrorCodes.SERVICE_UNAVAILABLE` - Service unavailable |
| 178 | + |
| 179 | +## Common Usage Patterns |
| 180 | + |
| 181 | +### Creating an Instance |
| 182 | + |
| 183 | +```python |
| 184 | +from verda import VerdaClient |
| 185 | +from verda.constants import Locations |
| 186 | + |
| 187 | +verda = VerdaClient(CLIENT_ID, CLIENT_SECRET) |
| 188 | + |
| 189 | +# Get SSH keys |
| 190 | +ssh_keys = [key.id for key in verda.ssh_keys.get()] |
| 191 | + |
| 192 | +# Create instance |
| 193 | +instance = verda.instances.create( |
| 194 | + instance_type='1V100.6V', |
| 195 | + image='ubuntu-24.04-cuda-12.8-open-docker', |
| 196 | + location=Locations.FIN_03, |
| 197 | + ssh_key_ids=ssh_keys, |
| 198 | + hostname='my-instance', |
| 199 | + description='My GPU instance' |
| 200 | +) |
| 201 | + |
| 202 | +print(f"Created instance: {instance.id}") |
| 203 | +``` |
| 204 | + |
| 205 | +### Managing Instances |
| 206 | + |
| 207 | +```python |
| 208 | +from verda.constants import Actions, InstanceStatus |
| 209 | +import time |
| 210 | + |
| 211 | +# Wait for instance to be running |
| 212 | +while instance.status != InstanceStatus.RUNNING: |
| 213 | + time.sleep(30) |
| 214 | + instance = verda.instances.get_by_id(instance.id) |
| 215 | + |
| 216 | +# Shutdown instance |
| 217 | +verda.instances.action(instance.id, Actions.SHUTDOWN) |
| 218 | + |
| 219 | +# Wait for instance to be offline |
| 220 | +while instance.status != InstanceStatus.OFFLINE: |
| 221 | + time.sleep(30) |
| 222 | + instance = verda.instances.get_by_id(instance.id) |
| 223 | + |
| 224 | +# Hibernate instance |
| 225 | +verda.instances.action(instance.id, Actions.HIBERNATE) |
| 226 | + |
| 227 | +# Delete instance (with OS volume) |
| 228 | +verda.instances.action(instance.id, Actions.DELETE) |
| 229 | + |
| 230 | +# Delete instance without deleting OS volume |
| 231 | +verda.instances.action(instance.id, Actions.DELETE, volume_ids=[]) |
| 232 | +``` |
| 233 | + |
| 234 | +### Working with Volumes |
| 235 | + |
| 236 | +```python |
| 237 | +from verda.constants import VolumeTypes, VolumeActions |
| 238 | + |
| 239 | +# Create instance with extra volumes |
| 240 | +instance = verda.instances.create( |
| 241 | + instance_type='1V100.6V', |
| 242 | + image='ubuntu-24.04-cuda-12.8-open-docker', |
| 243 | + ssh_key_ids=ssh_keys, |
| 244 | + hostname='example', |
| 245 | + description='Instance with extra volumes', |
| 246 | + volumes=[ |
| 247 | + {'type': VolumeTypes.HDD, 'name': 'data-volume', 'size': 500}, |
| 248 | + {'type': VolumeTypes.NVMe, 'name': 'fast-storage', 'size': 100}, |
| 249 | + ] |
| 250 | +) |
| 251 | + |
| 252 | +# Create standalone volume |
| 253 | +volume = verda.volumes.create( |
| 254 | + volume_type=VolumeTypes.NVMe, |
| 255 | + name='my-volume', |
| 256 | + size=100, |
| 257 | + location=Locations.FIN_03 |
| 258 | +) |
| 259 | + |
| 260 | +# Attach volume to instance |
| 261 | +verda.volumes.action( |
| 262 | + volume_id=volume.id, |
| 263 | + action=VolumeActions.ATTACH, |
| 264 | + instance_id=instance.id |
| 265 | +) |
| 266 | + |
| 267 | +# Detach volume |
| 268 | +verda.volumes.action( |
| 269 | + volume_id=volume.id, |
| 270 | + action=VolumeActions.DETACH |
| 271 | +) |
| 272 | + |
| 273 | +# Delete volume |
| 274 | +verda.volumes.action(volume.id, VolumeActions.DELETE) |
| 275 | +``` |
| 276 | + |
| 277 | +### Container Deployments |
| 278 | + |
| 279 | +```python |
| 280 | +# Create container deployment |
| 281 | +deployment = verda.containers.deployments.create( |
| 282 | + name='my-model', |
| 283 | + image='registry.example.com/my-model:latest', |
| 284 | + replicas=2, |
| 285 | + compute_resources={ |
| 286 | + 'cpu': 4, |
| 287 | + 'memory': 16, |
| 288 | + 'gpu': 1 |
| 289 | + }, |
| 290 | + environment_variables=[ |
| 291 | + {'name': 'MODEL_PATH', 'value': '/models/model.bin'} |
| 292 | + ], |
| 293 | + ports=[{'container_port': 8080, 'protocol': 'http'}] |
| 294 | +) |
| 295 | + |
| 296 | +# Send inference request |
| 297 | +result = verda.containers.inference( |
| 298 | + deployment_id=deployment.id, |
| 299 | + prompt='Hello, world!', |
| 300 | + max_tokens=100 |
| 301 | +) |
| 302 | + |
| 303 | +# Update deployment scaling |
| 304 | +verda.containers.deployments.update( |
| 305 | + deployment_id=deployment.id, |
| 306 | + replicas=4 |
| 307 | +) |
| 308 | + |
| 309 | +# Delete deployment |
| 310 | +verda.containers.deployments.delete(deployment.id) |
| 311 | +``` |
| 312 | + |
| 313 | +## Exception Handling |
| 314 | + |
| 315 | +```python |
| 316 | +from verda.exceptions import APIException |
| 317 | + |
| 318 | +try: |
| 319 | + verda.instances.action(instance.id, Actions.SHUTDOWN) |
| 320 | +except APIException as e: |
| 321 | + print(f"API Error: {e}") |
| 322 | + # Access error details |
| 323 | + print(f"Status code: {e.status_code}") |
| 324 | + print(f"Error code: {e.error_code}") |
| 325 | + print(f"Message: {e.message}") |
| 326 | +``` |
| 327 | + |
| 328 | +## Migration from DataCrunch |
| 329 | + |
| 330 | +The SDK was originally published as `datacrunch`. If migrating: |
| 331 | + |
| 332 | +1. Replace `datacrunch` imports with `verda` |
| 333 | +2. Update constant paths: `verda.constants.instance_actions` → `Actions` (import from `verda.constants`) |
| 334 | +3. See MIGRATION.md for detailed migration guide |
| 335 | + |
| 336 | +## Best Practices |
| 337 | + |
| 338 | +1. **Store credentials securely**: Use environment variables, never hardcode |
| 339 | +2. **Handle rate limits**: Implement exponential backoff for retries |
| 340 | +3. **Check instance status**: Wait for instances to reach desired state before performing actions |
| 341 | +4. **Clean up resources**: Delete instances and volumes when no longer needed |
| 342 | +5. **Use SSH keys**: Always configure SSH keys for secure instance access |
| 343 | +6. **Monitor balance**: Check balance regularly to avoid service interruptions |
| 344 | + |
| 345 | +## Additional Resources |
| 346 | + |
| 347 | +- Full API documentation: https://api.verda.com/v1/docs |
| 348 | +- SDK documentation: https://datacrunch-python.readthedocs.io/en/latest/ |
| 349 | +- Examples: https://github.com/verda-cloud/sdk-python/tree/master/examples |
| 350 | +- Support: https://verda.com/contact |
0 commit comments