diff --git a/files/ansible-playbooks/sot-updater.yml b/files/ansible-playbooks/sot-updater.yml index 02d588c..fe95fc2 100644 --- a/files/ansible-playbooks/sot-updater.yml +++ b/files/ansible-playbooks/sot-updater.yml @@ -36,6 +36,10 @@ rmq_exchange: "{{ lookup('env','RMQ_EXCHANGE') | default('controls', true) }}" control_queue: "{{ lookup('env','CONTROLQUEUE') | default('queue_controls', true) }}" + # Cloud API (offboard provisioning telemetry) + cloud_config_base: "https://cloud.ikeja.co.za/v2/devices" + cloud_bearer: "{{ lookup('env','CLOUD_BEARER') | default('', true) }}" + # NetBox API (delta compare; user may override) netbox_url: "http://netbox.gt-tiso.ikeja.co.za" netbox_token: "7648e4f5ee370cda7834682e61b47c2ee8e95623" @@ -1251,6 +1255,209 @@ else (inventory_hostname | default('')) }} + # ----------------------- Cloud offboard provisioning telemetry ----------------------- + - name: Cloud offboard provisioning | Resolve cloud_id and initialize values + delegate_to: localhost + set_fact: + offp_cloud_id: >- + {{ + (nb_custom_fields_current.get('cloud_id','') | string | trim) + if ((nb_custom_fields_current.get('cloud_id','') | string | trim | length) > 0) + else ( + ( + (nb_preflight | default({})).get('stdout','') + | regex_findall('CL: fetch liveness cloud_id=([^\s]+)') + | first + ) | default('') + ) + }} + offp_config_ok: false + offp_status_value: "missing" + offp_sync_value: "missing" + indoor_offp_vlan_value: "missing" + changed_when: false + + - name: Cloud offboard provisioning | Read reported config + when: + - (offp_cloud_id | default('') | length) > 0 + - (cloud_bearer | default('') | length) > 0 + delegate_to: localhost + uri: + url: "{{ cloud_config_base }}/{{ offp_cloud_id }}/config" + method: GET + headers: + Authorization: "Bearer {{ cloud_bearer }}" + Accept: "application/json" + return_content: true + status_code: 200 + timeout: 30 + register: offp_config_lookup + failed_when: false + changed_when: false + + - name: Cloud offboard provisioning | Normalize reported values + when: + - offp_config_lookup is defined + - (offp_config_lookup.status | default(0) | int) == 200 + - offp_config_lookup.json is defined + delegate_to: localhost + vars: + _reported_data: "{{ (offp_config_lookup.json.get('reported', {})).get('data', {}) }}" + _offp_services: "{{ (_reported_data.get('services', {})).get('offboardProvisioning', {}) }}" + _offp_vlan: "{{ (((((((_reported_data.get('offboardProvisioned', {})).get('fox200', {})).get('ethernet', {})).get('ports', {})).get('eth0', {})).get('network', {})).get('dataVlan', {})) }}" + set_fact: + offp_config_ok: true + offp_status_value: >- + {%- if (_offp_services is mapping) and ('isEnabled' in _offp_services) -%} + {%- if _offp_services.get('isEnabled') == true -%}enabled + {%- elif _offp_services.get('isEnabled') == false -%}disabled + {%- else -%}missing{%- endif -%} + {%- else -%}missing{%- endif -%} + offp_sync_value: >- + {%- if (_offp_services is mapping) and ('isSynchronized' in _offp_services) -%} + {%- if _offp_services.get('isSynchronized') == true -%}enabled + {%- elif _offp_services.get('isSynchronized') == false -%}disabled + {%- else -%}missing{%- endif -%} + {%- else -%}missing{%- endif -%} + indoor_offp_vlan_value: >- + {%- if (_offp_vlan is mapping) and ('isEnabled' in _offp_vlan) -%} + {%- set _vlan_id = + (_offp_vlan.get('id') | string | trim) + if ( + ('id' in _offp_vlan) and + (_offp_vlan.get('id') is not none) and + ((_offp_vlan.get('id') | string | trim | length) > 0) + ) + else 'missing' + -%} + {%- if _offp_vlan.get('isEnabled') == true -%}enabled-{{ _vlan_id }} + {%- elif _offp_vlan.get('isEnabled') == false -%}disabled-{{ _vlan_id }} + {%- else -%}missing{%- endif -%} + {%- else -%}missing{%- endif -%} + changed_when: false + + - name: Cloud offboard provisioning | Debug + delegate_to: localhost + debug: + msg: + - "cloud_id={{ offp_cloud_id | default('') }}" + - "config_http={{ offp_config_lookup.status | default('not-requested') }}" + - "offp_status={{ offp_status_value | default('missing') }}" + - "offp_sync={{ offp_sync_value | default('missing') }}" + - "indoor_offp_vlan={{ indoor_offp_vlan_value | default('missing') }}" + + - name: Scan tracking | Cloud offboard provisioning outcome + delegate_to: localhost + set_fact: + scan_ok: "{{ scan_ok + (['offp_status', 'offp_sync', 'indoor_offp_vlan'] if (offp_config_ok | default(false)) else []) }}" + scan_fail: "{{ scan_fail + ([] if (offp_config_ok | default(false)) else ['offp_status=unavailable', 'offp_sync=unavailable', 'indoor_offp_vlan=unavailable']) }}" + changed_when: false + + - name: Publish Cloud offp_status custom field + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((offp_status_value) != (nb_custom_fields_current.get('offp_status'))) + delegate_to: localhost + uri: + url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost|urlencode }}/{{ rmq_exchange|urlencode }}/publish" + method: POST + user: "{{ rmq_user }}" + password: "{{ rmq_pass }}" + force_basic_auth: true + status_code: 200 + headers: { content-type: "application/json" } + body_format: json + body: + properties: { content_type: "application/json" } + routing_key: "{{ control_queue }}" + payload: "{{ { + 'inscope_device': (ansible_hostname|default(inventory_hostname)), + 'task_name': 'custom_field_set', + 'task_add1': 'offp_status', + 'task_result': offp_status_value + } | to_json }}" + payload_encoding: "string" + changed_when: false + + - name: Delta tracking | Mark changed offp_status + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((offp_status_value) != (nb_custom_fields_current.get('offp_status'))) + delegate_to: localhost + set_fact: + non_ts_diff_found: true + changed_when: false + + - name: Publish Cloud offp_sync custom field + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((offp_sync_value) != (nb_custom_fields_current.get('offp_sync'))) + delegate_to: localhost + uri: + url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost|urlencode }}/{{ rmq_exchange|urlencode }}/publish" + method: POST + user: "{{ rmq_user }}" + password: "{{ rmq_pass }}" + force_basic_auth: true + status_code: 200 + headers: { content-type: "application/json" } + body_format: json + body: + properties: { content_type: "application/json" } + routing_key: "{{ control_queue }}" + payload: "{{ { + 'inscope_device': (ansible_hostname|default(inventory_hostname)), + 'task_name': 'custom_field_set', + 'task_add1': 'offp_sync', + 'task_result': offp_sync_value + } | to_json }}" + payload_encoding: "string" + changed_when: false + + - name: Delta tracking | Mark changed offp_sync + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((offp_sync_value) != (nb_custom_fields_current.get('offp_sync'))) + delegate_to: localhost + set_fact: + non_ts_diff_found: true + changed_when: false + + - name: Publish Cloud indoor_offp_vlan custom field + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((indoor_offp_vlan_value) != (nb_custom_fields_current.get('indoor_offp_vlan'))) + delegate_to: localhost + uri: + url: "http://{{ rmq_host }}:{{ rmq_port }}/api/exchanges/{{ rmq_vhost|urlencode }}/{{ rmq_exchange|urlencode }}/publish" + method: POST + user: "{{ rmq_user }}" + password: "{{ rmq_pass }}" + force_basic_auth: true + status_code: 200 + headers: { content-type: "application/json" } + body_format: json + body: + properties: { content_type: "application/json" } + routing_key: "{{ control_queue }}" + payload: "{{ { + 'inscope_device': (ansible_hostname|default(inventory_hostname)), + 'task_name': 'custom_field_set', + 'task_add1': 'indoor_offp_vlan', + 'task_result': indoor_offp_vlan_value + } | to_json }}" + payload_encoding: "string" + changed_when: false + + - name: Delta tracking | Mark changed indoor_offp_vlan + when: + - offp_config_ok | default(false) + - (not (nb_baseline_ok | default(false))) or ((indoor_offp_vlan_value) != (nb_custom_fields_current.get('indoor_offp_vlan'))) + delegate_to: localhost + set_fact: + non_ts_diff_found: true + changed_when: false + # ----------------------- Dev2 auth + firmux ----------------------- - name: Try DEV2 login when: tunnel_ok|default(false)