Air API 和 Python SDK
本项目提供了一个 Python SDK,用于与 NVIDIA Air API 交互。
使用 SDK
先决条件
SDK 需要 Python 3.7 或更高版本。安装 SDK 最安全的方法是在 Python 3.7 中设置虚拟环境。例如
$ apt-get install python3.7
$ python3.7 -m pip install virtualenv
$ python3.7 -m virtualenv venv37
$ . venv37/bin/activate
安装 SDK
要安装 SDK,请使用 pip
$ python3 -m pip install air-sdk
身份验证选项
身份验证需要 API 令牌、用户名/密码或持有者令牌。
API 令牌
生成 API 令牌的最简单方法是使用 Air UI。
生成令牌后
>>> air = AirApi(username='<username>', password='<api_token>')
API 需要使用 API 令牌来生成持有者令牌
curl --request POST 'https://air.nvidia.com/api/v1/login/' --form 'username="<user>"' --form 'password="<api_token>"'
返回的持有者令牌用于后续的身份验证
curl --location --request <http_request>' \
--header 'Authorization: Bearer <bearer_token>'
其他身份验证选项
用户名和密码
用户名和密码身份验证仅对 Air 服务帐户有效,该帐户只能由 NVIDIA Air 管理员创建。管理员提供用户名和密码后
>>> air = AirApi(username='<username>', password='<password>')
持有者令牌
对于 SDK 使用,NVIDIA 建议使用 API 令牌 而不是持有者令牌。但是,持有者令牌可用于测试和执行不需要长期 API 令牌的操作。要使用持有者令牌,调用用户必须拥有 nvidia.com 帐户,并且之前已批准访问 NVIDIA Air。获得令牌后
>>> air = AirApi(bearer_token='<bearer_token>')
使用持有者令牌进行身份验证并获取所有模拟的列表
curl --location --request GET 'https://air.nvidia.com/api/v1/simulation/' \
--header 'Authorization: Bearer <bearer_token>'
服务帐户
NVIDIA 内部用户可以使用 SSA 客户端 ID 作为服务帐户进行身份验证。首先,必须生成有效的持有者令牌。
curl --user "$CLIENT_ID:$CLIENT_SECRET" --request POST $AIR_TOKEN_URL --header "Content-Type: application/x-www-form-urlencoded" --data-urlencode "grant_type=client_credentials" --data-urlencode "scope=api-access"
{"access_token":"eyJraWQ...","token_type":"bearer","expires_in":900,"scope":"api-access"}
将 $CLIENT_ID、$CLIENT_SECRET 和 $AIR_TOKEN_URL 替换为您在客户端注册期间生成的值。有关更多详细信息,请参阅关于使用服务帐户的内部文档。
获得持有者令牌后,可以像 Air 持有者令牌 一样使用它
示例
列出所有模拟
SDK 提供了各种辅助方法用于与 API 交互。下面的示例展示了如何使用 SDK 和 cURL 通过 API 列出所有模拟
>>> air.simulations.list()
[<Simulation sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Simulation sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
curl --request GET 'https://air.nvidia.com/api/v1/simulation/' \
--header 'Authorization: Bearer <bearer_token>'
获取特定模拟
要获取 ID 为 c51b49b6-94a7-4c93-950c-e7fa4883591 的模拟
>>> sim1 = air.simulations.get('c51b49b6-94a7-4c93-950c-e7fa4883591')
>>> print(sim1.title)
My Sim
curl --request GET 'https://air.nvidia.com/api/v1/simulation/?id=c51b49b6-94a7-4c93-950c-e7fa4883591' \
--header 'Authorization: Bearer <bearer_token>'
创建模拟
使用自定义拓扑和自定义组织创建一个模拟。
示例 topology.dot 文件
graph "sample_topology" {
"cumulus0" [ memory="1024" os="cumulus-vx-4.4.0" cpu="1"]
"cumulus1" [ memory="1024" os="cumulus-vx-4.4.0" cpu="1"]
"cumulus0":"swp1" -- "cumulus1":"swp1"
"cumulus0":"swp2" -- "cumulus1":"swp2"
}
创建组织,然后创建并启动模拟
目前仅支持 NVIDIA 用户创建组织。
>>> from air_sdk import AirApi
>>> user = 'user@nvidia.com'
>>> api_token = 'fake_api_token'
>>> air = AirApi(username=user, password=api_token)
>>> dot_file_path = '/tmp/topology.dot'
>>> org_name = 'My Organization'
>>> org = air.organizations.create(name=org_name, members=[{'username': f'{user}', 'roles': ['Organization Admin']}])
>>> simulation = air.simulations.create(topology_data=dot_file_path, organization=org)
创建组织
curl --location --request POST 'https://air.nvidia.com/api/v1/organization/' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "My Organization",
"members": [
{
"username": "user@nvidia.com"
}
]
}'
创建并启动模拟
curl --location --request POST 'https://air.nvidia.com/api/v2/simulation/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"topology_data": "graph \"My Simulation\" {\n \"cumulus0\" [ memory=\"1024\" os=\"cumulus-vx-5.7.0\" cpu=\"1\" ]\n \"cumulus1\" [ memory=\"1024\" os=\"cumulus-vx-5.7.0\" cpu=\"1\"]\n \"cumulus0\":\"swp1\" -- \"cumulus1\":\"swp1\"\n \"cumulus0\":\"swp2\" -- \"cumulus1\":\"swp2\"\n}\n",
"organization": "<organization_uuid>"
}'
可选地,在模拟创建期间还可以包含 ZTP 脚本。该脚本将自动由 oob-mgmt-server 托管,并由支持 ZTP 的节点获取。
>>> ztp_contents = '<ztp_script_content_here>'
>>> simulation = air.simulations.create(topology_data=dot_file_path, ztp_script=ztp_contents)
curl --location --request POST 'https://air.nvidia.com/api/v2/simulation/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"topology_data": "graph \"My Simulation\" {\n \"cumulus0\" [ memory=\"1024\" os=\"cumulus-vx-5.7.0\" cpu=\"1\" ]\n \"cumulus1\" [ memory=\"1024\" os=\"cumulus-vx-5.7.0\" cpu=\"1\"]\n \"cumulus0\":\"swp1\" -- \"cumulus1\":\"swp1\"\n \"cumulus0\":\"swp2\" -- \"cumulus1\":\"swp2\"\n}\n",
"ztp_script": "<ztp_script_content_here>"
}'
删除模拟
>>> from air_sdk import AirApi
>>> air = AirApi(username='<user>', password='<api_token>')
>>> simulation = air.simulations.get('<simulation_uuid>')
>>> simulation.delete()
查找模拟
curl --request GET 'https://air.nvidia.com/api/v1/simulation/?id=<simulation_uuid>' \
--header 'Authorization: Bearer <bearer_token>'
删除模拟
curl --request POST 'https://air.nvidia.com/api/v1/simulation/<simulation_uuid>/control/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"action": "destroy",
}'
启用 SSH 服务
唤醒休眠的模拟并启用 SSH 连接到 oob-mgmt-server。
查找并加载模拟
>>> from air_sdk import AirApi
>>> air = AirApi(username='<user>', password='<api_token>')
>>> simulation = air.simulations.get('<simulation_uuid>')
>>> simulation.load()
加载模拟
curl --request POST 'https://air.nvidia.com/api/v1/simulation/<simulation_id>/control/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"action": "load",
"start": true
}'
模拟 ID 将在稍后再次使用。
启用 ssh 连接到 oob-mgmt-server 的管理端口,并打印 ssh 到设备的命令
>>> service_name = 'oob-mgmt-server SSH'
>>> interface = 'oob-mgmt-server:eth0'
>>> dest_port = 22
>>> service = air.services.create(name=service_name, interface=interface, simulation=simulation, dest_port=dest_port)
>>> print(f'ssh -p {service.src_port} {service.os_default_username}@{service.host}')
ssh -p 15738 ubuntu@worker.air.nvidia.com
要启用 SSH 连接到节点的接口,API 需要特定的 simulation-interface 对象的 uuid 或资源 URL。在此示例中,simulation_id 为 47c91cdd-93d2-42b7-9c94-1580a9e49a88,simulation-interface 是 oob-mgmt-server 节点上的 eth0。
要查找模拟接口 uuid,首先查找节点对象
curl --request GET 'https://air.nvidia.com/api/v1/node/?name=oob-mgmt-server&simulation=47c91cdd-93d2-42b7-9c94-1580a9e49a88' \
--header 'Authorization: Bearer <bearer_token>'
这将返回一个包含一个节点的列表。该节点有一个接口列表
[{
"url": "https://air.nvidia.com/api/v1/node/f2b54dc7-2ec0-40de-b04f-8a2b8655814a/",
"id": "f2b54dc7-2ec0-40de-b04f-8a2b8655814a",
"name": "oob-mgmt-server",
"os": "https://air.nvidia.com/api/v1/image/40000000-0000-0000-8050-000000000001/",
"interfaces": [
{
"url": "https://air.nvidia.com/api/v1/interface/fc92eb67-0abb-4a36-8458-2ecf5cc8ec75/",
"id": "fc92eb67-0abb-4a36-8458-2ecf5cc8ec75", <--------
"name": "eth0",
"mac_address": "04:ca:04:5a:6c:17",
"outbound": true,
"index": 5
}
],
"topology": "https://air.nvidia.com/api/v1/topology/0fbdfdef-c284-4287-85aa-1499fef18a3b/"
}]
查找接口 ID 并使用它来解析 simulation-interface
curl --request GET 'https://air.nvidia.com/api/v1/simulation-interface/?original=fc92eb67-0abb-4a36-8458-2ecf5cc8ec75' \
--header 'Authorization: Bearer <bearer_token>'
[{
"url": "https://air.nvidia.com/api/v1/simulation-interface/bc084dc3-b009-430e-a49a-0699362f955a/",
"id": "bc084dc3-b009-430e-a49a-0699362f955a", <--------
"node": "https://air.nvidia.com/api/v1/simulation-node/fbfe474d-44ba-4ff5-b933-658a33857c96/",
"original": "https://air.nvidia.com/api/v1/interface/fc92eb67-0abb-4a36-8458-2ecf5cc8ec75/",
"link_up": false,
"services": [
"https://air.nvidia.com/api/v1/service/af474fff-4bc9-4590-9f68-0cd3c3b021da/"
],
...
}]
最后,在 interface 参数中使用 simulation-interface ID,并在 simulation ID 中创建 ssh 服务
curl --request POST 'https://air.nvidia.com/api/v1/service/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "oob-mgmt-server SSH",
"simulation": "47c91cdd-93d2-42b7-9c94-1580a9e49a88",
"interface": "bc084dc3-b009-430e-a49a-0699362f955a",
"dest_port": 22
}'
响应类似于以下内容
{
"url": "https://air.nvidia.com/api/v1/service/af474fff-4bc9-4590-9f68-0cd3c3b021da/",
"id": "af474fff-4bc9-4590-9f68-0cd3c3b021da",
"name": "oob-mgmt-server SSH",
"simulation": "https://air.nvidia.com/api/v1/simulation/47c91cdd-93d2-42b7-9c94-1580a9e49a88/",
"interface": "https://air.nvidia.com/api/v1/simulation-interface/bc084dc3-b009-430e-a49a-0699362f955a/",
"dest_port": 22,
"src_port": 15502, <--------
"link": "",
"service_type": "other",
"node_name": "oob-mgmt-server",
"interface_name": "eth0",
"host": "worker.air.nvidia.com", <--------
"os_default_username": "ubuntu" <--------
}
使用以下模板生成 SSH 命令
ssh -p <src_port> <os_default_username>@<host>
该模板生成类似于以下的命令
ssh -p 15502 ubuntu@worker.air.nvidia.com
使用 oob-mgmt-server 作为跳板机,并通过 oob-mgmt-server ssh 连接到模拟中的另一个节点
>>> ssh -J ubuntu@worker.air.nvidia.com:15738 user@hostname
上传镜像并创建拓扑
上传自定义镜像并使用该镜像创建拓扑。
目前仅支持 NVIDIA 用户上传镜像。
上传并创建镜像对象
>>> from air_sdk import AirApi
>>> user = 'user@nvidia.com'
>>> api_token = 'fake_api_token'
>>> air = AirApi(username=user, password=api_token)
>>> image_name = 'My Image'
>>> filename = '/Users/user/my_image.qcow2'
>>> # Is the air-agent enabled in the Image by default?
>>> agent_enabled = False
>>> # Should the image be published and accessible to all users?
>>> default_username = 'admin'
>>> default_password = 'admin'
>>> organization = '<organization_uuid>'
>>> version = '1.0.0'
>>> cpu_arch = 'x86'
>>> image = air.images.create(name=image_name, filename=filename, agent_enabled=agent_enabled, default_username=default_username, default_password=default_password, organization=organization, version=version, cpu_arch=cpu_arch)
创建镜像对象
curl --request POST 'https://air.nvidia.com/api/v1/image/' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "<image_name>",
"base": "false",
"agent_enabled": "false",
"cpu_arch": "x86",
"default_username": "admin",
"organization": "<organization_id>",
"simx": "false",
"provider": "VM",
"version": "1.0.0"
}'
响应包含一个镜像上传 URL
{
"url": "https://air.nvidia.co,/api/v1/image/3d9a34e6-fd64-47bc-a65d-8a30f9f3ddc7/",
"id": "3d9a34e6-fd64-47bc-a65d-8a30f9f3ddc7",
...
"upload_url": "https://air.nvidia.com/api/v1/image/3d9a34e6-fd64-47bc-a65d-8a30f9f3ddc7/upload/", <--------
...
}
使用提供的 upload_url 将本地镜像文件上传到 Air
curl --request PUT 'https://air.nvidia.com/api/v1/image/3d9a34e6-fd64-47bc-a65d-8a30f9f3ddc7/upload/' -F filename='@/Users/admin/fake_image.qcow2' \
--header 'Authorization: Bearer <bearer_token>'
在自定义拓扑中使用您创建的镜像
>>> topology_name = 'My Topology'
>>> node_name = 'server01'
>>> dot_graph = f'graph \"{topology_name}\" {{ \"{node_name}\" [ os=\"{image_name}\"] }}'
>>> simulation = air.simulations.create(topology_data=dot_graph)
curl --request POST 'https://air.nvidia.com/api/v2/simulation/' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"topology_data": "graph \"My Topology\" {\n \"cumulus0\" [ memory=\"1024\" os=\"<image_uuid>\" cpu=\"1\" ]\n \"cumulus1\" [ memory=\"1024\" os=\"<image_uuid>\" cpu=\"1\" ]\n \"cumulus0\":\"swp1\" -- \"cumulus1\":\"swp1\"\n \"cumulus0\":\"swp2\" -- \"cumulus1\":\"swp2"\n}\n"
}'
节点指令
您可以使用节点指令通过 API 配置已安装 Air 代理的模拟节点。Air 代理存在于使用 agent_enabled
标志设置为 true 的镜像的模拟节点中。
在创建(但未启动)模拟后,获取要配置的模拟节点的 ID
查找模拟的模拟节点,并获取要配置的特定模拟节点。在本例中,节点名为 sample-node
>>> simnodes = air.simulation_nodes.list(simulation=simulation)
>>> for simnode in simnodes:
>>> if 'sample-node' == simnode.name:
>>> sample_node = simnode
编辑 sample-node 上的 /etc/network/interfaces 并使用 ifreload 应用配置
>>> eni_contents = '<string_containing_desired_etc_network_interfaces_content>''
>>> post_cmd = 'ifreload -a'
>>> data = {'/etc/network/interfaces': eni_contents, 'post_cmd': post_cmd}
>>> sample_node.create_instructions(data=json.dumps(data), executor='file')
编辑 sample-node 上的 /etc/frr/frr.conf
并重启 FRR
>>> frr_contents = '<frr_conf_config_here>'
>>> post_cmd = 'systemctl restart frr'
>>> data = {'/etc/frr/frr.conf': frr_contents, 'post_cmd':post_cmd}
>>> sample_node.create_instructions(data=json.dumps(data), executor='file')
要执行命令而不是填充文件内容,请使用 shell
执行器而不是 file
>>> data = 'ip link set swp1 ip address 192.168.100.2/24'
>>> sample_node.create_instructions(data=data, executor='shell')
向名为 oob-mgmt-server 的节点添加 ZTP 脚本
>>> oob_mgmt_server = air.simulation_nodes.list(simulation=simulation, name='oob-mgmt-server')[0]
>>> ztp_contents = '<ztp_script_content_here>'
>>> data = {'/var/www/html/cumulus-ztp': ztp_contents}
>>> oob_mgmt_server.create_instructions(data=json.dumps(data), executor='file')
最后,启动模拟
>>> simulation.start()
查找模拟的节点
curl --request GET 'https://air.nvidia.com/api/v1/simulation-node/?simulation=<simulation_id>' \
--header 'Authorization: Bearer <bearer_token>'
创建并发送节点指令
curl --request POST 'https://air.nvidia.com/api/v1/simulation-node/<simulation_node_id>/instructions/' \
--header 'Authorization: Bearer <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"executor": "file",
"data": "{'\''/etc/frr/frr.conf'\'': '\''<frr.conf contents>'\'', '\''post_cmd'\'':,'\''systemctl restart frr'\''}"
}'
或者,使用 shell 执行器而不是 file 来运行命令
curl --request POST 'https://air.nvidia.com/api/v1/simulation-node/<simulation_node_id>/instructions/' \
--header 'Authorization: <bearer_token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"executor": "shell",
"data": "ip link set swp1 ip address 192.168.100.2/24"
}'
为了避免在运行 5.0.0 或更早版本的 Cumulus Linux 节点上出现竞争条件,请在启动模拟之前安排节点指令。如果您不按此顺序执行步骤,则指令可能无法完成。
使用 Cloud-init
Cloud-init 允许用户在首次启动时配置其节点。Cloud-init 可以运行用户脚本来执行各种配置任务。
有关用户数据和元数据文件的信息和示例,请参阅 cloud-init 文档。
在创建(但未启动)模拟后,获取要配置的特定模拟节点。在本例中,节点名为 node-1 和 node-2
>>> sim_node_1 = air.simulation_nodes.list(name='node-1', simulation=simulation).pop()
>>> sim_node_2 = air.simulation_nodes.list(name='node-2', simulation=simulation).pop()
创建用户数据和元数据用户配置
>>> USER_DATA = """#cloud-config
...
... users:
... - default
... - name: custom-user
... passwd: "$6$kW4vfBM9kGgq4hr$TFtHW7.3jOECR9UCBuw9NrdSMJETzSVoNQGcVv2y.RqRUzWDEtYhYRkGvIpB6ml1fh/fZEVIgKbSXI9L1B6xF." # 'possible'
... shell: /bin/bash
... lock-passwd: false
... ssh_pwauth: True
... chpasswd: { expire: False }
... sudo: ALL=(ALL) NOPASSWD:ALL
... groups: users, admin
... """
>>> sim_node_1_metadata = air.user_configs.create(name='sim-node-1-metadata', kind='cloud-init-meta-data', organization=org, content='local-hostname: cloud-init-node-1')
>>> sim_node_2_metadata = air.user_configs.create(name='sim-node-1-metadata', kind='cloud-init-meta-data', organization=org, content='local-hostname: cloud-init-node-2')
>>> sim_node_shared_userdata = air.user_configs.create(name='sim-node-shared-userdata', kind='cloud-init-user-data', organization=org, content=USER_DATA)
为模拟节点设置 cloud-init 分配
>>> sim_node_1.set_cloud_init_assignment({'user_data': sim_node_shared_userdata, 'meta_data': sim_node_1_metadata})
>>> sim_node_2.set_cloud_init_assignment({'user_data': sim_node_shared_userdata, 'meta_data': sim_node_2_metadata})
最后,启动模拟
>>> simulation.start()
调整请求超时
默认情况下,SDK 为所有 API 请求实现以下超时
connect_timeout
为 16 秒,用于建立与服务器的连接。read_timeout
为 61 秒,用于接收对请求的响应。
您可以在实例化 AirApi
客户端后调整这些值
>>> air = AirApi(username='<username>', password='<api_token>')
>>> air.client.default_connect_timeout = 30
>>> air.client.default_read_timeout = 120
开发
非常欢迎对 SDK 做出贡献。所有代码在合并之前都必须通过 linting 和单元测试。
要求
python3 -m pip install -r requirements-dev.txt
代码检查
pylint **/*.py
单元测试
./unit_test.sh
生成文档
pydoc-markdown
SDK 参考指南
帐户
管理帐户
json
返回帐户的 JSON 字符串表示形式
刷新
将帐户与 API 返回的所有值同步
AccountApi
Account API 的高级接口
get
获取现有帐户
参数:
account_id
str - 帐户 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.accounts.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Account mrobertson@nvidia.com 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有帐户
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.accounts.list()
[<Account mrobertson@nvidia.com c51b49b6-94a7-4c93-950c-e7fa4883591>, <Account nmitchell@nvidia.com 3134711d-015e-49fb-a6ca-68248a8d4aff>]
首选项
获取帐户首选项
返回:
dict
- 响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.accounts.preferences()
{"baz": true, "foo": false}
Cumulus AIR API 模块
AirSession
requests.Session 的包装器
rebuild_auth
仅允许在 nvidia.com 和 cumulusnetworks.com 之间共享凭据
AirApi
API 客户端实例的主要接口
__init__
创建一个新的 API 客户端实例。调用者必须提供 username
和 password
或 bearer_token
。password
参数可以是 API 令牌或服务帐户密码。
参数:
username
str, 可选 - 用户名password
str, 可选 - 密码或 API 令牌bearer_token
str, 可选 - 预生成的持有者令牌api_url
str, 可选 - 默认 = https://air.nvidia.com/api/api_version
str - 默认 = v1
authorize
使用预生成的 API 令牌、服务帐户用户名/密码或预生成的持有者令牌授权 API 客户端。调用者必须传递有效的 bearer_token
或 username
和 password
。password
参数可以是 API 令牌或服务帐户密码。成功授权后,所有后续 API 调用都将包含 AIR API 提供的授权令牌。注意: 这在实例化 AirApi 对象时会自动调用一次。
参数:
bearer_token
str, 可选 - 预生成的持有者令牌username
str, 可选 - 用户名password
str, 可选 - 密码或 API 令牌
引发:
ValueError - 调用者未传递令牌或用户名/密码
get_token
为给定的用户名和密码获取新的持有者令牌
参数:
username
str - 用户名password
str - 密码
返回:
str
- 持有者令牌
引发:
AirAuthorizationError
- API 未返回令牌JSONDecodeError
- API 的响应不是有效的 JSON 对象
get
GET 请求的包装器方法
post
POST 请求的包装器方法
put
PUT 请求的包装器方法
patch
PATCH 请求的包装器方法
delete
DELETE 请求的包装器方法
容量
查看平台容量
json
返回容量的 JSON 字符串表示形式
刷新
将容量与 API 返回的所有值同步
CapacityApi
Simulation API 的高级接口
get
获取 Simulation
的当前平台容量
参数:
simulation_id
str |Simulation
- 模拟或 ID
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.capacity.get(simulation)
<Capacity 30>
演示
查看演示
json
返回演示的 JSON 字符串表示形式
刷新
将演示与 API 返回的所有值同步
DemoApi
Demo API 的高级接口
get
获取现有演示
参数:
demo_id
str - 演示 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.demos.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Demo EVPN 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有演示
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.demos.list()
[<Demo EVPN c51b49b6-94a7-4c93-950c-e7fa4883591>, <Demo Challenges 3134711d-015e-49fb-a6ca-68248a8d4aff>]
AIR SDK 的自定义异常
AirError
基类异常类。所有自定义异常都应从此类继承。
AirAuthorizationError
当与 API 的授权失败时引发。
AirUnexpectedResponse
当 API 返回意外响应时引发。
AirForbiddenError
当 API 调用返回 403 Forbidden 错误时引发
AirObjectDeleted
当访问先前实例化的对象(该对象已被删除)时引发
镜像
管理镜像
复制
将镜像复制到另一个组织。
参数:
organization
str |Organization
- 应在其中复制镜像的组织
返回:
引发:
AirUnexpectedresponse
- 复制失败
delete
删除镜像。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回镜像的 JSON 字符串表示形式
刷新
将镜像与 API 返回的所有值同步
更新
使用提供的数据更新镜像
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
发布
发布镜像以供公开使用
参数:
contact
str - 与此镜像关联的联系人的电子邮件地址。
引发:
AirUnexpectedresponse
- 发布失败
取消发布
从公开使用中取消发布镜像
引发:
AirUnexpectedresponse
- 取消发布失败
上传
上传镜像文件
参数:
filename
str - 本地镜像的绝对路径
引发:
AirUnexpectedresponse
- 上传失败
ImageApi
Image API 的高级接口
get
获取现有镜像
参数:
image_id
str - 镜像 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.images.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Image cumulus-vx-4.2.1 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有镜像
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.images.list()
[<Image cumulus-vx-4.2.1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Image generic/ubuntu18.04 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新镜像
参数:
name
str - 镜像名称organization
str |Organization
-Organization
或 IDfilename
str, 可选 - 应上传的本地文件的绝对路径kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> image = air.images.create(name='my_image', filename='/tmp/my_image.qcow2', agent_enabled=False, default_username='user', default_password='password', organization=org, version='1.0.0', cpu_arch='x86')
>>> image
<Image my_image 01298e0c-4ef1-43ec-9675-93160eb29d9f>
>>> image.upload_status
'COMPLETE'
>>> alt_img = air.images.create(name='my_alt_img', filename='/tmp/alt_img.qcow2', agent_enabled=False, default_username='user', default_password='password', organization=org, version='1.0.0', cpu_arch='x86')
>>> alt_img.upload_status
'FAILED'
接口
查看接口
json
返回接口的 JSON 字符串表示形式
刷新
将接口与 API 返回的所有值同步
InterfaceApi
Interface API 的高级接口
get
获取现有接口
参数:
interface_id
str - 接口 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Interface eth0 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有接口
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.interfaces.list()
[<Interface eth0 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Interface eth1 3134711d-015e-49fb-a6ca-68248a8d4aff>]
SimulationInterface 模块
SimulationInterface
管理模拟接口
json
返回模拟接口的 JSON 字符串表示形式
刷新
将模拟接口与 API 返回的所有值同步
更新
使用提供的数据更新模拟接口
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
SimulationInterfaceApi
SimulationInterface API 的高级接口
get
获取现有模拟接口
参数:
simulation_interface_id
str - SimulationInterface IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationInterface 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有模拟接口
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_interfaces.list()
[<SimulationInterface c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationInterface 3134711d-015e-49fb-a6ca-68248a8d4aff>]
作业
管理作业
json
返回作业的 JSON 字符串表示形式
刷新
将作业与 API 返回的所有值同步
更新
使用提供的数据更新作业
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
JobApi
Job API 的高级接口
get
获取现有作业
参数:
job_id
str - 作业 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.jobs.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Job START 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有作业
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.jobs.list()
[<Job START c51b49b6-94a7-4c93-950c-e7fa4883591>, <Job STOP 3134711d-015e-49fb-a6ca-68248a8d4aff>]
链接
管理链接
delete
删除链接。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回链接的 JSON 字符串表示形式
刷新
将链接与 API 返回的所有值同步
更新
使用提供的数据更新链接
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
LinkApi
Link API 的高级接口
get
获取现有链接
参数:
link_id
str - 链接 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.links.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Link 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有链接
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.links.list()
[<Link c51b49b6-94a7-4c93-950c-e7fa4883591>, <Link 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新链接
参数:
topology
str |Topology
-Topology
或 IDinterfaces
list -Interface
对象或 ID 的列表kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.links.create(topology=topology, interfaces=[intf1, 'fd61e3d8-af2f-4735-8b1d-356ee6bf4abe'])
<Link 01298e0c-4ef1-43ec-9675-93160eb29d9f>
登录
查看登录信息
json
返回登录信息的 JSON 字符串表示形式
刷新
将登录信息与 API 返回的所有值同步
LoginApi
Login API 的高级接口
get
获取登录信息或启动 OAuth 请求。这等效于 login.list()
。
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.login.get()
<Login>
list
获取登录信息或启动 OAuth 请求。这等效于 login.get()
。
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.login.get()
<Login>
市场
查看市场演示
json
返回市场演示的 JSON 字符串表示形式
刷新
将市场演示与 API 返回的所有值同步
MarketplaceApi
Marketplace API 的高级接口
get
获取现有市场演示
参数:
demo_id
str - 市场演示 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.Marketplace.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Marketplace Demo EVPN 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有市场演示
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.marketplace.list()
[<Marketplace Demo EVPN c51b49b6-94a7-4c93-950c-e7fa4883591>, <Marketplace Demo Challenges 3134711d-015e-49fb-a6ca-68248a8d4aff>]
节点
管理节点
delete
删除节点。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回节点的 JSON 字符串表示形式
刷新
将节点与 API 返回的所有值同步
更新
使用提供的数据更新节点
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
NodeApi
Node API 的高级接口
get
获取现有节点
参数:
node_id
str - 节点 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Node server 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有节点
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.nodes.list()
[<Node server c51b49b6-94a7-4c93-950c-e7fa4883591>, <Node switch 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新节点
参数:
name
str - 节点名称topology
str |Topology
-Topology
或 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.nodes.create(name='server', topology=topology)
<Node server 01298e0c-4ef1-43ec-9675-93160eb29d9f>
SimulationNode
管理 SimulationNode
json
返回模拟节点的 JSON 字符串表示形式
刷新
将模拟节点与 API 返回的所有值同步
更新
使用提供的数据更新模拟节点
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
create_instructions
为 SimulationNode
的代理创建要执行的指令
参数:
data
str | list - 指令数据executor
str - 代理执行器类型kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
dict
- 响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.create_instructions(data='echo foo', executor='shell')
{'id': '67f73552-ffdf-4e5f-9881-aeae227604a3'}
list_instructions
列出 SimulationNode
的所有指令
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.list_instructions()
[{'id': '56abc69b-489f-429a-aed9-600f26afc956'}, {'id': '7c9c3449-f071-4bbc-bb42-bef04e44d74e'}]
delete_instructions
删除 SimulationNode
的所有指令
引发:
AirUnexpectedresponse
- 指令删除失败
示例:
>>> simulation_node.delete_instructions()
set_cloud_init_assignment
设置特定节点的 cloud-init 脚本分配
参数:
user_data
str - UserConfig ID。UserConfig 必须是 ‘cloud-init-user-data’ 类型meta_data
str - UserConfig ID。UserConfig 必须是 ‘cloud-init-meta-data’ 类型
返回:
dict
- 响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.set_cloud_init_assignment({'user_data': '09b168b8-f9dd-408c-b3c6-bbecf6a43a09', 'meta_data': 'a19a8715-b46b-4599-81e6-379adebe4bb4'})
{'simulation_node': 'a44894a4-d805-42e2-a07f-7fd5fb0ea154', 'user_data': '09b168b8-f9dd-408c-b3c6-bbecf6a43a09', 'meta_data': 'a19a8715-b46b-4599-81e6-379adebe4bb4', 'user_data_name': 'userdata1', 'meta_data_name': 'metadata1'}
>>> simulation_node.set_cloud_init_assignment({'user_data': userdata, 'meta_data': metadata})
{'simulation_node': 'a44894a4-d805-42e2-a07f-7fd5fb0ea154', 'user_data': '09b168b8-f9dd-408c-b3c6-bbecf6a43a09', 'meta_data': 'a19a8715-b46b-4599-81e6-379adebe4bb4', 'user_data_name': 'userdata1', 'meta_data_name': 'metadata1'}
>>> simulation_node.set_cloud_init_assignment({'user_data': userdata, 'meta_data': None})
{'simulation_node': 'a44894a4-d805-42e2-a07f-7fd5fb0ea154', 'user_data': '09b168b8-f9dd-408c-b3c6-bbecf6a43a09', 'meta_data': None, 'user_data_name': 'userdata1', 'meta_data_name': None}
>>> sim.start()
get_cloud_init_assignment
获取特定节点的 cloud-init 分配
返回:
dict
- 响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.get_cloud_init_assignment()
{'simulation_node': 'a44894a4-d805-42e2-a07f-7fd5fb0ea154', 'user_data': 09b168b8-f9dd-408c-b3c6-bbecf6a43a09', 'meta_data': 'a19a8715-b46b-4599-81e6-379adebe4bb4', 'user_data_name': 'userdata1', 'meta_data_name': 'metadata1'}
控制
向 SimulationNode
发送控制命令。
参数:
action
str - 控制命令kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
dict
- 响应 JSON
示例:
>>> simulation_node.control(action='reset')
{'result': 'success'}
重建
将 SimulationNode
重建回其初始状态。所有现有数据都将丢失。
重置
重置 SimulationNode
SimulationNodeApi
SimulationNode API 的包装器
get
获取现有模拟节点
参数:
simulation_node_id
str - SimulationNode IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationNode my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有模拟节点
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_nodes.list()
[<SimulationNode sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationNode sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
组织
管理组织
delete
删除组织。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回组织的 JSON 字符串表示形式
刷新
将组织与 API 返回的所有值同步
更新
使用提供的数据更新组织
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
add_member
向组织添加新成员
参数:
username
str - 要添加的用户的电子邮件地址roles
list, 可选 - 要分配给用户的角色列表。有效值为 ‘Organization Admin’ 或 ‘Organization Member’。如果未提供角色列表,则 ‘Organization Member’ 用作默认角色。
示例:
>>> organization.add_member('user1@nvidia.com')
>>> organization.add_member('user2@nvidia.com', roles=['Organization Admin'])
add_members
向组织添加新成员
参数:
members
list - 组织成员字典列表,格式为 {‘username’: <email_address>, ‘roles’: []}. ‘roles’ 是可选的,默认为 [‘Organization Member’] 可以是 ‘Organization Admin’ 或 ‘Organization Member’ 的值。
示例:
>>> organization.add_members([{'username': 'user1@nvidia.com', 'roles': ['Organization Admin']}, {'username': 'user2@nvidia.com'}])
remove_member
从组织中移除成员
参数:
username
str - 要移除的用户的电子邮件地址
示例:
>>> organization.remove_member('user1@nvidia.com')
remove_members
从组织中移除多个成员
参数:
members
list - 要移除的用户的电子邮件地址
示例:
>>> organization.remove_members(['user1@nvidia.com', 'user2@nvidia.com'])
OrganizationApi
Organization API 的高级接口
get
获取现有组织
参数:
organization_id
str - 组织 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.organizations.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Organization NVIDIA 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有组织
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.organizations.list()
[<Organization NVIDIA c51b49b6-94a7-4c93-950c-e7fa4883591>, <Organization Customer 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新组织
参数:
name
str - 组织名称members
list, 可选 - 组织成员字典列表,格式为 {‘username’: <email_address>, ‘roles’: []}. ‘roles’ 是可选的,默认为 [‘Organization Member’] 可以是 ‘Organization Admin’ 或 ‘Organization Member’ 的值。如果未提供成员列表,则默认情况下,调用用户的帐户将被设置为组织管理员。 kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.organizations.create(name='NVIDIA', members=[{'username': 'user1@nvidia.com', 'roles': ['Organization Admin']}, {'username': 'user2@nvidia.com'}])
<Organization NVIDIA 01298e0c-4ef1-43ec-9675-93160eb29d9f>
权限
管理权限
delete
删除权限。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回权限的 JSON 字符串表示形式
刷新
将权限与 API 返回的所有值同步
更新
使用提供的数据更新权限
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
PermissionApi
Permission API 的高级接口
创建
创建新权限。调用者必须提供 simulation
、topology
或 subject_id
参数:
email
str - 被授予权限的用户的电子邮件地址simulation
str |Simulation
, 可选 -Simulation
或 IDtopology
str |Topology
, 可选 -Topology
或 IDsubject_id
str |AirModel
, 可选 -AirModel
实例或 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> 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
获取现有权限
参数:
permission_id
str - 权限 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.permissions.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Permission 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有权限
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.permissions.list()
[<Permission c51b49b6-94a7-4c93-950c-e7fa4883591>, <Permission 3134711d-015e-49fb-a6ca-68248a8d4aff>]
资源预算
管理资源预算
json
返回预算的 JSON 字符串表示形式
刷新
将预算与 API 返回的所有值同步
更新
使用提供的数据更新预算
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
ResourceBudgetApi
ResourceBudget API 的高级接口
get
获取现有预算
参数:
budget_id
str - 资源预算 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.resource_budgets.get('c604c262-396a-48a0-a8f6-31708c0cff82')
<ResourceBudget c604c262-396a-48a0-a8f6-31708c0cff82>
list
列出现有预算
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.resource_budgets.list()
[<ResourceBudget c604c262-396a-48a0-a8f6-31708c0cff82>, <ResourceBudget 906675f7-8b8d-4f52-b59d-52847af2f0ef>]
服务
管理服务
delete
删除服务。成功后,该对象将不再使用,并在被引用时引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回服务的 JSON 字符串表示形式
刷新
将服务与 API 返回的所有值同步
更新
使用提供的数据更新服务
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
ServiceApi
Service API 的高级接口
get
获取现有服务
参数:
service_id
str - 服务 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.services.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Service SSH 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有服务
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.services.list()
[<Service SSH c51b49b6-94a7-4c93-950c-e7fa4883591>, <Service HTTP 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新服务
参数:
name
str - 服务名称interface
str |SimulationInterface
- 应为其创建服务的接口。这可以以下列格式之一提供SimulationInterface
对象SimulationInterface
的 ID- 格式为 ‘node_name:interface_name’ 的字符串
simulation
str |Simulation
-Simulation
或 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> 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>
模拟
管理模拟
json
返回模拟的 JSON 字符串表示形式
首选项
返回模拟首选项的 JSON 字符串表示形式
刷新
将模拟与 API 返回的所有值同步
更新
使用提供的数据更新模拟
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
create_service
为此模拟创建新服务
参数:
name
str - 服务名称interface
str |SimulationInterface
- 应为其创建服务的接口。这可以以下列格式之一提供SimulationInterface
对象SimulationInterface
的 ID- 格式为 ‘node_name:interface_name’ 的字符串
dest_port
int - 服务端口号kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
示例:
>>> 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
为此模拟的给定用户添加权限。
参数:
email
str - 被授予权限的用户的电子邮件地址kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
示例:
>>> simulation.add_permission('mrobertson@nvidia.com', write_ok=True)
<Permission 217bea68-7048-4262-9bbc-b98ab16c603e>
控制
向模拟发送控制命令。
参数:
action
str - 控制命令kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
dict
- 响应 JSON
示例:
>>> simulation.control(action='destroy')
{'result': 'success'}
加载
start()
的别名
启动
启动/加载模拟
停止
store()
的别名
存储
存储并关闭模拟电源
delete
删除模拟
SimulationApi
Simulation API 的高级接口
duplicate
复制/克隆现有模拟
参数:
simulation
str |Simulation
- 要复制的快照的模拟或 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
(Simulation
, dict): 新创建的模拟和响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulations.duplicate(simulation=simulation)
<Simulation my_sim 5ff3f0dc-7db8-4938-8257-765c8e48623a>
get_citc_simulation
获取活动的 CITC 参考模拟
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulations.get_citc_simulation()
<Simulation my_sim b9125419-7c6e-41db-bba9-7d647d63943e>
get
获取现有模拟
参数:
simulation_id
str - 模拟 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulations.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Simulation my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有模拟
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulations.list()
[<Simulation sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Simulation sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新模拟。调用者必须提供 topology
或 topology_data
。
参数:
topology
str |Topology
, 可选 -Topology
或 IDtopology_data
str | fd, optional - DOT 格式的拓扑。这可以作为包含原始 DOT 数据的字符串、本地磁盘上 DOT 文件的路径或本地文件的文件描述符传递kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulations.create(topology=topology, title='my_sim')
<Simulation my_sim 01298e0c-4ef1-43ec-9675-93160eb29d9f>
>>> air.simulations.create(topology_data='/tmp/my_net.dot', organization=my_org)
<Simulation my_sim c0a4c018-0b85-4439-979d-9814166aaeac>
>>> air.simulations.create(topology_data='graph "my_sim" { "server1" [ function="server" os="generic/ubuntu2204"] }', organization=my_org)
<Simulation my_sim b9c0c68e-d4bd-4e9e-8a49-9faf41efaf70>
>>> air.simulations.create(topology_data=open('/tmp/my_net.dot', 'r', encoding='utf-8')), organization=my_org)
<Simulation my_sim 86162934-baa7-4d9a-a826-5863f92b03ef>
SimulationInterface
管理模拟接口
json
返回模拟接口的 JSON 字符串表示形式
刷新
将模拟接口与 API 返回的所有值同步
更新
使用提供的数据更新模拟接口
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
SimulationInterfaceApi
SimulationInterface API 的高级接口
get
获取现有模拟接口
参数:
simulation_interface_id
str - SimulationInterface IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_interfaces.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationInterface 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有模拟接口
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_interfaces.list()
[<SimulationInterface c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationInterface 3134711d-015e-49fb-a6ca-68248a8d4aff>]
SimulationNode
管理模拟节点
json
返回模拟节点的 JSON 字符串表示形式
刷新
将模拟节点与 API 返回的所有值同步
更新
使用提供的数据更新模拟节点
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
create_instructions
为 SimulationNode
的代理创建要执行的指令
参数:
data
str | list - 指令数据executor
str - 代理执行器类型kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
dict
- 响应 JSON
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.create_instructions(data='echo foo', executor='shell')
{'id': '67f73552-ffdf-4e5f-9881-aeae227604a3'}
list_instructions
列出 SimulationNode
的所有指令
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> simulation_node.instructions.list()
[{'id': '56abc69b-489f-429a-aed9-600f26afc956'}, {'id': '7c9c3449-f071-4bbc-bb42-bef04e44d74e'}]
delete_instructions
删除 SimulationNode
的所有指令
引发:
AirUnexpectedresponse
- 指令删除失败
示例:
>>> simulation_node.instructions.delete()
控制
向 SimulationNode
发送控制命令。
参数:
action
str - 控制命令kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
dict
- 响应 JSON
示例:
>>> simulation_node.control(action='reset')
{'result': 'success'}
重建
将 SimulationNode
重建回其初始状态。所有现有数据都将丢失。
重置
重置 SimulationNode
SimulationNodeApi
SimulationNode API 的包装器
get
获取现有模拟节点
参数:
simulation_node_id
str - SimulationNode IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_nodes.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<SimulationNode my_sim 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有模拟节点
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.simulation_nodes.list()
[<SimulationNode sim1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <SimulationNode sim2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
SSH 密钥
管理 SSH 密钥
delete
删除密钥。成功后,该对象将不再使用,并且在被引用时将引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回密钥的 JSON 字符串表示形式
刷新
将密钥与 API 返回的所有值同步
SSHKeyApi
SSHKey API 的高级接口
list
列出现有密钥
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.ssh_keys.list()
[<SSHKey mykey c51b49b6-94a7-4c93-950c-e7fa4883591>, <SSHKey test_key 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
向您的帐户添加新的公钥
参数:
name
str - 公钥的描述性名称public_key
str - 公钥kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.ssh_keys.create(name='my_pub_key', public_key='<key_string>')
<SSHKey my_pub_key 01298e0c-4ef1-43ec-9675-93160eb29d9f>
令牌
管理 API 令牌
TokenApi
Token API 的高级接口
list
列出现有令牌
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedResponse
- API 未返回 200 OK 或有效的 JSON 响应
示例:
>>> air.api_tokens.list()
[<Token mytoken c51b49b6-94a7-4c93-950c-e7fa4883591>, <Token test_token 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
向您的帐户添加新的 API 令牌
参数:
name
str - 公钥的描述性名称kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedResponse
- API 未返回 200 OK 或有效的 JSON 响应
示例:
>>> air.api_tokens.create(name='my_api_token')
<Token my_api_token 01298e0c-4ef1-43ec-9675-93160eb29d9f>
delete
删除令牌
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
字符串
引发:
AirUnexpectedresponse
- 从 Cumulus AIR API 收到意外响应 (404): {“detail”:“Not found."}
示例:
>>> air.api_tokens.delete()
'SUCCESS'
拓扑
管理拓扑
delete
删除拓扑。成功后,该对象将不再使用,并且在被引用时将引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回拓扑的 JSON 字符串表示形式
刷新
将拓扑与 API 返回的所有值同步
更新
使用提供的数据更新拓扑
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
add_permission
为此拓扑添加给定用户的权限。
参数:
email
str - 被授予权限的用户的电子邮件地址kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
示例:
>>> topology.add_permission('mrobertson@nvidia.com', write_ok=True)
<Permission 217bea68-7048-4262-9bbc-b98ab16c603e>
TopologyApi
Topology API 的高级接口
get
获取现有拓扑
参数:
topology_id
str - 拓扑 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.topologies.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Topology my_network 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有拓扑
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.topologies.list()
[<Topology my_network1 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Topology my_network2 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新的拓扑。调用者必须提供 dot
(推荐) 或 json
。
参数:
dot
str | fd, optional - DOT 格式的拓扑。这可以作为包含原始 DOT 数据的字符串、本地磁盘上 DOT 文件的路径或本地文件的文件描述符传递json
dict, optional - JSON 格式的拓扑
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> 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>
工作节点
管理工作节点
json
返回工作节点的 JSON 字符串表示形式
刷新
将工作节点与 API 返回的所有值同步
更新
使用提供的数据更新工作节点
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
set_available
在 AIR 中设置工作节点的 available
值
参数:
可用 (bool)
WorkerApi
Worker API 的高级接口
get
获取现有工作节点
参数:
worker_id
str - 工作节点 IDkwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.workers.get('3dadd54d-583c-432e-9383-a2b0b1d7f551')
<Worker worker01 3dadd54d-583c-432e-9383-a2b0b1d7f551>
list
列出现有工作节点
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.workers.list()
[<Worker worker01 c51b49b6-94a7-4c93-950c-e7fa4883591>, <Worker worker02 3134711d-015e-49fb-a6ca-68248a8d4aff>]
创建
创建新的工作节点
参数:
cpu
int - 工作节点可以支持的 vCPU 数量memory
int - 工作节点可以支持的内存量(MB)storage
int - 工作节点可以支持的存储量(GB)ip_address
str - 内部 IP 地址port_range
str - 工作节点上可用的端口范围username
str - 用于 API 访问的工作节点用户名password
str - 用于 API 访问的工作节点密码kwargs
dict, 可选 - 所有其他可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> 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>
UserConfig
管理 UserConfig
delete
删除 UserConfig。成功后,该对象将不再使用,并且在被引用时将引发 AirDeletedObject
。
引发:
AirUnexpectedresponse
- 删除失败
json
返回 UserConfig 的 JSON 字符串表示形式。
刷新
将 UserConfig 与 API 返回的所有值同步
更新
使用提供的数据更新 UserConfig
参数:
kwargs
dict, 可选 - 所有可选关键字参数都作为请求的 JSON 有效负载中的键/值对应用
UserConfigApi
UserConfig API 的高级接口
list
列出现有 UserConfig 脚本
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
list
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.user_configs.list()
[<UserConfig userdata1 cloud-init-user-data 84ddf2da-7a09-4a3b-a2b9-09179f4668c8>]
创建
创建新的 UserConfig
参数:
name
str - UserConfig 名称kind
str - 必须为 ‘cloud-init-user-data’ 或 ‘cloud-init-meta-data’organization
str - 组织 IDcontent
str - 数据脚本的纯文本内容或现有文件的路径或打开的文件句柄
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> userdata = air.user_configs.create(name='userdata1', kind='cloud-init-user-data', organization=None, content='/tmp/userConfig-ex1.YML')
<UserConfig userdata1 cloud-init-user-data 09b168b8-f9dd-408c-b3c6-bbecf6a43a09>
>>> metadata = air.user_configs.create(name='metadata1', kind='cloud-init-meta-data', organization='3dadd54d-583c-432e-9383-a2b0b1d7f551', content='local-hostname: cloud-init-node')
<UserConfig metadata1 cloud-init-meta-data a19a8715-b46b-4599-81e6-379adebe4bb4>
get
获取现有 UserConfig
参数:
kwargs
dict, 可选 - 所有其他可选关键字参数都作为查询参数/过滤器应用
返回:
引发:
AirUnexpectedresponse
- API 未返回 200 OK 或有效的响应 JSON
示例:
>>> air.user_configs.get(id='09b168b8-f9dd-408c-b3c6-bbecf6a43a09')
<UserConfig userdata1 cloud-init-user-data 09b168b8-f9dd-408c-b3c6-bbecf6a43a09>
更新
更新 UserConfig 的特定属性
参数:
kwargs
dict, optional - 所有其他可选关键字参数都作为键/值对应用于请求的 JSON 有效负载中。Kind 和 Organization 字段无法更改。
delete
删除现有 UserConfig 脚本
引发:
AirUnexpectedresponse
- Userconfig 删除失败
示例:
>>> metadata = air.user_configs.create(name='metadata', kind='cloud-init-meta-data', organization=None, content='local-hostname: cloud-init-node')
>>> metadata.delete()