Air Python SDK

This project provides a Python SDK for interacting with the NVIDIA Air API (https://air.nvidia.com/api/).

Prerequisite

The SDK requires python 3.7 or later. The safest way to install the SDK is to set up a virtual environment in python3.7:

apt-get install python3.7
python3.7 -m pip install virtualenv
python3.7 -m virtualenv venv37
. venv37/bin/activate

Installation

To install the SDK, use pip:

python3 -m pip install air-sdk

Usage

>>> from air_sdk import AirApi
>>> air = AirApi(username='<user>', password='<password>')

Authentication Options

Using the API requires the use of either an API token, a username/password, or a bearer token.

API token

To use an API token, one must first be generated. The easiest way to do this is via the Air UI.

Once a token is generated:

>>> air = AirApi(username='<username>', password='<api_token>')

Username/Password

To use a username/password, an administrator of NVIDIA Air must provision a service account. Once the administrator provides the username and password:

>>> air = AirApi(username='<username>', password='<password>')

Bearer token

Generally, it’s recommended to use an API Token over a bearer token. However, a bearer token might be used for testing or quick-and-dirty operations that might not need a long term API token. To use a bearer token, the calling user must have a nvidia.com account and have previously approved access for NVIDIA Air. Once a token is obtained:

>>> air = AirApi(bearer_token='<bearer_token>')

Interacting with the API

The SDK provides various helper methods for interacting with the API. For example:

>>> air.simulations.list()
[<Simulation sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Simulation sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
>>> sim1 = air.simulations.get('c51b49b6-94a7-4c93-950c-e7fa4883591')
>>> sim1.title = 'My Sim'
>>> sim1.store()

Developing

Contributions to the SDK are very welcome. All code must pass linting and unit testing before it will be merged.

Requirements

python3 -m pip install -r requirements-dev.txt

Linting

pylint **/*.py

Unit testing

./unit_test.sh

Generating docs

pydoc-markdown

SDK Reference Guide

Account

Manage an account

json

Returns a JSON string representation of the account

refresh

Syncs the account with all values returned by the API

AccountApi

High-level interface for the Account API

get

Get an existing account

Arguments:

  • account_id str - Account ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Account

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.accounts.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Account mrobertson@nvidia.com 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing accounts

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.accounts.list()
[<Account mrobertson@nvidia.com c51b49b6-94a7-4c93-950c-e7fa4883591>, <Account nmitchell@nvidia.com 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Cumulus AIR API module

AirSession

Wrapper around requests.Session

rebuild_auth

Allow credential sharing between nvidia.com and cumulusnetworks.com only

AirApi

Main interface for an API client instance

__init__

Create a new API client instance. The caller MUST provide either username and password or a bearer_token. The password argument may either be an API token or a service account password.

Arguments:

  • username str, optional - Username
  • password str, optional - Password or API token
  • bearer_token str, optional - Pre-generated bearer token
  • api_url str, optional - Default = https://air.nvidia.com/api/
  • api_version str - Default = v1

authorize

Authorizes the API client using either a pre-generated API token, a service account username/password, or a pre-generated bearer token. Callers MUST pass either a valid bearer_token or a username and password. The password argument may either be an API token or a service account password. After successfully authorizing, all subsequent API calls will include the authorization token provided by the AIR API. Note: This is called once automatically when an AirApi object is instantiated.

Arguments:

  • bearer_token str, optional - Pre-generated bearer token
  • username str, optional - Username
  • password str, optional - Password or API token

Raises:

ValueError - Caller did not pass either a token or a username/password

get_token

Gets a new bearer token for a given username and password

Arguments:

  • username str - Username
  • password str - Password

Returns:

  • str - Bearer token

Raises:

  • AirAuthorizationError - API did not return a token
  • JSONDecodeError - API’s response is not a valid JSON object

get

Wrapper method for GET requests

post

Wrapper method for POST requests

put

Wrapper method for PUT requests

patch

Wrapper method for PATCH requests

delete

Wrapper method for DELETE requests

Capacity

View platform capacity

json

Returns a JSON string representation of the capacity

refresh

Syncs the capacity with all values returned by the API

CapacityApi

High-level interface for the Simulation API

get

Get current platform capacity for a Simulation

Arguments:

  • simulation_id str | Simulation - Simulation or ID

Returns:

Capacity

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.capacity.get(simulation)
<Capacity 30>

Demo

View demos

json

Returns a JSON string representation of the demo

refresh

Syncs the demo with all values returned by the API

DemoApi

High-level interface for the Demo API

get

Get an existing demo

Arguments:

  • dmeo_id str - Demo ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Demo

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.demos.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Demo EVPN 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing demos

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.demos.list()
[<Demo EVPN c51b49b6-94a7-4c93-950c-e7fa4883591>, <Demo Challenges 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Custom exceptions for the AIR SDK

AirError

Base exception class. All custom exceptions should inherit from this class.

AirAuthorizationError

Raised when authorization with the API fails.

AirUnexpectedResponse

Raised when the API returns an unexpected response.

AirForbiddenError

Raised when an API call returns a 403 Forbidden error

AirObjectDeleted

Raised when accessing a previously instantiated object that has since been deleted

Image

Manage an image

delete

Delete the image. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the image

refresh

Syncs the image with all values returned by the API

update

Update the image with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

upload

Upload an image file

Arguments:

  • filename str - Absolute path to the local image

Raises:

AirUnexpectedresponse - Upload failed

ImageApi

High-level interface for the Image API

get

Get an existing image

Arguments:

  • image_id str - Image ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Image

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.images.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Image cumulus-vx-4.2.1 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing images

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.images.list()
[<Image cumulus-vx-4.2.1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Image generic/ubuntu18.04 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new image

Arguments:

  • name str - Image name
  • organization str | Organization - Organization or ID
  • filename str, optional - Absolute path to the local file which should be uploaded
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Image

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.images.create(name='my_image', filename='/tmp/my_image.qcow2', agent_enabled=False)
<Image my_image 01298e0c-4ef1-43ec-9675-93160eb29d9f>

Interface

View an interface

json

Returns a JSON string representation of the interface

refresh

Syncs the interface with all values returned by the API

InterfaceApi

High-level interface for the Interface API

get

Get an existing interface

Arguments:

  • interface_id str - Interface ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Interface

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Interface eth0 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing interfaces

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.interfaces.list()
[<Interface eth0 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Interface eth1 3134711d-015e-49fb-a6ca-68248a8d4aff>]

SimulationInterface module

SimulationInterface

Manage a simulation interface

json

Returns a JSON string representation of the simulation interface

refresh

Syncs the simulation interface with all values returned by the API

update

Update the simulation interface with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

SimulationInterfaceApi

High-level interface for the SimulationInterface API

get

Get an existing simulation interface

Arguments:

  • simulation_interface_id str - SimulationInterface ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

SimulationInterface

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationInterface 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing simulation interfaces

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_interfaces.list()
[<SimulationInterface c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationInterface 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Job

Manage a Job

json

Returns a JSON string representation of the job

refresh

Syncs the job with all values returned by the API

update

Update the job with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

JobApi

High-level interface for the Job API

get

Get an existing job

Arguments:

  • job_id str - Job ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Job

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.jobs.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Job START 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing jobs

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.jobs.list()
[<Job START c51b49b6-94a7-4c93-950c-e7fa4883591>, <Job STOP 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Manage a link

delete

Delete the link. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the link

refresh

Syncs the link with all values returned by the API

update

Update the link with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

LinkApi

High-level interface for the Link API

get

Get an existing link

Arguments:

  • link_id str - Link ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Link

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.links.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Link 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing links

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.links.list()
[<Link c51b49b6-94a7-4c93-950c-e7fa4883591>, <Link 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new link

Arguments:

  • topology str | Topology - Topology or ID
  • interfaces list - List of Interface objects or IDs
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Link

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.links.create(topology=topology, interfaces=[intf1, 'fd61e3d8-af2f-4735-8b1d-356ee6bf4abe'])
<Link 01298e0c-4ef1-43ec-9675-93160eb29d9f>

Login

View login information

json

Returns a JSON string representation of the login info

refresh

Syncs the login info with all values returned by the API

LoginApi

High-level interface for the Login API

get

Get login information or start an OAuth request. This is equivalent to login.list().

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Login

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.login.get()
<Login>

list

Get login information or start an OAuth request. This is equivalent to login.get().

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Login

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.login.get()
<Login>

Marketplace

View marketplace demos

json

Returns a JSON string representation of the marketplace demo

refresh

Syncs the marketplace demo with all values returned by the API

MarketplaceApi

High-level interface for the Marketplace API

get

Get an existing Marketplace Demo

Arguments:

  • demo_id str - Marketplace Demo ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Marketplace

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.Marketplace.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Marketplace Demo EVPN 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing Marketplace demos

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.marketplace.list()
[<Marketplace Demo EVPN c51b49b6-94a7-4c93-950c-e7fa4883591>, <Marketplace Demo Challenges 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Node

Manage a node

delete

Delete the node. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the node

refresh

Syncs the node with all values returned by the API

update

Update the node with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

NodeApi

High-level interface for the Node API

get

Get an existing node

Arguments:

  • node_id str - Node ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Node

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Node server 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing nodes

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.nodes.list()
[<Node server c51b49b6-94a7-4c93-950c-e7fa4883591>, <Node switch 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new node

Arguments:

  • name str - Node name
  • topology str | Topology - Topology or ID
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Node

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.nodes.create(name='server', topology=topology)
<Node server 01298e0c-4ef1-43ec-9675-93160eb29d9f>

SimulationNode

Manage a SimulationNode

json

Returns a JSON string representation of the simulation node

refresh

Syncs the simulation node with all values returned by the API

update

Update the simulation node with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

create_instructions

Create instructions for the SimulationNode’s agent to execute

Arguments:

  • data str | list - Instruction data
  • executor str - Agent executor type
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

  • dict - Response JSON

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> simulation_node.create_instructions(data='echo foo', executor='shell')
{'id': '67f73552-ffdf-4e5f-9881-aeae227604a3'}

list_instructions

List all instructions for a SimulationNode

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> simulation_node.instructions.list()
[{'id': '56abc69b-489f-429a-aed9-600f26afc956'}, {'id': '7c9c3449-f071-4bbc-bb42-bef04e44d74e'}]

delete_instructions

Delete all instructions for a SimulationNode

Raises:

AirUnexpectedresponse - Instruction delete failed

Example:

>>> simulation_node.instructions.delete()

control

Sends a control command to the SimulationNode.

Arguments:

  • action str - Control command
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

  • dict - Response JSON

Example:

>>> simulation_node.control(action='reset')
{'result': 'success'}

rebuild

Rebuild the SimulationNode back to its initial state. All existing data will be lost.

reset

Reset the SimulationNode

SimulationNodeApi

Wrapper for the SimulationNode API

get

Get an existing simulation node

Arguments:

  • simulation_node_id str - SimulationNode ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

SimulationNode

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationNode my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing simulation nodes

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_nodes.list()
[<SimulationNode sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationNode sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Organization

Manage an organization

delete

Delete the organization. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the organization

refresh

Syncs the organization with all values returned by the API

update

Update the organization with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

OrganizationApi

High-level interface for the Organization API

get

Get an existing organization

Arguments:

  • organization_id str - Organization ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Organization

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.organizations.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Organization NVIDIA 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing organizations

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.organizations.list()
[<Organization NVIDIA c51b49b6-94a7-4c93-950c-e7fa4883591>, <Organization Customer 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new organization

Arguments:

  • name str - Organization name
  • members list - List of member Account objects or IDs
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Organization

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.organizations.create(name='NVIDIA', members=[account, 'fa42f2ce-8494-4d4d-87fd-d9ebc18831bd'])
<Organization NVIDIA 01298e0c-4ef1-43ec-9675-93160eb29d9f>

Permission

Manage a permission

delete

Delete the permission. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the permission

refresh

Syncs the permission with all values returned by the API

update

Update the permission with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

PermissionApi

High-level interface for the Permission API

create

Create a new permission. The caller MUST provide simulation, topology, or subject_id

Arguments:

  • email str - Email address for the user being granted permission
  • simulation str | Simulation, optional - Simulation or ID
  • topology str | Topology, optional - Topology or ID
  • subject_id str | AirModel, optional - AirModel instance or ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Permission

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.permissions.create(email='mrobertson@nvidia.com', topology=topology, write_ok=True)
<Permission 01298e0c-4ef1-43ec-9675-93160eb29d9f>
>>> air.permissions.create(email='mrobertson@nvidia.com',
... subject_id='80cf922a-7b80-4795-8cc5-550833ab1cec', subject_model='simulation.image')
<Permission 8a09ea66-51f9-4ddd-8416-62c266cd959e>

get

Get an existing permission

Arguments:

  • permission_id str - Permission ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Permission

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.permissions.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Permission 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing permissions

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.permissions.list()
[<Permission c51b49b6-94a7-4c93-950c-e7fa4883591>, <Permission 3134711d-015e-49fb-a6ca-68248a8d4aff>]

Service

Manage a service

delete

Delete the service. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the service

refresh

Syncs the service with all values returned by the API

update

Update the service with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

ServiceApi

High-level interface for the Service API

get

Get an existing service

Arguments:

  • service_id str - Service ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Service

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.services.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Service SSH 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing services

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.services.list()
[<Service SSH c51b49b6-94a7-4c93-950c-e7fa4883591>, <Service HTTP 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new service

Arguments:

  • name str - Service name
  • interface str | SimulationInterface - Interface that the service should be created for. This can be provided in one of the following formats:
  • simulation str | Simulation - Simulation or ID
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Service

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.services.create(name='myservice', interface='oob-mgmt-server:eth0', dest_port=22)
<Service myservice cc18d746-4cf0-4dd3-80c0-e7df68bbb782>
>>> air.services.create(name='myservice', interface=simulation_interface, dest_port=22)
<Service myservice 9603d0d5-5526-4a0f-91b8-a600010d0091>

Simulation

Manage a simulation

json

Returns a JSON string representation of the simulation

refresh

Syncs the simulation with all values returned by the API

update

Update the simulation with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

create_service

Create a new service for this simulation

Arguments:

  • name str - Name of the service
  • interface str | SimulationInterface - Interface that the service should be created for. This can be provided in one of the following formats:
  • dest_port int - Service port number
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Service

Example:

>>> simulation.create_service('myservice', 'oob-mgmt-server:eth0', 22, service_type='ssh')
<Service myservice cc18d746-4cf0-4dd3-80c0-e7df68bbb782>
>>> simulation.create_service('myservice', simulation_interface, 22, service_type='ssh')
<Service myservice 9603d0d5-5526-4a0f-91b8-a600010d0091>

add_permission

Adds permission for a given user to this simulation.

Arguments:

  • email str - Email address of the user being given permission
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Permission

Example:

>>> simulation.add_permission('mrobertson@nvidia.com', write_ok=True)
<Permission 217bea68-7048-4262-9bbc-b98ab16c603e>

control

Sends a control command to the simulation.

Arguments:

  • action str - Control command
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

  • dict - Response JSON

Example:

>>> simulation.control(action='destroy')
{'result': 'success'}

load

Alias for start()

start

Start/load the simulation

stop

Alias for store()

store

Store and power off the simulation

delete

Delete the simulation

SimulationApi

High-level interface for the Simulation API

duplicate

Duplicate/clone an existing simulation

Arguments:

  • simulation str | Simulation - Simulation or ID of the snapshot to be duplicated
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

(Simulation, dict): Newly created simulation and response JSON

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulations.duplicate(simulation=simulation)
<Simulation my_sim 5ff3f0dc-7db8-4938-8257-765c8e48623a>

get_citc_simulation

Get the active CITC reference simulation

Returns:

Simulation

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulations.get_citc_simulation()
<Simulation my_sim b9125419-7c6e-41db-bba9-7d647d63943e>

get

Get an existing simulation

Arguments:

  • simulation_id str - Simulation ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Simulation

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulations.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Simulation my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing simulations

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulations.list()
[<Simulation sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Simulation sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new simulation

Arguments:

  • topology str | Topology - Topology or ID
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Simulation

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulations.create(topology=topology, title='my_sim')
<Simulation my_sim 01298e0c-4ef1-43ec-9675-93160eb29d9f>

SimulationInterface

Manage a simulation interface

json

Returns a JSON string representation of the simulation interface

refresh

Syncs the simulation interface with all values returned by the API

update

Update the simulation interface with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

SimulationInterfaceApi

High-level interface for the SimulationInterface API

get

Get an existing simulation interface

Arguments:

  • simulation_interface_id str - SimulationInterface ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

SimulationInterface

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationInterface 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing simulation interfaces

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_interfaces.list()
[<SimulationInterface c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationInterface 3134711d-015e-49fb-a6ca-68248a8d4aff>]

SimulationNode

Manage a simulation node

json

Returns a JSON string representation of the simulation node

refresh

Syncs the simulation node with all values returned by the API

update

Update the simulation node with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

create_instructions

Create instructions for the SimulationNode’s agent to execute

Arguments:

  • data str | list - Instruction data
  • executor str - Agent executor type
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

  • dict - Response JSON

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> simulation_node.create_instructions(data='echo foo', executor='shell')
{'id': '67f73552-ffdf-4e5f-9881-aeae227604a3'}

list_instructions

List all instructions for a SimulationNode

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> simulation_node.instructions.list()
[{'id': '56abc69b-489f-429a-aed9-600f26afc956'}, {'id': '7c9c3449-f071-4bbc-bb42-bef04e44d74e'}]

delete_instructions

Delete all instructions for a SimulationNode

Raises:

AirUnexpectedresponse - Instruction delete failed

Example:

>>> simulation_node.instructions.delete()

control

Sends a control command to the SimulationNode.

Arguments:

  • action str - Control command
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

  • dict - Response JSON

Example:

>>> simulation_node.control(action='reset')
{'result': 'success'}

rebuild

Rebuild the SimulationNode back to its initial state. All existing data will be lost.

reset

Reset the SimulationNode

SimulationNodeApi

Wrapper for the SimulationNode API

get

Get an existing simulation node

Arguments:

  • simulation_node_id str - SimulationNode ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

SimulationNode

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationNode my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing simulation nodes

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.simulation_nodes.list()
[<SimulationNode sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationNode sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]

SSHKey

Manage an SSH key

delete

Delete the key. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the key

refresh

Syncs the key with all values returned by the API

SSHKeyApi

High-level interface for the SSHKey API

list

List existing keys

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.ssh_keys.list()
[<SSHKey mykey c51b49b6-94a7-4c93-950c-e7fa4883591>, <SSHKey test_key 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Add a new public key to your account

Arguments:

  • name str - Descriptive name for the public key
  • public_key str - Public key
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

SSHKey

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.ssh_keys.create(name='my_pub_key', public_key='<key_string>')
<SSHKey my_pub_key 01298e0c-4ef1-43ec-9675-93160eb29d9f>

Token

Manage an API token

TokenApi

High-level interface for the Token API

list

List existing tokens

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedResponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.api_tokens.list()
[<Token mytoken c51b49b6-94a7-4c93-950c-e7fa4883591>, <Token test_token 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Add a new api token to your account

Arguments:

  • name str - Descriptive name for the public key
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Token

Raises:

AirUnexpectedResponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.api_tokens.create(name='my_api_token')
<Token my_api_token 01298e0c-4ef1-43ec-9675-93160eb29d9f>

delete

Delete the token

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

string

Raises:

AirUnexpectedresponse - Received an unexpected response from the Cumulus AIR API (404): {“detail”:“Not found."}

Example:

>>> air.api_tokens.delete()
'SUCCESS'

Topology

Manage a topology

delete

Delete the topology. Once successful, the object should no longer be used and will raise AirDeletedObject when referenced.

Raises:

AirUnexpectedresponse - Delete failed

json

Returns a JSON string representation of the topology

refresh

Syncs the topology with all values returned by the API

update

Update the topology with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

add_permission

Adds permission for a given user to this topology.

Arguments:

  • email str - Email address of the user being given permission
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Permission

Example:

>>> topology.add_permission('mrobertson@nvidia.com', write_ok=True)
<Permission 217bea68-7048-4262-9bbc-b98ab16c603e>

TopologyApi

High-level interface for the Topology API

get

Get an existing topology

Arguments:

  • topology_id str - Topology ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Topology

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.topologies.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Topology my_network 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing topologies

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.topologies.list()
[<Topology my_network1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Topology my_network2 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new topology. The caller must provide either dot (recommended) or json.

Arguments:

  • dot str | fd, optional - Topology in DOT format. This can be passed as a string containing the raw DOT data, a path to the DOT file on your local disk, or as a file descriptor for a local file
  • json dict, optional - Topology in JSON format

Returns:

Topology

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.topologies.create(dot='/tmp/my_net.dot')
<Topology my_net 01298e0c-4ef1-43ec-9675-93160eb29d9f>
>>> air.topologies.create(dot='graph "my sim" { "server1" [ function="server" os="generic/ubuntu1804"] }')
<Topology my_net 6256baa8-f54b-4190-85c8-1cc574590080>
>>> air.topologies.create(dot=open('/tmp/my_net.dot', 'r'))
<Topology my_net a3d09f12-56ff-4889-8e03-3b714d32c3e5>

Worker

Manage a worker

json

Returns a JSON string representation of the worker

refresh

Syncs the worker with all values returned by the API

update

Update the worker with the provided data

Arguments:

  • kwargs dict, optional - All optional keyword arguments are applied as key/value pairs in the request’s JSON payload

set_available

Sets a worker’s available value in AIR

Arguments:

available (bool)

WorkerApi

High-level interface for the Worker API

get

Get an existing worker

Arguments:

  • worker_id str - Worker ID
  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

Worker

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.workers.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Worker worker01 3dadd54d-583c-432e-9383-a2b0b1d7f551>

list

List existing workers

Arguments:

  • kwargs dict, optional - All other optional keyword arguments are applied as query parameters/filters

Returns:

list

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.workers.list()
[<Worker worker01 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Worker worker02 3134711d-015e-49fb-a6ca-68248a8d4aff>]

create

Create a new worker

Arguments:

  • cpu int - Number of vCPUs the worker can support
  • memory int - Amount of memory (in MB) a worker can support
  • storage int - Amount of storage (in GB) a worker can support
  • ip_address str - Internal IP address
  • port_range str - Range of ports available on the worker
  • username str - Worker username for API access
  • password str - Worker password for API access
  • kwargs dict, optional - All other optional keyword arguments are applied as key/value pairs in the request’s JSON payload

Returns:

Worker

Raises:

AirUnexpectedresponse - API did not return a 200 OK or valid response JSON

Example:

>>> air.workers.create(cpu=100, memory=200000, storage=1000, ip_address='10.1.1.1', port_range='10000-30000', username='worker01', password='secret')
<Worker my_sim 01298e0c-4ef1-43ec-9675-93160eb29d9f>