OpenStack Plugin
Introduction
The OpenStack plugin for Waldur provides comprehensive integration with OpenStack cloud infrastructure, enabling organizations to manage OpenStack resources through Waldur's unified platform. This plugin acts as a bridge between Waldur's resource management capabilities and OpenStack's Infrastructure-as-a-Service (IaaS) offerings.
Core Functionality
The plugin enables:
- Multi-tenant Resource Management: Create and manage OpenStack projects (tenants) with isolated resources
- Compute Resource Provisioning: Deploy and manage virtual machines with full lifecycle control
- Storage Management: Provision block storage volumes, create snapshots, and manage backups
- Network Configuration: Set up virtual networks, subnets, routers, and security policies
- Quota Management: Synchronize and enforce resource quotas between Waldur and OpenStack
- Cross-tenant Resource Sharing: Share networks between tenants using RBAC policies
- Automated Resource Discovery: Import existing OpenStack resources into Waldur
- Console Access: Provide direct console access to virtual machines
Architecture
Module Structure
The OpenStack integration consists of two active Django applications:
| Module | Django Label | Purpose |
|---|---|---|
waldur_openstack |
openstack |
Core OpenStack resource models, backend client, executors, serializers, and ViewSets |
waldur_mastermind.marketplace_openstack |
marketplace_openstack |
Marketplace bridge that maps marketplace orders to OpenStack operations and synchronizes resource state |
A third module, waldur_openstack_replication, handles tenant migration between OpenStack deployments and is documented separately in OpenStack Replication.
Layered Architecture
Each OpenStack operation flows through a well-defined layer stack:
1 2 3 4 5 6 | |
| Layer | Role |
|---|---|
| Models | Django ORM models representing OpenStack resources (Tenant, Instance, Volume, Network, etc.) |
| Serializers | Validate API input and format output; enforce field-level permissions |
| ViewSets | REST endpoints for CRUD and custom actions; enforce object-level permissions |
| Executors | Celery task chains that orchestrate multi-step backend operations with error handling |
Backend (OpenStackBackend) |
Translates Waldur operations into OpenStack API calls using service-specific clients |
| Handlers | Signal receivers that react to state changes (e.g., update marketplace resource when backend state changes) |
Resource Lifecycle Flow
A typical end-to-end provisioning flow:
- Administrator creates an Offering of type
OpenStack.Tenant, scoped to a set of OpenStack admin credentials (stored insecret_options). - User places a marketplace order for a tenant. The
TenantCreateProcessorvalidates limits and delegates to theTenantCreateExecutor. - Executor runs a Celery task chain: create project in Keystone, create admin and tenant users, push quotas, create default security groups, set up internal network/subnet/router, connect to external network, pull images/flavors/volume types, then mark the tenant as OK.
- On tenant OK (when
AUTOMATICALLY_CREATE_PRIVATE_OFFERINGis enabled), signal handlers automatically create privateOpenStack.InstanceandOpenStack.Volumeofferings scoped to that tenant. - Users order instances and volumes through those offerings. The respective processors (
InstanceCreateProcessor,VolumeCreateProcessor) handle creation via their own executor chains. - Background tasks periodically pull resource state, quotas, and properties from OpenStack to keep Waldur in sync.
Backend Connection Flow
1 2 3 4 5 | |
Session caching: Authenticated Keystone sessions are cached in Django's cache backend with a 10-hour TTL. The cache key is derived from a SHA-256 hash of the credentials. If a cached token will expire within 10 minutes, the session is recreated.
OpenStack client versions:
| Service | Client Library | API Version |
|---|---|---|
| Keystone | keystoneclient |
v3 |
| Nova | novaclient |
v2.19 (microversion) |
| Cinder | cinderclient |
v3 |
| Glance | glanceclient |
v2 |
| Neutron | neutronclient |
v2.0 |
Only the Keystone endpoint needs to be configured explicitly; all other service endpoints are discovered automatically from the Keystone service catalog.
Supported Operations by OpenStack Service
Keystone (Identity Service)
| Operation | Description | API Endpoint |
|---|---|---|
| Tenant Creation | Create new OpenStack projects/tenants | POST /api/openstack-tenants/ |
| Tenant Deletion | Remove OpenStack projects | DELETE /api/openstack-tenants/{uuid}/ |
| Authentication | Manage tenant credentials | Handled internally |
| Quota Retrieval | Fetch tenant quotas | GET /api/openstack-tenants/{uuid}/quotas/ |
| Quota Update | Modify tenant quotas | POST /api/openstack-tenants/{uuid}/set_quotas/ |
Nova (Compute Service)
| Operation | Description | API Endpoint |
|---|---|---|
| Instances | ||
| Create Instance | Launch new virtual machines | POST /api/openstack-instances/ |
| Delete Instance | Terminate virtual machines | DELETE /api/openstack-instances/{uuid}/ |
| Start Instance | Power on virtual machines | POST /api/openstack-instances/{uuid}/start/ |
| Stop Instance | Power off virtual machines | POST /api/openstack-instances/{uuid}/stop/ |
| Restart Instance | Reboot virtual machines | POST /api/openstack-instances/{uuid}/restart/ |
| Resize Instance | Change instance flavor | POST /api/openstack-instances/{uuid}/change_flavor/ |
| Console Access | Get VNC console URL | POST /api/openstack-instances/{uuid}/console/ |
| Attach Volume | Connect storage to instance | POST /api/openstack-instances/{uuid}/attach_volume/ |
| Detach Volume | Disconnect storage from instance | POST /api/openstack-instances/{uuid}/detach_volume/ |
| Assign Floating IP | Attach public IP | POST /api/openstack-instances/{uuid}/assign_floating_ip/ |
| Flavors | ||
| List Flavors | Get available VM sizes | GET /api/openstack-flavors/ |
| Import Flavors | Sync flavors from backend | POST /api/openstack-tenants/{uuid}/pull_flavors/ |
| Images | ||
| List Images | Get available OS images | GET /api/openstack-images/ |
| Import Images | Sync images from backend | POST /api/openstack-tenants/{uuid}/pull_images/ |
| Server Groups | ||
| Create Server Group | Set up affinity policies | POST /api/openstack-server-groups/ |
| Delete Server Group | Remove affinity policies | DELETE /api/openstack-server-groups/{uuid}/ |
| Availability Zones | ||
| List AZs | Get compute availability zones | GET /api/openstack-instance-availability-zones/ |
Cinder (Block Storage Service)
| Operation | Description | API Endpoint |
|---|---|---|
| Volumes | ||
| Create Volume | Provision block storage | POST /api/openstack-volumes/ |
| Delete Volume | Remove block storage | DELETE /api/openstack-volumes/{uuid}/ |
| Extend Volume | Increase volume size | POST /api/openstack-volumes/{uuid}/extend/ |
| Attach to Instance | Connect volume to VM | POST /api/openstack-volumes/{uuid}/attach/ |
| Detach from Instance | Disconnect volume from VM | POST /api/openstack-volumes/{uuid}/detach/ |
| Create from Snapshot | Restore volume from snapshot | POST /api/openstack-volumes/{uuid}/create_from_snapshot/ |
| Snapshots | ||
| Create Snapshot | Create volume snapshot | POST /api/openstack-snapshots/ |
| Delete Snapshot | Remove snapshot | DELETE /api/openstack-snapshots/{uuid}/ |
| Restore Snapshot | Create volume from snapshot | POST /api/openstack-snapshots/{uuid}/restore/ |
| Volume Types | ||
| List Volume Types | Get storage types (SSD/HDD) | GET /api/openstack-volume-types/ |
| Import Volume Types | Sync types from backend | POST /api/openstack-tenants/{uuid}/pull_volume_types/ |
| Backups | ||
| Create Backup | Create volume backup | POST /api/openstack-backups/ |
| Delete Backup | Remove backup | DELETE /api/openstack-backups/{uuid}/ |
| Restore Backup | Restore volume from backup | POST /api/openstack-backups/{uuid}/restore/ |
Neutron (Networking Service)
| Operation | Description | API Endpoint |
|---|---|---|
| Networks | ||
| Create Network | Set up virtual network | POST /api/openstack-networks/ |
| Delete Network | Remove virtual network | DELETE /api/openstack-networks/{uuid}/ |
| Update Network | Modify network properties | PATCH /api/openstack-networks/{uuid}/ |
| Subnets | ||
| Create Subnet | Define IP address pool | POST /api/openstack-subnets/ |
| Delete Subnet | Remove subnet | DELETE /api/openstack-subnets/{uuid}/ |
| Update Subnet | Modify subnet configuration | PATCH /api/openstack-subnets/{uuid}/ |
| Routers | ||
| Create Router | Set up network router | POST /api/openstack-routers/ |
| Delete Router | Remove router | DELETE /api/openstack-routers/{uuid}/ |
| Add Interface | Connect subnet to router | POST /api/openstack-routers/{uuid}/add_interface/ |
| Remove Interface | Disconnect subnet from router | POST /api/openstack-routers/{uuid}/remove_interface/ |
| Set Gateway | Configure external gateway | POST /api/openstack-routers/{uuid}/set_gateway/ |
| Common Resource Actions | ||
| Set Erred | Force resource to ERRED state (staff-only) | POST /api/openstack-{resource}/{uuid}/set_erred/ |
| Set OK | Force resource to OK state (staff-only) | POST /api/openstack-{resource}/{uuid}/set_ok/ |
| Pull | Sync resource state from backend | POST /api/openstack-{resource}/{uuid}/pull/ |
| Unlink | Remove resource record without backend deletion (staff-only) | POST /api/openstack-{resource}/{uuid}/unlink/ |
| Ports | ||
| Create Port | Create network interface | POST /api/openstack-ports/ |
| Delete Port | Remove network interface | DELETE /api/openstack-ports/{uuid}/ |
| Update Port | Modify port configuration | PATCH /api/openstack-ports/{uuid}/ |
| Floating IPs | ||
| Allocate Floating IP | Reserve public IP | POST /api/openstack-floating-ips/ |
| Release Floating IP | Release public IP | DELETE /api/openstack-floating-ips/{uuid}/ |
| Associate Floating IP | Attach to instance | POST /api/openstack-floating-ips/{uuid}/assign/ |
| Disassociate Floating IP | Detach from instance | POST /api/openstack-floating-ips/{uuid}/unassign/ |
| Security Groups | ||
| Create Security Group | Set up firewall rules | POST /api/openstack-sgp/ |
| Delete Security Group | Remove firewall rules | DELETE /api/openstack-sgp/{uuid}/ |
| Add Rule | Create firewall rule | POST /api/openstack-sgp/{uuid}/rules/ |
| Remove Rule | Delete firewall rule | DELETE /api/openstack-sgp/{uuid}/rules/{rule_id}/ |
| RBAC Policies | ||
| Create RBAC Policy | Share network between tenants | POST /api/openstack-network-rbac-policies/ |
| List RBAC Policies | View sharing policies | GET /api/openstack-network-rbac-policies/ |
| External Networks | ||
| List External Networks | Get provider-level external networks with subnets | GET /api/openstack-external-networks/ |
| Get External Network | Retrieve external network details | GET /api/openstack-external-networks/{uuid}/ |
External Networks
External networks are provider-level OpenStack networks (with router:external=True) that provide floating IP connectivity for tenants. Waldur discovers and stores these as ExternalNetwork and ExternalSubnet model instances, following the same ServiceProperty pattern used for flavors, images, and volume types.
API Endpoints
| Operation | Description | API Endpoint |
|---|---|---|
| List External Networks | Get discovered external networks with subnets | GET /api/openstack-external-networks/ |
| Get External Network | Retrieve details including nested subnets | GET /api/openstack-external-networks/{uuid}/ |
The endpoint is read-only. External networks are synced automatically from OpenStack during the periodic properties pull (every 24 hours) via pull_external_networks().
Response Format
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Filtering
| Parameter | Description |
|---|---|
settings_uuid |
Filter by service settings UUID |
settings |
Filter by service settings URL |
External Network Resolution
When Waldur needs to determine which external network a tenant should use (for floating IP allocation, router creation, etc.), it follows this priority order:
- Tenant FK (
tenant.external_network_ref) - direct model reference on the tenant - CustomerOpenStack FK (
customer_openstack.external_network_ref) - per-customer override - Service settings option (
options.external_network_id) - provider-wide default, resolved to anExternalNetworkbybackend_id - Legacy string fallback - direct
external_network_idCharField values (deprecated, will be removed)
The get_external_network() utility in waldur_openstack.utils implements this resolution chain and returns an ExternalNetwork model instance (or None). The older get_external_network_id() function wraps this and returns the backend_id string for backward compatibility.
Carrier-Grade NAT (IP Mapping)
For environments using carrier-grade NAT, each ExternalSubnet has an optional public_ip_range field that maps the subnet's floating IP CIDR to a publicly routable CIDR. This replaces the free-form ipv4_external_ip_mapping JSON previously stored in Offering.secret_options.
The get_external_ip() function in marketplace_openstack/utils.py resolves public IPs by:
- Looking up
ExternalSubnetrecords wherepublic_ip_rangeis set and the floating IP falls within the subnet'scidr - Falling back to
secret_options["ipv4_external_ip_mapping"]if no matching subnet is found
Migration Notes
This feature was introduced as Phase 1 of a two-phase migration:
- Phase 1 (current):
ExternalNetworkandExternalSubnetmodels exist alongside the legacyexternal_network_idCharField onTenantandCustomerOpenStack. Both the FK (external_network_ref) and the string field are maintained in parallel. Internal code reads from the FK first and falls back to the string. - Phase 2 (follow-up): The legacy
external_network_idCharFields andipv4_external_ip_mappinginsecret_optionswill be removed. All consumers will use the FK exclusively.
Glance (Image Service)
| Operation | Description | API Endpoint |
|---|---|---|
| List Images | Get available images | GET /api/openstack-images/ |
| Import Images | Sync images from Glance | Handled via tenant sync |
| Image Metadata | Get image properties | Included in image list |
| Custom Images | ||
| Create Custom Image | Create image metadata | POST /api/openstack-marketplace/{tenant_uuid}/create_image/ |
| Upload Image Data | Upload binary image data | POST /api/openstack-marketplace/{tenant_uuid}/upload_image_data/{image_id}/ |
Custom Image Upload Workflow
The OpenStack plugin provides a two-step process for uploading custom images to OpenStack Glance, enabling users to create and use their own VM images.
Overview
The image upload process consists of two sequential API calls:
- Create Image Metadata: Creates an empty image record in OpenStack with metadata
- Upload Image Data: Streams the actual image file content to OpenStack
Step 1: Create Image Metadata
Endpoint: POST /api/openstack-marketplace/{tenant_uuid}/create_image/
Creates an image metadata record in OpenStack Glance and returns an upload URL.
Required Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
name |
string | Image name | Required |
disk_format |
string | Disk format | qcow2 |
container_format |
string | Container format | bare |
visibility |
string | Image visibility | private |
min_disk |
integer | Minimum disk size (GB) | 0 |
min_ram |
integer | Minimum RAM (MB) | 0 |
Supported Disk Formats
qcow2- QEMU Copy On Write (recommended)raw- Raw disk imagevhd- Virtual Hard Diskvmdk- VMware Virtual Machine Diskvdi- VirtualBox Disk Imageiso- ISO 9660 disk imageaki,ami,ari- Amazon kernel/machine/ramdisk images
Supported Container Formats
bare- No container (most common)ovf- Open Virtualization Formataki,ami,ari- Amazon formats
Example Request
1 2 3 4 5 6 7 8 | |
Example Response
1 2 3 4 5 6 | |
Step 2: Upload Image Data
Endpoint: POST /api/openstack-marketplace/{tenant_uuid}/upload_image_data/{image_id}/
Uploads the binary image file content to the previously created image.
Request Format
- Content-Type:
application/octet-stream - Body: Raw binary image file data
- Method: HTTP PUT (internally) to OpenStack Glance
Example using curl
1 2 3 4 5 | |
Example Response
1 2 3 4 | |
Implementation Details
Backend Workflow
- Authentication: Uses tenant-specific OpenStack session
- Streaming: Uploads data in 8KB chunks to handle large files efficiently
- Direct API: Makes direct HTTP PUT to Glance API v2 (
/v2/images/{image_id}/file) - Verification: Confirms image exists in Glance after upload
Permission Requirements
- Service Provider Permission:
SERVICE_PROVIDER_OPENSTACK_IMAGE_MANAGEMENTrequired for public images - Tenant Access: User must have access to the target OpenStack tenant
- Offering Context: Image limits are enforced based on the marketplace offering configuration
Size and Count Limits
The plugin enforces configurable limits:
| Limit Type | Configuration Key | Description |
|---|---|---|
| Total Image Count | image_count_total_limit |
Maximum number of images per tenant |
| Total Image Size | image_size_total_limit |
Maximum total size of all images (bytes) |
Limits are checked before creation and upload respectively.
Error Handling
Common error scenarios:
| Error | Cause | Solution |
|---|---|---|
Image ID is required |
Missing image_id in URL path | Ensure correct URL format |
Image count limit exceeded |
Too many images in tenant | Remove unused images |
Image size limit would be exceeded |
File too large | Use smaller image or increase limits |
HTTPX request failed |
Network/connectivity issue | Check OpenStack connectivity |
Verification failed |
Image not found after upload | Retry upload or check OpenStack logs |
Security Considerations
- File Size Validation: Content-Length header used to validate file size before upload
- Permission Checks: Public image creation requires special permissions
- Streaming Upload: Large files handled via streaming to prevent memory issues
- SSL Verification: Configurable SSL verification for OpenStack API calls
Image Upload Troubleshooting
- Upload Timeouts: Large images may require extended timeout settings
- SSL Issues: Verify
verify_sslsetting in service configuration - Quota Exceeded: Check OpenStack image quotas in addition to Waldur limits
- Format Validation: Ensure disk_format and container_format are compatible
Network Requirements
Required Network Connectivity
The following table outlines the network ports and protocols required for Waldur to communicate with OpenStack services:
| Service | Port | Protocol | Direction | Description | Required |
|---|---|---|---|---|---|
| Keystone (Identity) | 5000 | HTTPS/HTTP | Outbound | Public API endpoint for authentication | Yes |
| Keystone (Admin) | 35357 | HTTPS/HTTP | Outbound | Admin API endpoint (deprecated in newer versions) | Version dependent |
| Nova (Compute) | 8774 | HTTPS/HTTP | Outbound | Compute API for instance management | Yes |
| Cinder (Block Storage) | 8776 | HTTPS/HTTP | Outbound | Volume API for storage management | Yes |
| Neutron (Networking) | 9696 | HTTPS/HTTP | Outbound | Network API for networking operations | Yes |
| Glance (Images) | 9292 | HTTPS/HTTP | Outbound | Image API for image management | Yes |
| Nova VNC Console | 6080 | HTTPS/HTTP | Outbound | VNC console proxy for instance access | Optional |
| Horizon Dashboard | 80/443 | HTTPS/HTTP | Outbound | Generate links to OpenStack web UI for users | Optional |
Network Configuration Notes
-
SSL/TLS Requirements:
- HTTPS is strongly recommended for all API communications
- Self-signed certificates are supported but require configuration
- Certificate validation can be disabled for testing (not recommended for production)
-
Firewall Considerations:
- All connections are initiated from Waldur to OpenStack (outbound only)
- No inbound connections to Waldur are required from OpenStack
- Stateful firewall rules should allow return traffic
-
API Endpoint Discovery:
- Waldur uses Keystone service catalog for endpoint discovery
- Only the Keystone endpoint needs to be explicitly configured
- Other service endpoints are automatically discovered from the service catalog
-
Network Latency:
- API timeout: 60 seconds (configurable)
- Recommended latency: < 100ms
- Long-running operations use asynchronous task queues
Configuration
Marketplace-Based Configuration
OpenStack integration in Waldur is configured through Marketplace offerings. The plugin provides three offering types for different resource levels:
| Offering Type | Purpose | Resource Scope |
|---|---|---|
OpenStack.Tenant |
Provision and manage OpenStack projects/tenants | Provider-level |
OpenStack.Instance |
Provision virtual machines within a tenant | Tenant-level |
OpenStack.Volume |
Provision block storage volumes within a tenant | Tenant-level |
Configuring an OpenStack Provider
To set up an OpenStack provider, create a Marketplace offering of type OpenStack.Tenant with the following configuration:
Required Connection Settings
| Parameter | Location | Description | Example |
|---|---|---|---|
backend_url |
secret_options | Keystone API endpoint URL | https://keystone.example.com:5000/v3 |
username |
secret_options | Admin account username | admin |
password |
secret_options | Admin account password | secure_password |
tenant_name |
secret_options | Admin tenant/project name | admin |
domain |
secret_options | Keystone domain (v3 only) | default |
Network Configuration
| Parameter | Location | Description | Required |
|---|---|---|---|
external_network_id |
secret_options | UUID of external network for floating IPs | Yes |
default_internal_network_mtu |
plugin_options | MTU for tenant internal networks (68-9000) | No |
ipv4_external_ip_mapping |
secret_options | NAT mapping for floating IPs | No |
Optional Settings
| Parameter | Location | Description | Default |
|---|---|---|---|
access_url |
options | Horizon dashboard URL for user links | Generated from backend_url |
verify_ssl |
options | Verify SSL certificates | true |
availability_zone |
options | Default availability zone | nova |
storage_mode |
plugin_options | Storage quota mode (fixed or dynamic) |
fixed |
Storage Modes
The plugin supports two storage quota modes:
| Mode | Description | Use Case |
|---|---|---|
fixed |
Single storage quota shared by all volume types | Simple environments with uniform storage |
dynamic |
Separate quotas per volume type (SSD, HDD, etc.) | Environments with tiered storage offerings |
In fixed mode, a single aggregate storage component tracks total block storage. All volume types share this one quota.
In dynamic mode, each OpenStack volume type becomes its own offering component with an independent quota. The generic storage component is excluded from the offering. Volume types are automatically synchronized from OpenStack when tenants are pulled.
Resource Components
OpenStack tenant offerings include the following billable components:
| Component Type | Description | Unit | Default Limit |
|---|---|---|---|
cores |
CPU cores | Count | 20 |
ram |
Memory | MB | 51200 |
storage |
Block storage (fixed mode) | MB | 1048576 |
volume_type_* |
Per-type storage (dynamic mode) | MB | Varies |
Automated Private Offerings
When AUTOMATICALLY_CREATE_PRIVATE_OFFERING is enabled in settings (default: True), the plugin automatically creates private offerings for instances and volumes when a tenant transitions to the OK state. This allows tenant users to order compute and storage resources through the Marketplace interface without administrator intervention.
Quota Mapping
OpenStack quotas are automatically synchronized with Waldur quotas:
| OpenStack Quota | Waldur Quota | Default Limit |
|---|---|---|
| cores | vcpu | 20 |
| ram | ram | 51200 MB |
| instances | instances | 30 |
| volumes | volumes | 50 |
| gigabytes | storage | 1024 GB |
| snapshots | snapshots | 50 |
| security_groups | security_group_count | 100 |
| security_group_rules | security_group_rule_count | 100 |
| floatingip | floating_ip_count | 50 |
| network | network_count | 10 |
| subnet | subnet_count | 10 |
| port | port_count | Unlimited |
Marketplace Integration
The OpenStack plugin integrates with Waldur Marketplace through the marketplace_openstack module.
Offering Types and Processors
Each offering type has dedicated processor classes that translate marketplace orders into OpenStack operations:
| Offering Type | Create Processor | Delete Processor | Resource Model |
|---|---|---|---|
OpenStack.Tenant |
TenantCreateProcessor |
TenantDeleteProcessor |
Tenant |
OpenStack.Instance |
InstanceCreateProcessor |
InstanceDeleteProcessor |
Instance |
OpenStack.Volume |
VolumeCreateProcessor |
VolumeDeleteProcessor |
Volume |
Tenant offerings also have a TenantUpdateProcessor that handles quota/limit changes by pushing updated quotas to the OpenStack backend.
Order Processing Flow
1 2 3 4 5 6 | |
For instance creation, the processor resolves the parent tenant from the offering scope, then passes attributes (name, flavor, image, security groups, networks, SSH key, user_data) to the Instance ViewSet.
For instance deletion, the processor validates that the instance is in a deletable state (SHUTOFF + OK, or ERRED) before proceeding. Both destroy (delete instance, keep volumes) and force_destroy (delete instance and all attached volumes) modes are supported.
Automatic Offering Creation
When AUTOMATICALLY_CREATE_PRIVATE_OFFERING is True (the default), transitioning a tenant to the OK state triggers automatic creation of:
- An
OpenStack.Instanceoffering in thevmcategory, scoped to the new tenant - An
OpenStack.Volumeoffering in thevolumecategory, scoped to the new tenant
These offerings are marked as private and are only visible to users with access to the parent tenant's project.
Storage Mode Impact on Components
The storage_mode setting on the tenant offering controls how storage components appear on the automatically created volume offerings:
fixed: A singlestoragecomponent represents all block storage.dynamic: Thestoragecomponent is removed and replaced by per-volume-type components (e.g.,volume_type_ssd,volume_type_hdd). These are auto-created when volume types are pulled from OpenStack.
Lost Resource Recovery
A scheduled task (create_resources_for_lost_instances_and_volumes) runs every 6 hours to detect OpenStack instances and volumes that exist in the backend but have no corresponding marketplace resource. For each orphaned resource found, a marketplace resource is automatically created. This handles cases where resources were created outside of Waldur or where marketplace records were lost.
Scheduled Tasks
The plugin runs the following automated tasks:
Core OpenStack Tasks
| Task | Schedule | Purpose |
|---|---|---|
| Pull Quotas | Every 12 hours | Synchronize quotas with OpenStack |
| Pull Resources | Every 1 hour | Update resource states (instances, volumes) |
| Pull Sub-resources | Every 2 hours | Sync networks, subnets, ports |
| Pull Properties | Every 24 hours | Update flavors, images, volume types, external networks |
| Mark Stuck Deleting Tenants as Erred | Every 24 hours | Clean up tenants stuck in deleting state |
| Mark Stuck Updating Tenants as Erred | Every 1 hour | Clean up tenants stuck in updating state |
| Delete Expired Backups | Every 10 minutes | Remove backups past retention |
| Delete Expired Snapshots | Every 10 minutes | Remove snapshots past retention |
Marketplace OpenStack Tasks
| Task | Schedule | Purpose |
|---|---|---|
| Create Resources for Lost Instances and Volumes | Every 6 hours | Recover orphaned OpenStack resources into marketplace |
| Refresh Instance Backend Metadata | Every 24 hours | Sync instance metadata from OpenStack to marketplace resources |
Administrator Operations
Initial Setup Checklist
- Create a Marketplace Offering of type
OpenStack.Tenantwith your OpenStack admin credentials insecret_options(see Configuring an OpenStack Provider). - Set the external network ID in
secret_options.external_network_idto enable floating IP allocation. - Choose a storage mode (
fixedordynamic) inplugin_options.storage_modebased on whether you need per-volume-type quotas. -
Validate connectivity by running:
1waldur validate_openstack_services --offering-uuid <UUID> --verbose -
Optionally enable write tests to verify full CRUD capabilities:
1waldur validate_openstack_services --offering-uuid <UUID> --test-writes -
Activate the offering in the marketplace to make it available to users.
CLI Commands
| Command | Purpose | Example |
|---|---|---|
validate_openstack_services |
Test connectivity and access to all OpenStack services | waldur validate_openstack_services --offering-uuid <UUID> --verbose |
drop_leftover_openstack_projects |
Remove OpenStack projects that are terminated in Waldur but still exist in OpenStack | waldur drop_leftover_openstack_projects --offering <name> --dry-run |
pull_openstack_volume_metadata |
Sync volume metadata from OpenStack to marketplace resources | waldur pull_openstack_volume_metadata --dry-run |
push_tenant_quotas |
Push marketplace quota limits to OpenStack backend | waldur push_tenant_quotas --dry-run |
import_tenant_quotas |
Import current OpenStack quota usage into marketplace | waldur import_tenant_quotas |
All commands except validate_openstack_services support the --dry-run flag to preview changes without applying them.
Connectivity Validation
The validate_openstack_services command tests each OpenStack service endpoint:
1 2 3 4 5 6 7 8 9 10 11 | |
The --test-writes flag performs actual create/delete operations for security groups, networks, volumes, server groups, floating IPs, and instances. Use this to verify full operational capability.
Feature Flags
The following UI feature flags can be toggled in the Waldur admin panel under Features:
| Flag | Description |
|---|---|
openstack.hide_volume_type_selector |
Hide the volume type dropdown when provisioning instances or volumes |
openstack.show_migrations |
Show OpenStack tenant migration action and tab in the UI |
Security and Troubleshooting
Security
-
Credential Management:
- Service account credentials are stored in the database
secret_optionsfield - Per-tenant credentials are auto-generated using random passwords
- Tenant credentials visibility can be controlled via
TENANT_CREDENTIALS_VISIBLEsetting - SSH keys are automatically distributed to tenants based on user permissions
- Service account credentials are stored in the database
-
Network Security:
- Security groups provide instance-level firewalling
- Default deny-all policy for new security groups
- RBAC policies control cross-tenant network resource sharing
- External IP mapping supports NAT scenarios
-
Audit Logging:
- All operations are logged with user attribution
- Resource state changes tracked in event log
- Failed operations logged with error details
- Quota changes trigger audit events
Common Issues
-
Connection Timeouts:
- Verify network connectivity to Keystone endpoint
- Check firewall rules for required ports
- Validate SSL certificates if using HTTPS
-
Authentication Failures:
- Verify service account credentials
- Check domain configuration for Keystone v3
- Ensure service account has admin privileges
-
Quota Synchronization Issues:
- Check OpenStack policy files for quota permissions
- Verify nova, cinder, and neutron quota drivers
- Review background task logs
- Run
waldur push_tenant_quotas --dry-runto check for mismatches - Note that
storage_modeaffects which quotas are tracked; switching modes may require re-syncing
-
Resource State Mismatches:
- Trigger manual pull operation
- Check OpenStack service status
- Review executor task logs
Troubleshooting Specific Scenarios
Resource Stuck in Creating or Deleting State
Resources that remain in a transitional state (Creating, Deleting, Updating) are automatically cleaned up by scheduled tasks:
- Tenants stuck in Deleting are marked as Erred after 24 hours.
- Tenants stuck in Updating are marked as Erred after 1 hour.
- Instances and volumes stuck in Creating are marked as Erred by the hourly resource pull task.
For manual intervention, staff users can use the set_erred API action to force a resource into the Erred state, then use pull to re-sync from the backend or unlink to remove the database record:
1 2 3 4 5 6 7 8 9 | |
The set_erred and set_ok actions are available on all OpenStack resource endpoints (networks, subnets, instances, volumes, ports, floating IPs, security groups, routers, snapshots, backups). Both actions are restricted to staff users.
Missing Marketplace Resource
If an OpenStack instance or volume exists in the backend but has no marketplace resource:
- The
create_resources_for_lost_instances_and_volumestask (runs every 6 hours) will automatically create the missing marketplace resource. - To trigger recovery immediately, run the task manually from the Celery admin or restart the beat scheduler.
- Common causes: resource created directly in OpenStack, marketplace database inconsistency, or failed order that partially completed.
Instance Deletion Failures
Instance deletion requires specific state conditions:
- The instance must be in SHUTOFF + OK or ERRED state for normal deletion.
- Running instances must be stopped first.
- Use
force_destroyto delete the instance along with all attached volumes. - If deletion fails, check that the OpenStack project still has the instance and that the service account has sufficient permissions.
Quota Mismatch Between Waldur and OpenStack
- Pull quotas from OpenStack:
waldur import_tenant_quotasimports current usage and limits. - Push quotas to OpenStack:
waldur push_tenant_quotasapplies Waldur limits to OpenStack. - When using dynamic storage mode, ensure all volume types are synchronized (the hourly properties pull task handles this automatically).
- Quota mismatches often occur after changing
storage_mode; re-import quotas after switching modes.
SSL and Certificate Issues
- Set
verify_ssltofalsein the offering'soptionsto disable certificate verification (testing only). - For self-signed certificates, add the CA certificate to the system trust store on the Waldur server.
- Certificate errors appear in Celery worker logs as
SSLErrororSSLCertVerificationError.
Configuration Reference
WALDUR_OPENSTACK Settings
These settings are configured in waldur_core.server.settings or local_settings.py under the WALDUR_OPENSTACK dictionary:
| Setting | Type | Default | Description |
|---|---|---|---|
ALLOW_CUSTOMER_USERS_OPENSTACK_CONSOLE_ACCESS |
bool | True |
Allow customer users to access the OpenStack VNC console |
ALLOW_DIRECT_EXTERNAL_NETWORK_CONNECTION |
bool | False |
Allow connecting instances directly to external networks (bypassing internal network + router) |
DEFAULT_SECURITY_GROUPS |
list[dict] | SSH (22), ping (ICMP), RDP (3389), web (80, 443) | Default security groups and rules created in each provisioned tenant |
DEFAULT_BLACKLISTED_USERNAMES |
list[str] | ["admin", "service"] |
Usernames that cannot be created by Waldur in OpenStack |
MAX_CONCURRENT_PROVISION |
dict | {"OpenStack.Instance": 4, "OpenStack.Volume": 4, "OpenStack.Snapshot": 4} |
Maximum parallel provisioning operations per resource type |
REQUIRE_AVAILABILITY_ZONE |
bool | False |
Make availability zone selection mandatory during provisioning |
SUBNET |
dict | Pool from .10 to .200 |
Default IP allocation pool range for auto-created internal subnets |
TENANT_CREDENTIALS_VISIBLE |
bool | False |
Expose auto-generated tenant credentials to project users |
Settings marked as public (ALLOW_CUSTOMER_USERS_OPENSTACK_CONSOLE_ACCESS, REQUIRE_AVAILABILITY_ZONE, ALLOW_DIRECT_EXTERNAL_NETWORK_CONNECTION, TENANT_CREDENTIALS_VISIBLE) are sent to the frontend and affect UI behavior.
WALDUR_MARKETPLACE_OPENSTACK Settings
| Setting | Type | Default | Description |
|---|---|---|---|
AUTOMATICALLY_CREATE_PRIVATE_OFFERING |
bool | True |
Auto-create private instance and volume offerings when a tenant is provisioned |
Per-Offering Configuration
In addition to the global settings above, each OpenStack offering has three configuration sections:
| Section | Visibility | Purpose | Examples |
|---|---|---|---|
secret_options |
Admin only | Sensitive credentials and connection details | backend_url, username, password, tenant_name, domain, external_network_id |
plugin_options |
Admin only | Plugin-specific behavior settings | storage_mode, default_internal_network_mtu |
options |
Visible to users | Non-sensitive offering metadata | access_url, verify_ssl, availability_zone |
API Reference
For detailed API documentation, refer to the Waldur API schema at /api/schema/ with the OpenStack plugin enabled.