Skip to content

Commit 9a3225d

Browse files
committed
feat: add storage network server delete automation
This change implements automated storage network cleanup triggered by OpenStack server delete events. When an instance is deleted via 'openstack server delete', the system now automatically removes the corresponding storage network configuration through an event-driven workflow. The automation flow works as follows: 1. Nova emits Oslo notification events for instance delete operations 2. Argo Events captures these notifications via RabbitMQ event source 3. Sensor filters trigger the storage cleanup workflow for delete events 4. Ansible playbooks update Nautobot to reflect the removed instance 5. Nautobot Golden Config generates updated switch configurations 6. Switch update playbook applies the network changes to remove storage network access This completes the storage network automation lifecycle (create was previously merged), enabling zero-touch storage network deprovisioning that keeps network state synchronized with compute instance lifecycle without manual intervention. Changes include: - Added Nova Oslo event source and RabbitMQ user configuration - Created sensor for Nova instance delete events with event filtering - Enabled IronicUnderstackDriver in Nova configuration for storage network integration - Updated site-workflows kustomization to include new event sources and sensors
1 parent 0f9a697 commit 9a3225d

5 files changed

Lines changed: 178 additions & 0 deletions

File tree

components/nova/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ conf:
9393
uwsgi:
9494
processes: 2
9595

96+
# Enable oslo.messaging notifications for Argo Events integration
97+
oslo_messaging_notifications:
98+
driver: messagingv2
99+
96100
console:
97101
# we are working with baremetal nodes and not QEMU so we don't need novnc or spice
98102
# connected to QEMU
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
apiVersion: argoproj.io/v1alpha1
2+
kind: EventSource
3+
metadata:
4+
name: openstack-nova
5+
spec:
6+
amqp:
7+
# this is our eventName
8+
notifications:
9+
# amqp server url
10+
url: amqp://rabbitmq-server-0.rabbitmq-nodes.openstack.svc.cluster.local:5672/nova
11+
# jsonBody specifies that all event body payload coming from this
12+
# source will be JSON
13+
jsonBody: true
14+
# name of the exchange.
15+
exchangeName: nova
16+
exchangeType: topic
17+
exchangeDeclare:
18+
durable: true
19+
# routing key for messages within the exchange
20+
routingKey: 'notifications.info'
21+
# queue settings, if not provided defaults are used
22+
queueDeclare:
23+
name: argo_notifications
24+
durable: true
25+
exclusive: false
26+
autoDelete: false
27+
noWait: true
28+
29+
# optional consume settings
30+
# if not provided, default values will be used
31+
consume:
32+
consumerTag: "argo-events"
33+
autoAck: true
34+
exclusive: false
35+
noLocal: false
36+
# username and password for authentication
37+
# use secret selectors
38+
auth:
39+
username:
40+
name: argo-nova-user-credentials
41+
key: username
42+
password:
43+
name: argo-nova-user-credentials
44+
key: password
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
apiVersion: rabbitmq.com/v1beta1
3+
kind: User
4+
metadata:
5+
name: argo-nova
6+
spec:
7+
rabbitmqClusterReference:
8+
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource
9+
namespace: openstack
10+
---
11+
apiVersion: rabbitmq.com/v1beta1
12+
kind: Permission
13+
metadata:
14+
name: argo-nova
15+
spec:
16+
vhost: "nova"
17+
userReference:
18+
name: "argo-nova" # name of a user.rabbitmq.com in the same namespace; must specify either spec.userReference or spec.user
19+
permissions:
20+
write: ".*"
21+
configure: ".*"
22+
read: ".*"
23+
rabbitmqClusterReference:
24+
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource
25+
namespace: openstack

