杰瑞科技汇

OpenStack 如何兼容 Python3?

Of course! Here is a comprehensive guide to using OpenStack with Python 3, covering the main libraries, authentication, and practical examples.

OpenStack 如何兼容 Python3?-图1
(图片来源网络,侵删)

Understanding the Landscape: OpenStack Python Clients

When you talk about "OpenStack Python3," you're typically referring to one of two things:

  1. Official OpenStack Clients: These are the primary, recommended libraries for interacting with OpenStack services (like Nova, Glance, Neutron, etc.) from a Python script. They are actively maintained and support Python 3.
  2. OpenStack SDK (oslo): This is a lower-level library that provides common functionalities like configuration loading, logging, and messaging. While powerful, you won't use it directly to create a virtual machine. It's the foundation upon which the official clients are built.

For most tasks, you'll want to use the Official OpenStack Clients.


The Official OpenStack Clients (The Main Tools)

These are a set of libraries, one for each major OpenStack service. The most common ones you'll need are:

  • python-openstacksdk: A high-level, unified client that can interact with multiple services. This is the recommended starting point for most new projects.
  • python-novaclient: For managing compute instances (VMs).
  • python-glanceclient: For managing images.
  • python-neutronclient: For managing networks, routers, and IPs.
  • python-cinderclient: For managing block storage (volumes).
  • python-keystoneauth1: The core authentication library used by almost all other clients.

Installation

You can install these clients using pip. It's best practice to do this in a Python virtual environment.

OpenStack 如何兼容 Python3?-图2
(图片来源网络,侵删)
# Create and activate a virtual environment
python3 -m venv openstack-env
source openstack-env/bin/activate
# Install the recommended high-level client
pip install openstacksdk
# Or, install specific clients if you prefer
pip install python-novaclient python-glanceclient python-keystoneauth1

Authentication: The Key to Everything

Before you can do anything, you need to authenticate with the OpenStack Identity service (Keystone) to get an authentication token.

Method 1: Using Environment Variables (Recommended for Scripts)

This is the cleanest method. You create a file named clouds.yaml in your home directory (~/.config/openstack/clouds.yaml) or in your project directory. This file stores your connection details.

Example ~/.config/openstack/clouds.yaml:

clouds:
  my_openstack_cloud:
    auth:
      auth_url: https://my-openstack-api.com:5000/v3
      project_name: my_project
      username: my_user
      password: my_secret_password
      user_domain_name: Default
      project_domain_name: Default
    region_name: RegionOne
    identity_api_version: 3

Why this is great: Your Python code doesn't need to hardcode credentials. It will automatically look for this file.

OpenStack 如何兼容 Python3?-图3
(图片来源网络,侵删)

Method 2: Using a Cloud YAML File in Code

You can explicitly point the SDK to your clouds.yaml file.

Method 3: Passing Credentials Directly (Less Secure)

You can pass credentials as a dictionary, but this is not recommended for production scripts.


Practical Examples with openstacksdk

Let's walk through common tasks using the modern openstacksdk. This library uses a connection object that handles authentication for you.

Step 1: Establish a Connection

First, you need to create a connection object. The SDK will automatically find and use your clouds.yaml file.

import openstack
# Create a connection object using the clouds.yaml file
# The 'cloud' argument should match the name in your clouds.yaml file.
conn = openstack.connect(cloud='my_openstack_cloud')
# You can verify the connection
print(f"Connected to project: {conn.current_project_name}")
print(f"Auth Token: {conn.auth_token[:20]}...") # Print first 20 chars of token

Example 1: List All Compute Instances (VMs)

This is a very common task. The conn.compute.servers() method returns a generator of server objects.

print("\n--- Listing Compute Instances ---")
for server in conn.compute.servers():
    print(f"Name: {server.name}, ID: {server.id}, Status: {server.status}")

Example 2: Create a New Compute Instance

Creating an instance requires specifying an image, a flavor (VM size), and a network.

