Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ansible/neutron-post-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@

roles:
- role: neutron_segment_range
- role: openstack_subnet_pools
- role: openstack_network
66 changes: 66 additions & 0 deletions ansible/roles/custom_fields/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,69 @@
content_types:
- dcim.interface
filter_logic: exact

- name: Create Custom Field Subnet Pool Name
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: Name of the OpenStack subnet pool to create from this prefix
label: Subnet Pool Name
key: subnet_pool_name
type: text
required: false
weight: 100
content_types:
- ipam.prefix
filter_logic: exact

- name: Create Custom Field Subnet Pool Default Prefixlen
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: Default prefix length for subnets created from this pool
label: Default Prefixlen
key: subnet_pool_default_prefixlen
type: integer
required: false
weight: 100
content_types:
- ipam.prefix
validation_minimum: 1
validation_maximum: 32
filter_logic: exact

- name: Create Custom Field Subnet Pool Min Prefixlen
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: Minimum prefix length for subnets created from this pool
label: Min Prefixlen
key: subnet_pool_min_prefixlen
type: integer
required: false
weight: 100
content_types:
- ipam.prefix
validation_minimum: 1
validation_maximum: 32
filter_logic: exact

- name: Create Custom Field Subnet Pool Max Prefixlen
networktocode.nautobot.custom_field:
state: present
url: "{{ nautobot_url }}"
token: "{{ nautobot_token }}"
description: Maximum prefix length for subnets created from this pool
label: Max Prefixlen
key: subnet_pool_max_prefixlen
type: integer
required: false
weight: 100
content_types:
- ipam.prefix
validation_minimum: 1
validation_maximum: 32
filter_logic: exact
14 changes: 14 additions & 0 deletions ansible/roles/openstack_subnet_pools/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
# Default variables for openstack_subnet_pools role

# OpenStack cloud configuration name from clouds.yaml
openstack_cloud: understack

# Tag to filter prefixes for subnet pool creation
subnet_pool_tag: openstack-subnet-pool

# Whether to create address scopes (optional)
create_address_scopes: false

# Address scope name mapping (if create_address_scopes is true)
address_scope_name: "{{ openstack_cloud }}-address-scope"
71 changes: 71 additions & 0 deletions ansible/roles/openstack_subnet_pools/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
# Create OpenStack subnet pools from Nautobot prefixes
# This role reads prefixes tagged with 'openstack-subnet-pool' and creates
# corresponding OpenStack subnet pools with the configured allocation settings

- name: Query Nautobot for prefixes tagged with openstack-subnet-pool
ansible.builtin.uri:
url: "{{ nautobot_url }}/api/ipam/prefixes/?tags={{ subnet_pool_tag }}"
method: GET
headers:
Authorization: "Token {{ nautobot_token }}"
Accept: "application/json; version={{ nautobot_api_version }}"
status_code: 200
register: prefixes_query
check_mode: false

- name: Log queried prefixes
ansible.builtin.debug:
msg: "Found {{ prefixes_query.json.count }} prefixes tagged with '{{ subnet_pool_tag }}'"

- name: Assert prefixes were found
ansible.builtin.assert:
that:
- prefixes_query.json.count > 0
fail_msg: "No prefixes found with tag '{{ subnet_pool_tag }}' in Nautobot"

- name: Group prefixes by subnet pool name
ansible.builtin.set_fact:
subnet_pools: >-
{{
subnet_pools | default({}) | combine({
item.custom_fields.subnet_pool_name: (subnet_pools.get(item.custom_fields.subnet_pool_name, []) + [item])
})
}}
loop: "{{ prefixes_query.json.results }}"
when:
- item.custom_fields.subnet_pool_name is defined
- item.custom_fields.subnet_pool_name | length > 0

- name: Log discovered subnet pools
ansible.builtin.debug:
msg: "Discovered subnet pools: {{ subnet_pools.keys() | list }}"

- name: Create or update OpenStack subnet pools
openstack.cloud.subnet_pool:
cloud: "{{ openstack_cloud }}"
state: present
name: "{{ pool_name }}"
prefixes: "{{ pool_prefixes | map(attribute='prefix') | list }}"
default_prefixlen: "{{ (pool_prefixes | first).custom_fields.subnet_pool_default_prefixlen }}"
min_prefixlen: "{{ (pool_prefixes | first).custom_fields.subnet_pool_min_prefixlen }}"
max_prefixlen: "{{ (pool_prefixes | first).custom_fields.subnet_pool_max_prefixlen }}"
shared: true
loop: "{{ subnet_pools | dict2items }}"
loop_control:
loop_var: subnet_pool_item
label: "{{ pool_name }}"
vars:
pool_name: "{{ subnet_pool_item.key }}"
pool_prefixes: "{{ subnet_pool_item.value }}"
register: subnet_pool_results

- name: Log subnet pool creation results
ansible.builtin.debug:
msg: "Subnet pool '{{ item.subnet_pool_item.key }}': {{ 'created' if item is changed else 'unchanged' }}"
loop: "{{ subnet_pool_results.results }}"
when: item is not skipped