components/site-workflows/kustomization.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ resources:
55
- eventbus/eventbus-default.yaml
66
- eventbus/poddisruptionbudget-eventbus-default-pdb.yaml
77
- eventsources/eventsource-openstack-ironic.yaml
8+
- eventsources/eventsource-openstack-nova.yaml
89
- eventsources/eventsource-openstack-keystone.yaml
910
- eventsources/eventsource-openstack-neutron.yaml
1011
- eventsources/rabbitmq-user-argo-ironic.yaml
12+
- eventsources/rabbitmq-user-argo-nova.yaml
1113
- eventsources/rabbitmq-user-argo-keystone.yaml
1214
- eventsources/rabbitmq-user-argo-neutron.yaml
1315
- eventsources/eventsource-k8s-openstack-secrets.yaml
@@ -26,6 +28,7 @@ resources:
2628
- sensors/sensor-ironic-oslo-event.yaml
2729
# CronWorkflows
2830
- cronworkflows/resync-ironic-nautobot.yaml
31+
- sensors/sensor-nova-oslo-event.yaml
2932

3033
helmCharts:
3134
- name: nautobot-token
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
apiVersion: argoproj.io/v1alpha1
3+
kind: Sensor
4+
metadata:
5+
name: nova-oslo-event
6+
annotations:
7+
workflows.argoproj.io/title: Process oslo_events for nova compute
8+
workflows.argoproj.io/description: |+
9+
Triggers on the following Nova Events:
10+
11+
- compute.instance.delete.end which happens when a server is deleted
12+
AND the server has metadata.storage == "wanted"
13+
14+
This sensor uses data filters to check the storage metadata and directly
15+
triggers the ansible playbook without requiring a Python handler.
16+
17+
The sensor extracts the following parameters from the event:
18+
- device_id: from payload.node (the Baremetal Node ID)
19+
- project_id: from payload.tenant_id (UUID without dashes)
20+
21+
These are passed directly to the storage_on_server_delete.yml ansible playbook.
22+
23+
Defined in `components/site-workflows/sensors/sensor-nova-oslo-event.yaml`
24+
spec:
25+
dependencies:
26+
- eventName: notifications
27+
eventSourceName: openstack-nova
28+
name: nova-dep
29+
transform:
30+
# the event is a string-ified JSON so we need to decode it
31+
# replace the whole event body and add a storage_wanted flag
32+
jq: |
33+
.body = (.body["oslo.message"] | fromjson) |
34+
.body.storage_wanted = (.body.payload.metadata.storage // "none")
35+
filters:
36+
# applies each of the items in data with 'and'
37+
dataLogicalOperator: "and"
38+
data:
39+
- path: "body.event_type"
40+
type: "string"
41+
value:
42+
- "compute.instance.delete.end"
43+
# Only process if storage was wanted
44+
- path: "body.storage_wanted"
45+
type: "string"
46+
value:
47+
- "wanted"
48+
template:
49+
serviceAccountName: sensor-submit-workflow
50+
triggers:
51+
- template:
52+
name: nova-instance-delete
53+
k8s:
54+
operation: create
55+
parameters:
56+
- dest: spec.arguments.parameters.0.value
57+
src:
58+
dataKey: body.payload.node
59+
dependencyName: nova-dep
60+
- dest: spec.arguments.parameters.1.value
61+
src:
62+
dataKey: body.payload.tenant_id
63+
dependencyName: nova-dep
64+
source:
65+
# create a workflow in argo-events prefixed with nova-delete-
66+
resource:
67+
apiVersion: argoproj.io/v1alpha1
68+
kind: Workflow
69+
metadata:
70+
generateName: nova-delete-
71+
namespace: argo-events
72+
spec:
73+
serviceAccountName: workflow
74+
entrypoint: main
75+
# defines the parameters extracted from the event
76+
arguments:
77+
parameters:
78+
- name: device_id
79+
- name: project_id
80+
templates:
81+
- name: main
82+
steps:
83+
- - name: ansible-delete-server-storage
84+
templateRef:
85+
name: ansible-workflow-template
86+
template: ansible-run
87+
arguments:
88+
parameters:
89+
- name: playbook
90+
value: storage_on_server_delete.yml
91+
- name: extra_vars
92+
value: device_id={{workflow.parameters.device_id}} project_id={{workflow.parameters.project_id}}
93+
- - name: ansible-update-switches
94+
templateRef:
95+
name: ansible-workflow-template
96+
template: ansible-run
97+
arguments:
98+
parameters:
99+
- name: playbook
100+
value: storage_update_switches.yml
101+
- name: extra_vars
102+
value: plan_mode=remediation

0 commit comments

Comments
 (0)