- 核心概念:
python-openstacksdk是什么,为什么用它。 - 安装与环境准备:如何开始使用。
- 认证与连接:如何安全地连接到 OpenStack 云。
- 核心操作示例:通过代码演示如何操作计算、网络、镜像等核心服务。
- 高级用法与最佳实践:如何更高效、更安全地使用。
- 其他相关库:除了
python-openstacksdk,还有哪些选择。
核心概念:python-openstacksdk
python-openstacksdk 是 OpenStack 官方推荐的、用于与 OpenStack 云进行交互的 Python 库,它不是一个单一的库,而是一个统一的客户端,它内部集成了对各个 OpenStack 服务(如 Nova, Neutron, Glance, Keystone 等)的底层调用。

主要优点:
- 统一性:一套 API 风格可以操作所有 OpenStack 服务,避免了学习多个不同库的麻烦。
- 高级抽象:它提供了比底层 REST API 更 Pythonic 的接口,让你可以操作对象(如服务器、网络)而不是原始的请求和响应。
- 会话管理:自动处理认证令牌、令牌刷新等繁琐工作。
- 插件化:可以轻松添加对新服务或新 API 版本的支持。
- 官方维护:与 OpenStack 社区同步更新,稳定可靠。
安装与环境准备
安装 SDK
使用 pip 进行安装非常简单:
# 安装核心库 pip install openstacksdk # 如果你需要特定的功能,可以安装可选的依赖 # 支持 Swift 对象存储的加密功能 pip install openstacksdk[swift_crypto]
准备 OpenStack 凭据
你的 Python 脚本需要知道如何连接到你的 OpenStack 云,最推荐的方式是使用一个云配置文件(clouds.yaml)。
-
获取凭据:从你的 OpenStack 云管理员或 Horizon 界面获取以下信息:
(图片来源网络,侵删)- 认证 URL (Auth URL): Keystone 的地址。
- 用户名 (Username)
- 密码 (Password)
- 项目名 (Project Name): 你要操作的项目/租户的名称。
- 用户域名 (User Domain Name): 用户所在的域。
- 项目域名 (Project Domain Name): 项目所在的域。
- API 版本 (API Version): 通常为
3。
-
创建
clouds.yaml文件: 在你的用户主目录下创建一个.config目录,并在其中创建openstack目录和clouds.yaml文件。- Linux/macOS:
~/.config/openstack/clouds.yaml - Windows:
%USERPROFILE%\.config\openstack\clouds.yaml
clouds.yaml文件内容示例:clouds: my_openstack_cloud: # 给你的云起一个名字 auth: auth_url: https://your-openstack-api:5000/v3 username: 'your_username' password: 'your_password' project_name: 'your_project_name' project_domain_name: 'Default' user_domain_name: 'Default' region_name: 'RegionOne' # 可选,指定区域 identity_api_version: 3安全提示:
clouds.yaml文件包含敏感信息,请务必设置好文件权限,例如在 Linux 上运行chmod 600 ~/.config/openstack/clouds.yaml。 - Linux/macOS:
认证与连接
使用 SDK 的第一步是创建一个 Connection 对象,这个对象会自动处理认证、令牌管理和 API 路由。

