Skip to content

Commit 5c7c359

Browse files
using generic handler rather than creating new files.
1 parent 753613d commit 5c7c359

File tree

13 files changed

+111
-445
lines changed

13 files changed

+111
-445
lines changed

components/site-workflows/kustomization.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ resources:
2222
- sensors/sensor-neutron-olso-event.yaml
2323
- sensors/sensor-ironic-reclean.yaml
2424
- sensors/sensor-ironic-node-port.yaml
25-
- sensors/sensor-ironic-oslo-deploying-event.yaml
26-
- sensors/sensor-ironic-oslo-inspecting-event.yaml
25+
- sensors/sensor-ironic-oslo-event.yaml
2726

2827
helmCharts:
2928
- name: nautobot-token

components/site-workflows/sensors/sensor-ironic-oslo-deploying-event.yaml renamed to components/site-workflows/sensors/sensor-ironic-oslo-event.yaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apiVersion: argoproj.io/v1alpha1
33
kind: Sensor
44
metadata:
5-
name: ironic-oslo-deploying-event
5+
name: ironic-oslo-event
66
annotations:
77
workflows.argoproj.io/title: Process oslo_events for ironic project
88
workflows.argoproj.io/description: |+
@@ -17,7 +17,7 @@ metadata:
1717
-p event-json "JSON-payload" -p device_id=<UUID> -p project_id=<UUID>
1818
```
1919
20-
Defined in `workflows/argo-events/sensors/sensor-sensor-ironic-oslo-deploying-event.yaml`
20+
Defined in `components/site-workflows/sensors/sensor-ironic-oslo-event.yaml`
2121
spec:
2222
dependencies:
2323
- eventName: openstack
@@ -43,6 +43,7 @@ spec:
4343
type: "string"
4444
value:
4545
- "deploying"
46+
- "inspecting"
4647
template:
4748
serviceAccountName: sensor-submit-workflow
4849
triggers:
@@ -64,6 +65,10 @@ spec:
6465
src:
6566
dataKey: body.ironic_object.lessee
6667
dependencyName: ironic-dep
68+
- dest: spec.arguments.parameters.3.value # previous_provision_state
69+
src:
70+
dataKey: body.ironic_object.previous_provision_state
71+
dependencyName: ironic-dep
6772
source:
6873
# create a workflow in argo-events prefixed with ironic-prov-
6974
resource:
@@ -81,6 +86,7 @@ spec:
8186
- name: event-json
8287
- name: device_id
8388
- name: project_id
89+
- name: previous_provision_state
8490
templates:
8591
- name: main
8692
steps:
@@ -93,6 +99,7 @@ spec:
9399
- name: event-json
94100
value: "{{workflow.parameters.event-json}}"
95101
- name: convert-project-id
102+
when: "\"{{workflow.parameters.previous_provision_state}}\" == deploying"
96103
inline:
97104
script:
98105
image: python:alpine
@@ -102,7 +109,7 @@ spec:
102109
project_id_without_dashes = "{{workflow.parameters.project_id}}"
103110
print(str(uuid.UUID(project_id_without_dashes)))
104111
- - name: ansible-storage-update
105-
when: "\"{{steps.oslo-events.outputs.parameters.storage}}\" == wanted"
112+
when: "\"{{steps.oslo-events.outputs.parameters.storage}}\" == wanted && \"{{workflow.parameters.previous_provision_state}}\" == deploying"
106113
templateRef:
107114
name: ansible-workflow-template
108115
template: ansible-run

components/site-workflows/sensors/sensor-ironic-oslo-inspecting-event.yaml

Lines changed: 0 additions & 84 deletions
This file was deleted.

docs/operator-guide/openstack-ironic-nautobot-device-interfaces-sync.md

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ Server Enrollment → Redfish Inspection → Oslo Event Bus → Argo Events Sens
7070

7171
5. **Workflow Trigger**
7272
- Sensor creates an Argo Workflow named `update-nautobot-*`
73-
- Workflow uses template `update-nautobot-on-openstack-oslo-event`
73+
- Workflow uses template `openstack-oslo-event`
7474
- Event data is passed as workflow parameter
7575

7676
6. **Data Processing**
77-
- Workflow executes `update-nautobot-on-openstack-oslo-event` script
77+
- Workflow executes `openstack-oslo-event` script
7878
- Script fetches full inventory data from Ironic API using node UUID
7979
- Inventory data is parsed and transformed into Nautobot format
8080

@@ -99,11 +99,11 @@ The sensor configuration defines:
9999

100100
### Workflow Template
101101

102-
**File:** `workflows/argo-events/workflowtemplates/update-nautobot-on-openstack-oslo-event.yaml`
102+
**File:** `workflows/argo-events/workflowtemplates/openstack-oslo-event.yaml`
103103

104104
The workflow template:
105105

106-
- Runs the `update-nautobot-on-openstack-oslo-event` command
106+
- Runs the `openstack-oslo-event` command
107107
- Mounts Nautobot token and OpenStack credentials
108108
- Passes event JSON as input file
109109
- Uses service account with appropriate permissions
@@ -135,8 +135,6 @@ LLDP (Link Layer Discovery Protocol) data is extracted from inspection results:
135135
- **Port ID (Type 2)**: Remote switch port name
136136
- **Port Description (Type 4)**: Alternative port identifier
137137

138-
The system requires a minimum of 3 LLDP neighbors to be discovered for validation.
139-
140138
#### Device Information
141139

142140
The following device attributes are extracted:
@@ -158,7 +156,6 @@ The following device attributes are extracted:
158156
1. **Switch Discovery**
159157
- Identifies switches using LLDP MAC addresses
160158
- Queries Nautobot for devices with matching `chassis_mac_address` custom field
161-
- Validates all switches are in the same location/rack
162159

163160
2. **Device Lookup**
164161
- Searches for existing device by serial number
@@ -186,36 +183,6 @@ The following device attributes are extracted:
186183
- Associates IP with interface in Nautobot IPAM
187184
- Converts DHCP leases to static assignments if applicable
188185

189-
## Validation and Error Handling
190-
191-
### LLDP Neighbor Validation
192-
193-
The system validates that sufficient LLDP neighbors are discovered:
194-
195-
```python
196-
MIN_REQUIRED_NEIGHBOR_COUNT = 3
197-
```
198-
199-
If fewer than 3 neighbors are found, the workflow fails with a detailed error message showing which interfaces have LLDP data.
200-
201-
### Location Consistency
202-
203-
All connected switches must be in the same location and rack. If switches span multiple locations, the workflow fails to prevent topology errors.
204-
205-
### IP Address Conflicts
206-
207-
The system detects and prevents:
208-
209-
- IP addresses already assigned to different interfaces
210-
- Interfaces already associated with different IP addresses
211-
212-
### Switch Port Conflicts
213-
214-
When creating cables, the system validates:
215-
216-
- Switch interface exists in Nautobot
217-
- Switch port is not already connected to another device
218-
219186
## Monitoring and Troubleshooting
220187

221188
### Viewing Workflow Executions
@@ -266,13 +233,13 @@ This will publish the Oslo event and trigger Nautobot synchronization.
266233
You can manually trigger the Nautobot update workflow for testing:
267234

268235
```bash
269-
# Capture an event from Ironic
270-
openstack baremetal node show <node-uuid> -f json > node.json
236+
# To view inspect inventory data
237+
openstack baremetal node inventory save [--file <filename>] <node>
271238

