Guide: OpenStack Python SDK – Basic Usage: Difference between revisions
No edit summary |
No edit summary |
||
| (42 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers | This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking. | ||
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts. | |||
'''Note:''' In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing <code>Enter</code> '''twice'''. | |||
__TOC__ | |||
== Prerequisites == | == Prerequisites == | ||
Install the OpenStack SDK | Install the OpenStack SDK, e.g. for Ubuntu: | ||
sudo apt install python3-openstacksdk | <pre> | ||
</pre>Alternatively | sudo apt install python3-openstacksdk | ||
</pre> | |||
Alternatively, you can install it via <code>pip</code> (preferably inside a virtual environment): | |||
<pre> | |||
python3 -m venv openstacksdk_venv | |||
source openstacksdk_venv/bin/activate | |||
pip install openstacksdk | pip install openstacksdk | ||
</pre> | </pre> | ||
== Authentication == | == Authentication == | ||
You can either: | You can either: | ||
* source an OpenRC file, or | * source an OpenRC file, or | ||
* use a clouds.yaml file | * use a <code>clouds.yaml</code> file | ||
For details, see the section [[Programmatic Access and Automation#How can I create an application credential?|Create an application credential]]. | |||
In the following, we use the <code>clouds.yaml</code> file. | |||
== Basic Connection == | == Basic Connection == | ||
Create a connection in Python:<pre> | Create a connection in Python: | ||
<pre> | |||
import openstack | import openstack | ||
conn = openstack.connect(cloud="openstack") | |||
</pre> | |||
== Images == | |||
List available images: | |||
<pre> | |||
for image in conn.image.images(): | |||
print(image.name, image.id) | |||
</pre> | |||
Upload a new image: | |||
<pre> | |||
import os | |||
conn = | image_path = "/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img" | ||
if not os.path.isfile(image_path): | |||
raise FileNotFoundError(f"Image file not found: {image_path}") | |||
with open(image_path, "rb") as img: | |||
image = conn.image.upload_image( | |||
name="ubuntu-24.04", | |||
data=img, | |||
disk_format="qcow2", | |||
container_format="bare" | |||
) | |||
print("Image ID:", image.id) | |||
</pre> | |||
Show image details: | |||
<pre> | |||
image = conn.image.get_image("<IMAGE_ID>") | |||
print(image) | |||
</pre> | |||
Delete an image: | |||
<pre> | |||
conn.image.delete_image("<IMAGE_ID>") | |||
</pre> | </pre> | ||
== Compute == | == Compute == | ||
=== Key Pairs (SSH Access) === | |||
Create a key pair: | |||
<pre> | |||
keypair = conn.compute.create_keypair(name="myKey") | |||
with open("myKey.pem", "w") as f: | |||
f.write(keypair.private_key) | |||
</pre> | |||
Set correct permissions (outside Python shell): | |||
<pre> | |||
chmod 600 myKey.pem | |||
</pre> | |||
List key pairs: | |||
<pre> | |||
for kp in conn.compute.keypairs(): | |||
print(kp.name) | |||
</pre> | |||
Delete a key pair: | |||
<pre> | |||
conn.compute.delete_keypair("myKey") | |||
</pre> | |||
=== Instances === | === Instances === | ||
List instances:<pre> | List instances: | ||
<pre> | |||
for server in conn.compute.servers(): | for server in conn.compute.servers(): | ||
print(server.name, server.status) | print(server.name, server.status) | ||
</pre>Create an instance:<pre> | </pre> | ||
Create an instance (ensure that the specified image, flavor, network, and key pair exist): | |||
<pre> | |||
image = conn.compute.find_image("ubuntu-24.04") | image = conn.compute.find_image("ubuntu-24.04") | ||
flavor = conn.compute.find_flavor("p1.tiny") | flavor = conn.compute.find_flavor("p1.tiny") | ||
network = conn.network.find_network("myNet") | network = conn.network.find_network("myNet") | ||
server = conn.compute.create_server( | server = conn.compute.create_server( | ||
name="myVM", | name="myVM", | ||
| Line 56: | Line 133: | ||
key_name="myKey" | key_name="myKey" | ||
) | ) | ||
server = conn.compute.wait_for_server(server) | server = conn.compute.wait_for_server(server) | ||
print("Created:", server.name) | print("Created:", server.name) | ||
</pre> | </pre> | ||
Show details of an instance: | |||
<pre> | |||
server = conn.compute.find_server("myVM") | server = conn.compute.find_server("myVM") | ||
conn.compute. | if server is None: | ||
raise ValueError("Server 'myVM' not found") | |||
server = conn.compute.get_server(server.id) | |||
print(server) | |||
</pre> | </pre> | ||
Delete an instance: | |||
<pre> | |||
server = conn.compute.find_server("myVM") | |||
conn.compute.delete_server(server.id) | |||
</pre> | </pre> | ||
| Line 73: | Line 158: | ||
=== Volumes === | === Volumes === | ||
List volumes:<pre> | |||
List volumes: | |||
<pre> | |||
for vol in conn.block_storage.volumes(): | for vol in conn.block_storage.volumes(): | ||
print(vol.name, vol.size) | print(vol.name, vol.size) | ||
</pre>Create a volume:<pre> | </pre> | ||
Create a volume (size in GB): | |||
<pre> | |||
volume = conn.block_storage.create_volume( | volume = conn.block_storage.create_volume( | ||
name="myVolume", | name="myVolume", | ||
size=10 | size=10 | ||
) | ) | ||
</pre>Delete a volume:<pre> | </pre> | ||
Delete a volume: | |||
<pre> | |||
volume = conn.block_storage.find_volume("myVolume") | volume = conn.block_storage.find_volume("myVolume") | ||
conn.block_storage.delete_volume(volume.id) | conn.block_storage.delete_volume(volume.id) | ||
| Line 87: | Line 183: | ||
=== Volume Management for Instances === | === Volume Management for Instances === | ||
Attach a volume to an instance:<pre> | |||
Attach a volume to an instance: | |||
<pre> | |||
server = conn.compute.find_server("myVM") | server = conn.compute.find_server("myVM") | ||
volume = conn.block_storage.find_volume("myVolume") | volume = conn.block_storage.find_volume("myVolume") | ||
conn.compute.create_volume_attachment( | conn.compute.create_volume_attachment( | ||
server, | server, | ||
volumeId=volume.id | volumeId=volume.id | ||
) | ) | ||
</pre>Detach a volume:<pre> | </pre> | ||
Detach a volume from an instance: | |||
<pre> | |||
attachments = conn.compute.volume_attachments(server) | attachments = conn.compute.volume_attachments(server) | ||
for att in attachments: | for att in attachments: | ||
| Line 105: | Line 207: | ||
=== Networks === | === Networks === | ||
List networks:<pre> | List networks: | ||
<pre> | |||
for net in conn.network.networks(): | for net in conn.network.networks(): | ||
print(net.name) | print(net.name) | ||
</pre>Create a network:<pre> | </pre> | ||
Create a network: | |||
<pre> | |||
network = conn.network.create_network(name="myNet") | network = conn.network.create_network(name="myNet") | ||
</pre>Delete a network:<pre> | </pre> | ||
Delete a network (after detaching all ports from its subnets): | |||
<pre> | |||
network = conn.network.find_network("myNet") | network = conn.network.find_network("myNet") | ||
conn.network.delete_network(network.id) | conn.network.delete_network(network.id) | ||
</pre> | |||
=== Subnets, Routers === | |||
Create a subnet: | |||
<pre> | |||
network = conn.network.create_network(name="myNet") | |||
subnet = conn.network.create_subnet( | |||
name="mySubnet", | |||
network_id=network.id, | |||
ip_version=4, | |||
cidr="192.168.1.0/24" | |||
) | |||
</pre> | |||
Create a router: | |||
<pre> | |||
router = conn.network.create_router(name="myRouter") | |||
</pre> | |||
Attach a subnet to a router: | |||
<pre> | |||
conn.network.add_interface_to_router( | |||
router, | |||
subnet_id=subnet.id | |||
) | |||
</pre> | |||
Set external gateway of a router: | |||
<pre> | |||
external_net = conn.network.find_network("provider_default_net") | |||
conn.network.update_router( | |||
router, | |||
external_gateway_info={"network_id": external_net.id} | |||
) | |||
</pre> | |||
Detach a subnet from a router: | |||
<pre> | |||
conn.network.remove_interface_from_router( | |||
router, | |||
subnet_id=subnet.id | |||
) | |||
</pre> | |||
Delete a router: | |||
<pre> | |||
conn.network.delete_router(router.id) | |||
</pre> | |||
Delete a subnet (after detaching all ports from the subnet): | |||
<pre> | |||
conn.network.delete_subnet(subnet.id) | |||
</pre> | </pre> | ||
=== Floating IPs === | === Floating IPs === | ||
Create a floating IP:<pre> | |||
fip = conn.network.create_ip(floating_network_id= | Create a floating IP (requires access to the provider network): | ||
<pre> | |||
network = conn.network.find_network("provider_default_net") | |||
fip = conn.network.create_ip(floating_network_id=network.id) | |||
print(fip.floating_ip_address) | print(fip.floating_ip_address) | ||
</pre>Associate a floating IP with an instance:<pre> | </pre> | ||
List floating IPs: | |||
<pre> | |||
for fip in conn.network.ips(): | |||
print(fip.floating_ip_address, fip.status, fip.port_id) | |||
</pre> | |||
Associate a floating IP with an instance: | |||
<pre> | |||
server = conn.compute.find_server("myVM") | server = conn.compute.find_server("myVM") | ||
conn. | port = list(conn.network.ports(device_id=server.id))[0] | ||
</pre>Disassociate a floating IP:<pre> | conn.network.update_ip(fip, port_id=port.id) | ||
conn. | </pre> | ||
</pre> | |||
Disassociate a floating IP: | |||
<pre> | |||
conn.network.update_ip(fip, port_id=None) | |||
</pre> | |||
Release (delete) a floating IP: | |||
<pre> | |||
conn.network.delete_ip(fip.id) | conn.network.delete_ip(fip.id) | ||
</pre> | </pre> | ||
=== Security Groups === | === Security Groups === | ||
List security groups:<pre> | |||
List security groups: | |||
<pre> | |||
for sg in conn.network.security_groups(): | for sg in conn.network.security_groups(): | ||
print(sg.name) | print(sg.name) | ||
</pre>Create a security group:<pre> | </pre> | ||
Create a security group: | |||
<pre> | |||
sg = conn.network.create_security_group(name="mySecGroup") | sg = conn.network.create_security_group(name="mySecGroup") | ||
</pre>Add a rule (HTTP):<pre> | </pre> | ||
Add a rule to a security group (e.g., HTTP access via port 80): | |||
<pre> | |||
conn.network.create_security_group_rule( | conn.network.create_security_group_rule( | ||
security_group_id=sg.id, | security_group_id=sg.id, | ||
direction="ingress", | |||
protocol="tcp", | protocol="tcp", | ||
port_range_min=80, | port_range_min=80, | ||
port_range_max=80, | port_range_max=80, | ||
ethertype="IPv4" | |||
) | ) | ||
</pre>Assign security group to an instance:<pre> | </pre> | ||
Assign security group to an instance: | |||
<pre> | |||
server = conn.compute.find_server("myVM") | server = conn.compute.find_server("myVM") | ||
conn.compute.add_security_group_to_server(server, sg.name) | conn.compute.add_security_group_to_server(server, sg.name) | ||
</pre>Remove a security group from an instance:<pre> | </pre> | ||
Remove a security group from an instance: | |||
<pre> | |||
conn.compute.remove_security_group_from_server(server, sg.name) | conn.compute.remove_security_group_from_server(server, sg.name) | ||
</pre>Delete a security group:<pre> | </pre> | ||
Delete a security group: | |||
<pre> | |||
conn.network.delete_security_group(sg.id) | conn.network.delete_security_group(sg.id) | ||
</pre> | </pre> | ||
Latest revision as of 10:13, 27 April 2026
This guide provides a quick introduction to managing your bwCloud-OS resources using the OpenStack Python SDK. It covers the most common operations for compute, storage, and networking.
In the following, we demonstrate the routines using an interactive Python shell. In practice, these routines are typically used within Python scripts.
Note: In the interactive Python shell, multi-line blocks (e.g., loops or function definitions) are executed after pressing Enter twice.
Prerequisites
Install the OpenStack SDK, e.g. for Ubuntu:
sudo apt install python3-openstacksdk
Alternatively, you can install it via pip (preferably inside a virtual environment):
python3 -m venv openstacksdk_venv source openstacksdk_venv/bin/activate pip install openstacksdk
Authentication
You can either:
- source an OpenRC file, or
- use a
clouds.yamlfile
For details, see the section Create an application credential.
In the following, we use the clouds.yaml file.
Basic Connection
Create a connection in Python:
import openstack conn = openstack.connect(cloud="openstack")
Images
List available images:
for image in conn.image.images():
print(image.name, image.id)
Upload a new image:
import os
image_path = "/path/to/images/ubuntu-24.04-server-cloudimg-amd64.img"
if not os.path.isfile(image_path):
raise FileNotFoundError(f"Image file not found: {image_path}")
with open(image_path, "rb") as img:
image = conn.image.upload_image(
name="ubuntu-24.04",
data=img,
disk_format="qcow2",
container_format="bare"
)
print("Image ID:", image.id)
Show image details:
image = conn.image.get_image("<IMAGE_ID>")
print(image)
Delete an image:
conn.image.delete_image("<IMAGE_ID>")
Compute
Key Pairs (SSH Access)
Create a key pair:
keypair = conn.compute.create_keypair(name="myKey")
with open("myKey.pem", "w") as f:
f.write(keypair.private_key)
Set correct permissions (outside Python shell):
chmod 600 myKey.pem
List key pairs:
for kp in conn.compute.keypairs():
print(kp.name)
Delete a key pair:
conn.compute.delete_keypair("myKey")
Instances
List instances:
for server in conn.compute.servers():
print(server.name, server.status)
Create an instance (ensure that the specified image, flavor, network, and key pair exist):
image = conn.compute.find_image("ubuntu-24.04")
flavor = conn.compute.find_flavor("p1.tiny")
network = conn.network.find_network("myNet")
server = conn.compute.create_server(
name="myVM",
image_id=image.id,
flavor_id=flavor.id,
networks=[{"uuid": network.id}],
key_name="myKey"
)
server = conn.compute.wait_for_server(server)
print("Created:", server.name)
Show details of an instance:
server = conn.compute.find_server("myVM")
if server is None:
raise ValueError("Server 'myVM' not found")
server = conn.compute.get_server(server.id)
print(server)
Delete an instance:
server = conn.compute.find_server("myVM")
conn.compute.delete_server(server.id)
Storage
Volumes
List volumes:
for vol in conn.block_storage.volumes():
print(vol.name, vol.size)
Create a volume (size in GB):
volume = conn.block_storage.create_volume(
name="myVolume",
size=10
)
Delete a volume:
volume = conn.block_storage.find_volume("myVolume")
conn.block_storage.delete_volume(volume.id)
Volume Management for Instances
Attach a volume to an instance:
server = conn.compute.find_server("myVM")
volume = conn.block_storage.find_volume("myVolume")
conn.compute.create_volume_attachment(
server,
volumeId=volume.id
)
Detach a volume from an instance:
attachments = conn.compute.volume_attachments(server)
for att in attachments:
if att.volume_id == volume.id:
conn.compute.delete_volume_attachment(att.id, server)
Networking
Networks
List networks:
for net in conn.network.networks():
print(net.name)
Create a network:
network = conn.network.create_network(name="myNet")
Delete a network (after detaching all ports from its subnets):
network = conn.network.find_network("myNet")
conn.network.delete_network(network.id)
Subnets, Routers
Create a subnet:
network = conn.network.create_network(name="myNet")
subnet = conn.network.create_subnet(
name="mySubnet",
network_id=network.id,
ip_version=4,
cidr="192.168.1.0/24"
)
Create a router:
router = conn.network.create_router(name="myRouter")
Attach a subnet to a router:
conn.network.add_interface_to_router(
router,
subnet_id=subnet.id
)
Set external gateway of a router:
external_net = conn.network.find_network("provider_default_net")
conn.network.update_router(
router,
external_gateway_info={"network_id": external_net.id}
)
Detach a subnet from a router:
conn.network.remove_interface_from_router(
router,
subnet_id=subnet.id
)
Delete a router:
conn.network.delete_router(router.id)
Delete a subnet (after detaching all ports from the subnet):
conn.network.delete_subnet(subnet.id)
Floating IPs
Create a floating IP (requires access to the provider network):
network = conn.network.find_network("provider_default_net")
fip = conn.network.create_ip(floating_network_id=network.id)
print(fip.floating_ip_address)
List floating IPs:
for fip in conn.network.ips():
print(fip.floating_ip_address, fip.status, fip.port_id)
Associate a floating IP with an instance:
server = conn.compute.find_server("myVM")
port = list(conn.network.ports(device_id=server.id))[0]
conn.network.update_ip(fip, port_id=port.id)
Disassociate a floating IP:
conn.network.update_ip(fip, port_id=None)
Release (delete) a floating IP:
conn.network.delete_ip(fip.id)
Security Groups
List security groups:
for sg in conn.network.security_groups():
print(sg.name)
Create a security group:
sg = conn.network.create_security_group(name="mySecGroup")
Add a rule to a security group (e.g., HTTP access via port 80):
conn.network.create_security_group_rule(
security_group_id=sg.id,
direction="ingress",
protocol="tcp",
port_range_min=80,
port_range_max=80,
ethertype="IPv4"
)
Assign security group to an instance:
server = conn.compute.find_server("myVM")
conn.compute.add_security_group_to_server(server, sg.name)
Remove a security group from an instance:
conn.compute.remove_security_group_from_server(server, sg.name)
Delete a security group:
conn.network.delete_security_group(sg.id)