import openstack
# 连接到云
# openstack.connect() 会自动在 ~/.config/openstack/clouds.yaml 中查找配置
conn = openstack.connect(cloud='my_openstack_cloud') # 使用你在 clouds.yaml 中定义的名字
# 连接成功后,可以打印一些信息来验证
print(f"Connected to cloud: {conn}")
print(f"Auth Token: {conn.auth_token}")
print(f"Current Region: {conn.region_name}")
# 使用完毕后关闭连接(虽然通常脚本结束时自动关闭,但显式关闭是好习惯)
conn.close()
核心操作示例
假设你已经成功创建了 conn 对象,下面是一些常见操作的代码示例。
示例 1:创建并管理虚拟机
import openstack
import time
# 假设 conn 已经创建
conn = openstack.connect(cloud='my_openstack_cloud')
# 1. 获取镜像和 flavor
image = conn.image.find_image("ubuntu-20.04") # 或者使用 ID
flavor = conn.compute.find_flavor("m1.small") # 或者使用 ID
# 2. 创建一个网络 (如果还没有的话)
network_name = "my-python-network"
try:
network = conn.network.create_network(name=network_name)
print(f"Created network: {network.name} (ID: {network.id})")
except openstack.exceptions.Conflict:
print(f"Network {network_name} already exists.")
network = conn.network.find_network(network_name)
# 3. 创建一个子网
subnet_name = "my-python-subnet"
try:
subnet = conn.network.create_subnet(
name=subnet_name,
network_id=network.id,
ip_version='4',
cidr='192.168.1.0/24',
gateway_ip='192.168.1.1'
)
print(f"Created subnet: {subnet.name} (ID: {subnet.id})")
except openstack.exceptions.Conflict:
print(f"Subnet {subnet_name} already exists.")
subnet = conn.network.find_subnet(subnet_name)
# 4. 创建一个安全组,并添加规则
security_group_name = "my-python-sg"
try:
sg = conn.network.create_security_group(name=security_group_name)
print(f"Created security group: {sg.name} (ID: {sg.id})")
# 允许 SSH (端口 22)
conn.network.create_security_group_rule(
security_group_id=sg.id,
protocol='tcp',
port_range_min=22,
port_range_max=22,
remote_ip_prefix='0.0.0.0/0'
)
# 允许 ICMP (ping)
conn.network.create_security_group_rule(
security_group_id=sg.id,
protocol='icmp'
)
except openstack.exceptions.Conflict:
print(f"Security group {security_group_name} already exists.")
sg = conn.network.find_security_group(security_group_name)
# 5. 创建虚拟机
server_name = "my-python-server"
print(f"Creating server {server_name}...")
server = conn.compute.create_server(
name=server_name,
image_id=image.id,
flavor_id=flavor.id,
networks=[{"uuid": network.id}], # 关联到网络
security_groups=[{"name": sg.name}] # 关联到安全组
)
# 6. 等待服务器创建并变为 'ACTIVE' 状态
server = conn.compute.wait_for_server(server, status='ACTIVE', interval=2, wait=300)
print(f"Server {server.name} is active with IP: {server.access_ipv4}")
# 7. 删除服务器 (示例结束后清理)
# print(f"Deleting server {server.name}...")
# conn.compute.delete_server(server, wait=True)
示例 2:管理镜像
# 上传一个镜像文件到 Glance
image_name = "my-custom-image"
image_file_path = "/path/to/your/image.qcow2"
print(f"Uploading image {image_name}...")
image = conn.image.create_image(
name=image_name,
disk_format='qcow2',
container_format='bare',
data=open(image_file_path, 'rb')
)
# 等待镜像上传并变为 'active' 状态
image = conn.image.wait_for_image(image, status='active')
print(f"Image {image.name} is ready.")
# 列出所有镜像
print("\nAll images:")
for img in conn.image.images():
print(f"- {img.name} (ID: {img.id}, Status: {img.status})")
# 删除镜像
# conn.image.delete_image(image, wait=True)
示例 3:管理对象存储 (Swift)
# 1. 获取容器对象
container_name = "my-python-container"
try:
container = conn.object_store.create_container(name=container_name)
print(f"Created container: {container_name}")
except openstack.exceptions.Conflict:
print(f"Container {container_name} already exists.")
container = conn.object_store.get_container(container_name)
# 2. 上传一个文件
object_name = "hello.txt"
file_content = b"Hello from Python OpenStack SDK!"
conn.object_store.create_object(
container=container,
name=object_name,
data=file_content,
content_type='text/plain'
)
print(f"Uploaded object {object_name} to container {container_name}")
# 3. 列出容器中的对象
print("\nObjects in container:")
for obj in conn.object_store.objects(container):
print(f"- {obj.name} (Size: {obj.total_bytes} bytes)")
# 4. 下载对象
# obj_data = conn.object_store.get_object(container, object_name)
# print(f"Downloaded content: {obj_data.data.decode('utf-8')}")
# 5. 删除对象
# conn.object_store.delete_object(container, object_name, ignore_missing=False)
高级用法与最佳实践
使用配置文件和 Profile
除了 clouds.yaml,你还可以在代码中直接传递配置,或者使用 Profile 来管理多个环境。
from openstack import connection
# 方式一:直接在代码中配置(不推荐,不灵活)
conn = connection.Connection(
auth_url='https://...',
project_name='...',
username='...',
password='...',
user_domain_name='...',
project_domain_name='...'
)
# 方式二:使用 Profile (更灵活)
profile = openstack.config.loader.from_config(
cloud='my_openstack_cloud',
options={'region_name': 'RegionTwo'} # 覆盖配置文件中的区域
)
conn = openstack.connect(profile=profile)
处理异常
OpenStack API 调用可能会因为各种原因失败(如资源不存在、权限不足、网络问题等),务必使用 try...except 块来处理异常。
from openstack import exceptions
try:
server = conn.compute.find_server("non-existent-server")
print(server.name)
except exceptions.ResourceNotFound:
print("Error: The server was not found.")
except exceptions.SDKException as e:
print(f"An OpenStack error occurred: {e}")
使用日志进行调试
当遇到问题时,开启日志非常有用。
import logging # 设置日志级别为 DEBUG logging.basicConfig(level=logging.DEBUG) # openstacksdk 使用标准的 Python logging 模块 # 现在所有的 API 请求和响应都会被打印出来 conn = openstack.connect(cloud='my_openstack_cloud')
其他相关库
虽然 python-openstacksdk 是首选,但在某些特定场景下,你可能还会遇到或使用其他库:
-
python-novaclient,python-neutronclient, ...:- 是什么:这些是针对单个 OpenStack 服务的旧版客户端库(
nova对应计算,neutron对应网络)。 - 现状:它们是遗留库,官方已不再积极维护,新项目应绝对避免使用它们,除非你需要维护一个非常古老的脚本。
- 对比:
python-openstacksdk统一了这些库的功能,并提供更好的抽象和错误处理。
- 是什么:这些是针对单个 OpenStack 服务的旧版客户端库(
-
shade:- 是什么:
shade是由 Rackspace 开发的一个高级抽象库,它构建在python-openstacksdk之上。 - 特点:
shade提供了更“用户友好”的接口,封装了许多常见的、多步骤的操作,使其更简单,创建一个带网络和浮动 IP 的服务器,在shade中可能一行代码就能搞定,而在sdk中需要多个步骤。 - 如何选择:
- 如果你只需要进行简单的 API 调用,
python-openstacksdk足够且更贴近底层。 - 如果你正在编写复杂的云管理脚本或工具,希望减少样板代码,
shade是一个非常好的选择。
- 如果你只需要进行简单的 API 调用,
- 是什么:
| 特性 | python-openstacksdk (官方 SDK) |
shade (高级抽象) |
单服务客户端 (如 novaclient) |
|---|---|---|---|
| 定位 | 官方、统一的底层客户端 | 社区驱动的高级抽象层 | 遗留的、单一服务客户端 |
| 易用性 | 中等,需要理解 OpenStack 概念 | 高,封装了复杂操作 | 低,每个库 API 风格不同 |
| 功能 | 全面,覆盖所有官方服务 | 基于 SDK,增加便利方法 | 仅限单一服务 |
| 推荐度 | 新项目的首选 | 复杂脚本/工具的绝佳选择 | 不推荐,仅用于维护旧代码 |
对于绝大多数 Python 从 python-openstacksdk 开始学习 OpenStack 自动化是最佳路径,它提供了强大的功能和灵活性,同时保持了与 OpenStack 生态系统的紧密集成。
