-
Notifications
You must be signed in to change notification settings - Fork 2
[SDK] Add Dynamo deployment support; bump platform-api-python-client to 4.23.1 #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| #!/usr/bin/env python3 | ||
| """Create and inspect a fixed-replica NVIDIA Dynamo deployment. | ||
|
|
||
| Run `centml login` or configure service-account credentials first. This example | ||
| creates a billable GPU deployment and intentionally leaves cleanup to the user. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: you don't need to mention billable since we don't charge credit. maybe more that it's active
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. agree |
||
| """ | ||
|
|
||
| import os | ||
|
|
||
| from centml.sdk import CreateDynamoDeploymentRequest | ||
| from centml.sdk.api import get_centml_client | ||
|
|
||
|
|
||
| def required_env(name: str) -> str: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a future TODO to make this function shared so we can enforce better env var checks
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make sense. for now as an example script this should be fine (allowing doc-reader to copy and paste from single file). |
||
| value = os.getenv(name) | ||
| if not value: | ||
| raise SystemExit(f"Set {name} before running this example.") | ||
| return value | ||
|
|
||
|
|
||
| def build_request() -> CreateDynamoDeploymentRequest: | ||
| hf_token = os.getenv("HF_TOKEN") | ||
| return CreateDynamoDeploymentRequest( | ||
| name=os.getenv("CENTML_DEPLOYMENT_NAME", "qwen-dynamo"), | ||
| cluster_id=int(required_env("CENTML_CLUSTER_ID")), | ||
| hardware_instance_id=int(required_env("CENTML_HARDWARE_INSTANCE_ID")), | ||
| model=os.getenv("DYNAMO_MODEL", "Qwen/Qwen3-0.6B"), | ||
| min_replicas=1, | ||
| max_replicas=1, | ||
| hf_token=hf_token or None, | ||
| endpoint_bearer_token=required_env("CENTML_ENDPOINT_BEARER_TOKEN"), | ||
| ) | ||
|
|
||
|
|
||
| def validate_target(client, request: CreateDynamoDeploymentRequest) -> None: | ||
| clusters = {cluster.id for cluster in client.get_clusters().results} | ||
| if request.cluster_id not in clusters: | ||
| raise SystemExit(f"Cluster {request.cluster_id} is not accessible to the authenticated identity.") | ||
|
|
||
| hardware_instances = {hardware.id for hardware in client.get_hardware_instances(cluster_id=request.cluster_id)} | ||
| if request.hardware_instance_id not in hardware_instances: | ||
| raise SystemExit( | ||
| f"Hardware instance {request.hardware_instance_id} is not available in cluster {request.cluster_id}." | ||
| ) | ||
|
|
||
|
|
||
| def main(): | ||
| request = build_request() | ||
|
|
||
| with get_centml_client() as client: | ||
| validate_target(client, request) | ||
|
|
||
| response = client.create_dynamo(request) | ||
| deployment = client.get_dynamo(response.id) | ||
|
|
||
| # Lifecycle helpers are type-independent: | ||
| # client.pause(deployment.id) | ||
| # client.resume(deployment.id) | ||
| # client.delete(deployment.id) | ||
| # | ||
| # To update a Dynamo deployment, construct a new | ||
| # CreateDynamoDeploymentRequest and call: | ||
| # client.update_dynamo(deployment.id, updated_request) | ||
|
|
||
| print(f"Created Dynamo deployment {deployment.id}: {deployment.endpoint_url}") | ||
| print(f"Model: {deployment.model}") | ||
| print(f"Replicas: {deployment.min_replicas}-{deployment.max_replicas}") | ||
| print(f"Status: {deployment.status.value}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #!/usr/bin/env python3 | ||
| """Validate CentML SDK authentication with a read-only API request.""" | ||
|
|
||
| from centml.sdk import ApiException | ||
| from centml.sdk.api import get_centml_client | ||
|
|
||
|
|
||
| def validate_auth(): | ||
| """Return accessible clusters after validating the configured credentials.""" | ||
| with get_centml_client() as client: | ||
| return client.get_clusters().results | ||
|
|
||
|
|
||
| def main(): | ||
| try: | ||
| clusters = validate_auth() | ||
| except SystemExit as error: | ||
| raise SystemExit( | ||
| "SDK authentication failed. Run `centml login` or set both " | ||
| "CENTML_SERVICE_ACCOUNT_ID and CENTML_SERVICE_ACCOUNT_SECRET." | ||
| ) from error | ||
| except ApiException as error: | ||
| if error.status in (401, 403): | ||
| raise SystemExit( | ||
| "The Platform API rejected the SDK credentials. Run `centml login` " | ||
| "or verify the service-account credentials and API URL." | ||
| ) from error | ||
| raise | ||
|
|
||
| print("SDK authentication succeeded.") | ||
| print(f"Accessible clusters: {len(clusters)}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: also here too for billing