- name: Verify subnet pools were created
ansible.builtin.debug:
msg: "Successfully created/updated {{ subnet_pool_results.results | selectattr('subnet_pool_item.key', 'defined') | list | length }} subnet pools"
67 changes: 0 additions & 67 deletions charts/site-workflows/templates/sensor-neutron-oslo-event.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion components/nautobot/job-nautobot-post-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
type: RuntimeDefault
containers:
- name: ansible
image: ghcr.io/rackerlabs/understack/ansible:latest
image: ghcr.io/rackerlabs/understack/ansible:pr-2081
imagePullPolicy: Always
command: ["ansible-runner", "run", "/runner", "--playbook", "nautobot-post-deploy.yaml"]
resources:
Expand Down
2 changes: 1 addition & 1 deletion components/neutron/job-neutron-post-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
type: RuntimeDefault
containers:
- name: ansible
image: ghcr.io/rackerlabs/understack/ansible:latest
image: ghcr.io/rackerlabs/understack/ansible:pr-2081
imagePullPolicy: Always
command: ["ansible-runner", "run", "/runner", "--playbook", "neutron-post-deploy.yaml"]
resources:
Expand Down
2 changes: 1 addition & 1 deletion go/nautobotop/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
k8s.io/api v0.33.0
k8s.io/apimachinery v0.33.0
k8s.io/client-go v0.33.0
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
sigs.k8s.io/controller-runtime v0.21.0
)

Expand Down Expand Up @@ -118,7 +119,6 @@ require (
k8s.io/component-base v0.33.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
Expand Down
33 changes: 17 additions & 16 deletions go/nautobotop/internal/nautobot/models/prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ type Prefixes struct {
}

type Prefix struct {
ID string `json:"id" yaml:"id"`
Prefix string `json:"prefix" yaml:"prefix"`
Namespace string `json:"namespace" yaml:"namespace"`
Type string `json:"type" yaml:"type"`
Status string `json:"status" yaml:"status"`
Role string `json:"role" yaml:"role"`
Rir string `json:"rir" yaml:"rir"`
DateAllocated string `json:"date_allocated" yaml:"date_allocated"`
Description string `json:"description" yaml:"description"`
Vrfs []string `json:"vrfs" yaml:"vrfs"`
Locations []string `json:"locations" yaml:"locations"`
VlanGroup string `json:"vlan_group" yaml:"vlan_group"`
Vlan string `json:"vlan" yaml:"vlan"`
TenantGroup string `json:"tenant_group" yaml:"tenant_group"`
Tenant string `json:"tenant" yaml:"tenant"`
Tags []string `json:"tags" yaml:"tags"`
ID string `json:"id" yaml:"id"`
Prefix string `json:"prefix" yaml:"prefix"`
Namespace string `json:"namespace" yaml:"namespace"`
Type string `json:"type" yaml:"type"`
Status string `json:"status" yaml:"status"`
Role string `json:"role" yaml:"role"`
Rir string `json:"rir" yaml:"rir"`
DateAllocated string `json:"date_allocated" yaml:"date_allocated"`
Description string `json:"description" yaml:"description"`
Vrfs []string `json:"vrfs" yaml:"vrfs"`
Locations []string `json:"locations" yaml:"locations"`
VlanGroup string `json:"vlan_group" yaml:"vlan_group"`
Vlan string `json:"vlan" yaml:"vlan"`
TenantGroup string `json:"tenant_group" yaml:"tenant_group"`
Tenant string `json:"tenant" yaml:"tenant"`
Tags []string `json:"tags" yaml:"tags"`
CustomFields map[string]interface{} `json:"custom_fields" yaml:"custom_fields"`
}
5 changes: 5 additions & 0 deletions go/nautobotop/internal/nautobot/sync/prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ func (s *PrefixSync) syncSinglePrefix(ctx context.Context, prefix models.Prefix)
if len(prefix.Locations) > 1 {
customFields["locations"] = s.buildLocationIDs(ctx, prefix.Locations[1:])
}
if prefix.CustomFields != nil {
for k, v := range prefix.CustomFields {
customFields[k] = v
}
}
if len(customFields) > 0 {
prefixRequest.CustomFields = customFields
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
from understack_workflows.oslo_event import ironic_portgroup
from understack_workflows.oslo_event import keystone_project
from understack_workflows.oslo_event import nautobot_device_sync
from understack_workflows.oslo_event import neutron_network
from understack_workflows.oslo_event import neutron_subnet

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -79,12 +77,6 @@ class NoEventHandlerError(Exception):
"volume_type_project.access.remove": (
cinder_volume_type.handle_volume_type_access_removed
),
"network.create.end": neutron_network.handle_network_create_or_update,
"network.update.end": neutron_network.handle_network_create_or_update,
"network.delete.end": neutron_network.handle_network_delete,
"subnet.create.end": neutron_subnet.handle_subnet_create_or_update,
"subnet.update.end": neutron_subnet.handle_subnet_create_or_update,
"subnet.delete.end": neutron_subnet.handle_subnet_delete,
}


Expand Down
Loading