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
110 changes: 110 additions & 0 deletions components/site-workflows/sensors/sensor-nova-oslo-event.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
name: nova-oslo-event
annotations:
workflows.argoproj.io/title: Process oslo_events for nova compute
workflows.argoproj.io/description: |+
Triggers on the following Nova Events:

- compute.instance.delete.end which happens when a server is deleted

Resulting code should be very similar to:

```
argo -n argo-events submit --from workflowtemplate/openstack-oslo-event \
-p event-json "JSON-payload"
```

Defined in `components/site-workflows/sensors/sensor-nova-oslo-event.yaml`
spec:
dependencies:
- eventName: notifications
eventSourceName: openstack-nova
name: nova-dep
transform:
# the event is a string-ified JSON so we need to decode it
# replace the whole event body
jq: |
.body = (.body["oslo.message"] | fromjson)
filters:
# applies each of the items in data with 'and' but there's only one
dataLogicalOperator: "and"
data:
- path: "body.event_type"
type: "string"
value:
- "compute.instance.delete.end"
template:
serviceAccountName: sensor-submit-workflow
triggers:
- template:
name: nova-instance-delete
k8s:
operation: create
parameters:
# first parameter is the parsed oslo.message
- dest: spec.arguments.parameters.0.value
src:
dataKey: body
dependencyName: nova-dep
- dest: spec.arguments.parameters.1.value
src:
dataKey: body.payload.instance_id
dependencyName: nova-dep
- dest: spec.arguments.parameters.2.value
src:
dataKey: body.payload.tenant_id
dependencyName: nova-dep
source:
# create a workflow in argo-events prefixed with nova-delete-
resource:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: nova-delete-
namespace: argo-events
spec:
serviceAccountName: workflow
entrypoint: main
# defines the parameters being replaced above
arguments:
parameters:
- name: event-json
- name: instance_id
- name: project_id
templates:
- name: main
steps:
- - name: oslo-events
templateRef:
name: openstack-oslo-event
template: main
arguments:
parameters:
- name: event-json
value: "{{workflow.parameters.event-json}}"
- name: convert-project-id
inline:
script:
image: python:alpine
command: [python]
source: |
import uuid
project_id_without_dashes = "{{workflow.parameters.project_id}}"
print(str(uuid.UUID(project_id_without_dashes)))

- - name: ansible-delete-server-storage
when: "{{steps.oslo-events.outputs.parameters.server_storage_deleted}} == True"
templateRef:
name: ansible-workflow-template
template: ansible-run
arguments:
parameters:
- name: playbook
value: storage_on_server_delete.yml
- name: extra_vars
value: device_id={{steps.oslo-events.outputs.parameters.node_uuid}} instance_id={{workflow.parameters.instance_id}} project_id={{steps.convert-project-id.outputs.result}}
- name: check_mode
value: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class NoEventHandlerError(Exception):
"baremetal.portgroup.update.end": ironic_portgroup.handle_portgroup_create_update,
"baremetal.portgroup.delete.end": ironic_portgroup.handle_portgroup_delete,
"baremetal.node.provision_set.end": ironic_node.handle_provision_end,
"compute.instance.delete.end": ironic_node.handle_instance_delete,
"identity.project.created": keystone_project.handle_project_created,
"identity.project.updated": keystone_project.handle_project_updated,
"identity.project.deleted": keystone_project.handle_project_deleted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,51 @@ def create_volume_connector(conn: Connection, event: IronicProvisionSetEvent):

def instance_nqn(instance_id: UUID):
return f"nqn.2014-08.org.nvmexpress:uuid:{instance_id}"


def handle_instance_delete(conn: Connection, _: Nautobot, event_data: dict) -> int:
"""Operates on a Nova instance delete event to clean up storage networking."""
payload = event_data.get("payload", {})
instance_uuid = payload.get("instance_id")

if not instance_uuid:
logger.error("No instance_id found in delete event payload")
return 1

logger.info("Processing instance delete for %s", instance_uuid)

# Get the server to find the node_uuid
try:
server = conn.get_server_by_id(instance_uuid)
if not server:
logger.warning("Server %s not found, may already be deleted", instance_uuid)
save_output("server_storage_deleted", "True")
save_output("node_uuid", "unknown")
save_output("instance_uuid", str(instance_uuid))
return 0

# Check if this server had storage enabled
if server.metadata.get("storage") != "wanted":
logger.info("Server %s did not have storage enabled, skipping cleanup", instance_uuid)
save_output("server_storage_deleted", "False")
return 0

# Get node_uuid from the server's hypervisor_hostname or other field
# The node_uuid might be in server properties
node_uuid = getattr(server, 'hypervisor_hostname', None) or getattr(server, 'OS-EXT-SRV-ATTR:hypervisor_hostname', None)

logger.info("Marking server storage for deletion: instance=%s, node=%s", instance_uuid, node_uuid)
save_output("server_storage_deleted", "True")
save_output("node_uuid", str(node_uuid) if node_uuid else "unknown")
save_output("instance_uuid", str(instance_uuid))

# Get project/lessee info
project_id = server.project_id
if project_id:
save_output("project_id", project_id)

return 0

except Exception as e:
logger.exception("Error processing instance delete: %s", e)
return 1
3 changes: 3 additions & 0 deletions workflows/argo-events/workflowtemplates/ansible-run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ spec:
default: "var=default"
- name: inventory_file
default: inventory/in-cluster/01-nautobot.yaml
- name: check_mode
default: "false"
container:
image: ghcr.io/rss-engineering/undercloud-nautobot/ansible:latest
command: [ansible-playbook]
Expand All @@ -29,6 +31,7 @@ spec:
- "-i"
- "{{ inputs.parameters.inventory_file }}"
- "-vvv"
- "{{- if eq inputs.parameters.check_mode \"true\" }}--check{{- end }}"
env:
- name: NAUTOBOT_TOKEN
valueFrom:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ spec:
valueFrom:
path: /var/run/argo/output.svm_created
default: "False"
- name: server_storage_deleted
valueFrom:
path: /var/run/argo/output.server_storage_deleted
default: "False"
- name: project_tags
valueFrom:
path: /var/run/argo/output.project_tags
Expand Down
Loading