272239
# Submit workflow manually
273240
argo -n argo-events submit \
274-
--from workflowtemplate/update-nautobot-on-openstack-oslo-event \
275-
-p event-json "$(cat node.json)"
241+
--from workflowtemplate/openstack-oslo-event \
242+
-p event-json '{"event_type":"baremetal.node.provision_set.end","payload":{"ironic_object.data":{"uuid":"<node-uuid>", "previous_provision_state":"inspecting"}}}'
276243
```
277244

278245
### Verifying Results

python/understack-workflows/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ sync-network-segment-range = "understack_workflows.main.sync_ucvni_group_range:m
4040
openstack-oslo-event = "understack_workflows.main.openstack_oslo_event:main"
4141
netapp-create-svm = "understack_workflows.main.netapp_create_svm:main"
4242
netapp-configure-interfaces = "understack_workflows.main.netapp_configure_net:main"
43-
update-nautobot-on-openstack-oslo-event = "understack_workflows.main.update_nautobot:main"
4443

4544
[dependency-groups]
4645
test = [

python/understack-workflows/understack_workflows/ironic/client.py

Lines changed: 6 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,84 +11,33 @@
1111

1212

1313
class IronicClient:
14-
def __init__(
15-
self,
16-
ironic_client: IronicV1Client | None = None,
17-
) -> None:
18-
"""Initialize our ironicclient wrapper."""
19-
self.logged_in = False
20-
self._client = ironic_client
21-
self._client_factory = get_ironic_client
22-
23-
@property
24-
def client(self) -> IronicV1Client:
25-
"""Get the ironic client, creating it lazily if needed."""
26-
if self._client is None:
27-
self._client = self._client_factory()
28-
return self._client
29-
30-
def login(self):
31-
self._client = get_ironic_client()
32-
self.logged_in = True
14+
def __init__(self, cloud: str | None = None) -> None:
15+
self.client: IronicV1Client = get_ironic_client(cloud=cloud)
3316

3417
def create_node(self, node_data: dict) -> Node:
35-
self._ensure_logged_in()
36-
3718
return cast(Node, self.client.node.create(**node_data))
3819

3920
def list_nodes(self):
40-
self._ensure_logged_in()
41-
4221
return self.client.node.list()
4322

4423
def get_node(self, node_ident: str, fields: list[str] | None = None) -> Node:
45-
self._ensure_logged_in()
46-
47-
return cast(
48-
Node,
49-
self.client.node.get(
50-
node_ident,
51-
fields,
52-
),
53-
)
24+
return cast(Node, self.client.node.get(node_ident, fields))
5425

5526
def update_node(self, node_id, patch):
56-
self._ensure_logged_in()
57-
58-
return self.client.node.update(
59-
node_id,
60-
patch,
61-
)
27+
return self.client.node.update(node_id, patch)
6228

6329
def create_port(self, port_data: dict):
64-
self._ensure_logged_in()
65-
6630
return self.client.port.create(**port_data)
6731

6832
def update_port(self, port_id: str, patch: list):
69-
self._ensure_logged_in()
70-
71-
return self.client.port.update(
72-
port_id,
73-
patch,
74-
)
33+
return self.client.port.update(port_id, patch)
7534

7635
def delete_port(self, port_id: str):
77-
self._ensure_logged_in()
78-
79-
return self.client.port.delete(
80-
port_id,
81-
)
36+
return self.client.port.delete(port_id)
8237

8338
def list_ports(self, node_id: str):
84-
self._ensure_logged_in()
85-
8639
return self.client.port.list(node=node_id, detail=True)
8740

88-
def _ensure_logged_in(self):
89-
if not self.logged_in:
90-
self.login()
91-
9241
def get_node_inventory(self, node_ident: str) -> dict:
9342
"""Fetch node inventory data from Ironic API.
9443

0 commit comments

Comments
 (0)