print("\n--- Creating a New Instance ---")
# Find a suitable image and flavor
image = conn.compute.find_image("ubuntu-22.04") # Or use an image ID
flavor = conn.compute.find_flavor("m1.small")   # Or use a flavor ID
# Find a network to launch the instance in
network = conn.network.find_network("private-net") # Or use a network ID
# Define the server configuration
server_name = "my-python3-test-vm"
image_id = image.id
flavor_id = flavor.id
network_id = network['id']
# Create the server
server = conn.compute.create_server(
    name=server_name,
    image_id=image_id,
    flavor_id=flavor_id,
    networks=[{"uuid": network_id}],
)
print(f"Server creation initiated. Name: {server.name}, ID: {server.id}")
# The 'server' object is initially in a 'BUILD' state.
# You can wait for it to become active.
server = conn.compute.wait_for_server(server)
print(f"Server is now active with IP: {server.access_ipv4}")

Example 3: Upload a New Image

This example shows how to upload a local disk image file (like a .qcow2 or .iso) to the Glance image service.

print("\n--- Uploading a New Image ---")
image_name = "my-custom-ubuntu-image"
image_filename = "/path/to/my/ubuntu-image.qcow2" # <-- IMPORTANT: Change this path
# Open the file in binary mode
with open(image_filename, 'rb') as image_file:
    image = conn.image.create_image(
        name=image_name,
        data=image_file,
        disk_format='qcow2',
        container_format='bare',
        is_public=False,
    )
print(f"Image upload initiated. Name: {image.name}, ID: {image.id}")
# Wait for the image to become active
image = conn.image.wait_for_image(image)
print(f"Image is now active.")

Example 4: Create a Network and a Router

This example demonstrates interacting with the Neutron network service.

print("\n--- Creating Network and Router ---")
# Create a private network
network_name = "my-python-network"
network = conn.network.create_network(name=network_name)
print(f"Created network: {network.name} (ID: {network.id})")
# Create a subnet within that network
subnet_name = "my-python-subnet"
subnet = conn.network.create_subnet(
    name=subnet_name,
    network_id=network.id,
    ip_version='4',
    cidr='192.168.101.0/24',
)
print(f"Created subnet: {subnet.name} (ID: {subnet.id})")
# Create a router and attach it to the external network (and our new subnet)
# First, find the external network
ext_net = conn.network.find_network("ext-net", ignore_missing=False)
router_name = "my-python-router"
router = conn.network.create_router(
    name=router_name,
    external_gateway_info={'network_id': ext_net.id},
)
print(f"Created router: {router.name} (ID: {router.id})")
# Attach the subnet to the router
conn.network.add_interface_to_router(router, subnet_id=subnet.id)
print(f"Attached subnet {subnet.name} to router {router.name}")

Important Considerations

  • Error Handling: OpenStack API calls can fail (e.g., invalid image ID, quota exceeded). Always wrap your code in try...except blocks. The openstacksdk raises specific exceptions.

    from openstack.exceptions import ResourceNotFound
    try:
        server = conn.compute.find_server("non-existent-server")
    except ResourceNotFound:
        print("Server not found, as expected.")
  • Pagination: For large lists of resources (like hundreds of servers), the API returns results in pages. The openstacksdk generators (conn.compute.servers()) handle pagination for you automatically, which is a huge advantage.

  • Asynchronous Operations: Many actions (like creating a server or volume) are asynchronous. The SDK provides convenient methods like wait_for_server() or wait_for_volume() to block your script until the resource reaches the desired state.

  • API Versioning: OpenStack services have multiple API versions. The openstacksdk is generally good at picking the best available version, but you can specify it in your clouds.yaml if needed. For older clients like novaclient, you might need to specify the API version explicitly in your code.

Summary and Best Practices

  1. Use openstacksdk: For any new project, start with the openstacksdk. It's modern, well-documented, and handles many complexities for you.
  2. Use clouds.yaml: Store your credentials in a clouds.yaml file. Do not hardcode them in your Python scripts.
  3. Iterate with Generators: Use the for item in conn.service.resources() pattern to list resources.
  4. Handle Errors: Use try...except to gracefully handle API errors.
  5. Wait for Completion: Use the wait_for_* methods to ensure your script waits for long-running tasks to finish.
分享:
扫描分享到社交APP
上一篇
下一篇