Of course! Using the OpenStack API with Python is a common and powerful way to automate cloud infrastructure. The primary and recommended way to do this is by using the OpenStack Python SDK, often referred to as python-openstacksdk.

This guide will walk you through the entire process, from setup to practical examples.
The Recommended Tool: python-openstacksdk
This is the official, high-level Python client for OpenStack. It's the best choice for most use cases because:
- High-Level Abstraction: It abstracts away the low-level REST API calls, making your code cleaner and easier to read.
- Session Management: It handles authentication, token management, and service catalog discovery automatically.
- Unified Interface: It provides a consistent way to interact with all OpenStack services (Nova, Neutron, Glance, etc.).
- Actively Maintained: It's developed and supported by the OpenStack community.
Installation
First, you need to install the library. It's recommended to do this in a Python virtual environment.
# Create and activate a virtual environment (optional but recommended) python3 -m venv openstack-env source openstack-env/bin/activate # Install the main SDK pip install openstacksdk # Optional: Install additional libraries for specific features # For example, to use the Image service with Pillow for image manipulation pip install openstacksdk[pillow]
Authentication and Connection
The SDK needs to know how to connect to your OpenStack cloud. This is done by providing a dictionary of connection parameters. The easiest way to get these is from a clouds.yaml file, which is the standard configuration file for OpenStack clients.

Step 3.1: Create a clouds.yaml file
Create a file named clouds.yaml in your home directory (~/.config/openstack/clouds.yaml) or in your project directory.
# clouds.yaml
clouds:
my-openstack-cloud:
auth:
auth_url: https://your-openstack-api.com:5000/v3
username: "your_username"
password: "your_password"
project_name: "your_project_name" # or project_id
user_domain_name: "Default"
project_domain_name: "Default"
region_name: "RegionOne"
identity_api_version: 3
# Optional: If you have a self-signed SSL certificate for your API
verify: /path/to/your/ca.crt
auth_url: The URL of your OpenStack Identity service (Keystone).username,password: Your OpenStack credentials.project_name: The project (tenant) you want to work in.user_domain_name,project_domain_name: Usually "Default" in most setups.verify: Set toFalseto ignore SSL certificate errors (not recommended for production) or provide the path to your CA certificate.
Step 3.2: Connecting in Python
Connecting is as simple as importing the openstack library and creating a Connection object. The SDK will automatically find and use the clouds.yaml file.
import openstack
# Connect to the OpenStack cloud using the 'my-openstack-cloud' profile
# from your clouds.yaml file.
conn = openstack.connect(cloud='my-openstack-cloud')
# You can now use the 'conn' object to interact with all services.
print("Connected to OpenStack successfully!")
print(f"Auth Token: {conn.auth_token}")
print(f"Project Name: {conn.session.get_project_name()}")
# It's good practice to close the connection when done
conn.close()
Practical Examples with Different Services
Once connected, you can interact with various OpenStack services through the conn object.
Example 1: Compute Service (Nova) - Managing Servers
import openstack
import time
# --- Connection ---
conn = openstack.connect(cloud='my-openstack-cloud')
# --- Create a Server ---
print("Creating a new server...")
server_name = "my-python-test-server"
image = conn.image.find("ubuntu-20.04") # Find an image by name
flavor = conn.compute.find_flavor("m1.small") # Find a flavor by name
network = conn.network.find("my-private-network") # Find a network by name
server = conn.compute.create_server(
name=server_name,
image=image,
flavor=flavor,
networks=[{"uuid": network.id}]
)
print(f"Server '{server_name}' creation started. ID: {server.id}")
print("Waiting for server to become active...")
# Wait for the server to be in an 'ACTIVE' state
server = conn.compute.wait_for_server(server, status='ACTIVE', interval=2, wait=300)
print(f"Server is now active with IP: {server.access_ipv4}")
# --- List Servers ---
print("\n--- List of Servers ---")
for server in conn.compute.servers():
print(f"- {server.name} (Status: {server.status})")
# --- Delete the Server ---
print(f"\nDeleting server '{server_name}'...")
conn.compute.delete_server(server, wait=True)
print("Server deleted.")
conn.close()
Example 2: Networking Service (Neutron) - Managing Networks and Ports
import openstack
# --- Connection ---
conn = openstack.connect(cloud='my-openstack-cloud')
# --- Create a Network ---
print("Creating a new network...")
network = conn.network.create_network(name='my-python-network')
print(f"Network created with ID: {network.id}")
# --- Create a Subnet ---
print("Creating a subnet...")
subnet = conn.network.create_subnet(
name='my-python-subnet',
network_id=network.id,
ip_version='4',
cidr='192.168.99.0/24',
gateway_ip='192.168.99.1'
)
print(f"Subnet created with ID: {subnet.id}")
# --- List Networks ---
print("\n--- List of Networks ---")
for net in conn.network.networks():
print(f"- {net.name} (ID: {net.id})")
# --- Clean Up ---
print("\nCleaning up resources...")
conn.network.delete_subnet(subnet, ignore_missing=False)
conn.network.delete_network(network, ignore_missing=False)
print("Network and subnet deleted.")
conn.close()
Example 3: Image Service (Glance) - Managing Images
import openstack
# --- Connection ---
conn = openstack.connect(cloud='my-openstack-cloud')
# --- Upload an Image ---
# Note: This requires a local image file (e.g., a qcow2 or iso file)
image_path = '/path/to/your/image.qcow2'
image_name = 'my-custom-ubuntu-image'
print(f"Uploading image '{image_name}' from '{image_path}'...")
image = conn.image.create_image(
name=image_name,
filename=image_path,
disk_format='qcow2',
container_format='bare',
is_public=False
)
# Wait for the image to become 'active'
image = conn.image.wait_for_image(image, status='active')
print(f"Image uploaded successfully with ID: {image.id}")
# --- List Images ---
print("\n--- List of Images ---")
for img in conn.image.images():
print(f"- {img.name} (Status: {img.status})")
# --- Delete the Image ---
print(f"\nDeleting image '{image_name}'...")
conn.image.delete_image(image, ignore_missing=False)
print("Image deleted.")
conn.close()
Alternative: Direct Low-Level API Calls (requests)
While python-openstacksdk is recommended, you might sometimes need to make direct REST API calls. This is useful for:

- Interacting with a new or experimental OpenStack API endpoint not yet in the SDK.
- Understanding the underlying API mechanics.
- Building a lightweight client without the SDK's dependencies.
You would use a library like requests.
import requests
import json
# 1. Authenticate to get a token
auth_url = "https://your-openstack-api.com:5000/v3/auth/tokens"
auth_data = {
"auth": {
"identity": {
"methods": ["password"],
"password": {
"user": {
"name": "your_username",
"domain": {"name": "Default"},
"password": "your_password"
}
}
},
"scope": {
"project": {
"name": "your_project_name",
"domain": {"name": "Default"}
}
}
}
}
headers = {'Content-Type': 'application/json'}
response = requests.post(auth_url, data=json.dumps(auth_data), headers=headers, verify='/path/to/ca.crt')
if response.status_code == 201:
token = response.headers['X-Subject-Token']
print("Authentication successful. Token received.")
else:
print(f"Authentication failed: {response.text}")
exit()
# 2. Use the token to call another API endpoint (e.g., list servers)
servers_url = "https://your-nova-api.com:8774/v2.1/servers"
headers = {'X-Auth-Token': token, 'Accept': 'application/json'}
servers_response = requests.get(servers_url 