From 564a956253b06802d20fd8a59427177df809faab Mon Sep 17 00:00:00 2001 From: pavel Date: Mon, 19 Jan 2026 19:17:47 +0200 Subject: [PATCH] 1917 --- files/ansible-playbooks/sot-updater.yml | 211 ++++++++++++++++++------ 1 file changed, 164 insertions(+), 47 deletions(-) diff --git a/files/ansible-playbooks/sot-updater.yml b/files/ansible-playbooks/sot-updater.yml index a8fd6a6..579284c 100644 --- a/files/ansible-playbooks/sot-updater.yml +++ b/files/ansible-playbooks/sot-updater.yml @@ -265,7 +265,6 @@ ) meta: end_host - - name: "NB preflight | Pause 1s if OK" when: - nb_script.stat.exists @@ -498,7 +497,6 @@ failed_when: false ignore_errors: true - - name: Dev1 | Normalize SSID profiles summary delegate_to: localhost set_fact: @@ -705,7 +703,6 @@ payload_encoding: "string" changed_when: false - # ----------------------- Dev1 wifidebug.sh check & publish ----------------------- - name: Dev1 | Check wifidebug.sh presence delegate_to: localhost @@ -1154,50 +1151,6 @@ | ternary(dev2_auth_lldp6.stdout | default('') | trim, 'NONE') }} - - - name: Indoor | Compute resolved IP for NetBox indoor_ip - delegate_to: localhost - set_fact: - indoor_conn_ip: >- - {%- if (tunnel_ok | default(false)) and (dev2_passfile_used | default('NONE')) != 'NONE' -%} - {{ dev2_host }} - {%- elif (dev2_passfile_used_lldp is defined) - and (dev2_passfile_used_lldp | default('NONE')) != 'NONE' - and (lldp_dev2_ip | default('') | length) > 0 -%} - {{ lldp_dev2_ip }} - {%- elif (dev2_passfile_used_lldp6 is defined) - and (dev2_passfile_used_lldp6 | default('NONE')) != 'NONE' - and (lldp_dev2_ip6 | default('') | length) > 0 -%} - {{ lldp_dev2_ip6 }} - {%- else -%} - na - {%- endif -%} - changed_when: false - - - name: Publish Dev2 indoor_ip custom field - 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_ip', - 'task_result': indoor_conn_ip - } | to_json }}" - payload_encoding: "string" - changed_when: false - - - name: Dev2 | IPv6 LLDP passfile decision when: - tunnel_ok | default(false) @@ -1634,6 +1587,170 @@ payload_encoding: "string" changed_when: false + # ----------------------- Dev2 indoor_ip resolution (ppp0/eth0.4000 preferred) ----------------------- + - name: Indoor | Compute fallback connected IP (as used for Dev2 reachability) + delegate_to: localhost + set_fact: + indoor_conn_ip_fallback: >- + {%- if (tunnel_ok | default(false)) and (dev2_passfile_used | default('NONE')) != 'NONE' -%} + {{ dev2_host }} + {%- elif (dev2_passfile_used_lldp is defined) + and (dev2_passfile_used_lldp | default('NONE')) != 'NONE' + and (lldp_dev2_ip | default('') | length) > 0 -%} + {{ lldp_dev2_ip }} + {%- elif (dev2_passfile_used_lldp6 is defined) + and (dev2_passfile_used_lldp6 | default('NONE')) != 'NONE' + and (lldp_dev2_ip6 | default('') | length) > 0 -%} + {{ lldp_dev2_ip6 }} + {%- else -%} + na + {%- endif -%} + changed_when: false + + - name: Dev2 | Read ppp0 10/8 IPv4 (preferred) + when: + - (dev2_passfile_used | default('NONE')) != 'NONE' + or ((dev2_passfile_used_lldp | default('NONE')) != 'NONE') + or ((dev2_passfile_used_lldp6 | default('NONE')) != 'NONE') + delegate_to: localhost + shell: | + set -o pipefail + + # Choose connection method (tunnel > LLDP IPv4 > LLDP IPv6) + if [ "{{ dev2_passfile_used | default('NONE') }}" != "NONE" ]; then + PORT="{{ _local_port }}" + sshpass -f "{{ dev2_passfile_used }}" ssh {{ ssh_opts_common }} \ + -o ConnectTimeout={{ ssh_timeout }} \ + -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \ + "ip -o -4 addr show dev ppp0 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | grep -m1 '^10\\.' || true" + exit 0 + fi + + if [ "{{ dev2_passfile_used_lldp | default('NONE') }}" != "NONE" ] && [ -n "{{ lldp_dev2_ip | default('') }}" ]; then + sshpass -f "{{ dev2_passfile_used_lldp }}" ssh \ + -o StrictHostKeyChecking=no -o PubkeyAuthentication=no \ + -o ConnectTimeout=15 \ + "{{ dev2_ssh_user }}@{{ lldp_dev2_ip }}" \ + "ip -o -4 addr show dev ppp0 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | grep -m1 '^10\\.' || true" + exit 0 + fi + + if [ "{{ dev2_passfile_used_lldp6 | default('NONE') }}" != "NONE" ] && [ -n "{{ lldp_dev2_ip6 | default('') }}" ]; then + IP6="{{ lldp_dev2_ip6 }}" + F="{{ dev2_passfile_used_lldp6 }}" + sshpass -p '{{ dev1_pass }}' ssh {{ ssh_opts_common }} \ + "{{ dev1_user }}@{{ ansible_host|default(inventory_hostname) }}" \ + "sshpass -f '/tmp/${F}' ssh \ + -o StrictHostKeyChecking=no -o PubkeyAuthentication=no \ + -o ConnectTimeout={{ ssh_timeout }} \ + '{{ dev2_ssh_user }}@\[${IP6}%{{ dev1_iface }}\]' \ + \"ip -o -4 addr show dev ppp0 2>/dev/null | awk '{print \\\\\$4}' | cut -d/ -f1 | grep -m1 '^10\\\\.' || true\"" + exit 0 + fi + + exit 0 + args: + executable: /bin/bash + register: dev2_ppp0_ip + changed_when: false + failed_when: false + ignore_errors: true + + - name: Dev2 | Read eth0.4000 10/8 IPv4 (only if ppp0 not usable) + when: + - (dev2_ppp0_ip.stdout | default('') | trim) == '' + - (dev2_passfile_used | default('NONE')) != 'NONE' + or ((dev2_passfile_used_lldp | default('NONE')) != 'NONE') + or ((dev2_passfile_used_lldp6 | default('NONE')) != 'NONE') + delegate_to: localhost + shell: | + set -o pipefail + + # Choose connection method (tunnel > LLDP IPv4 > LLDP IPv6) + if [ "{{ dev2_passfile_used | default('NONE') }}" != "NONE" ]; then + PORT="{{ _local_port }}" + sshpass -f "{{ dev2_passfile_used }}" ssh {{ ssh_opts_common }} \ + -o ConnectTimeout={{ ssh_timeout }} \ + -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \ + "ip -o -4 addr show dev eth0.4000 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | grep -m1 '^10\\.' || true" + exit 0 + fi + + if [ "{{ dev2_passfile_used_lldp | default('NONE') }}" != "NONE" ] && [ -n "{{ lldp_dev2_ip | default('') }}" ]; then + sshpass -f "{{ dev2_passfile_used_lldp }}" ssh \ + -o StrictHostKeyChecking=no -o PubkeyAuthentication=no \ + -o ConnectTimeout=15 \ + "{{ dev2_ssh_user }}@{{ lldp_dev2_ip }}" \ + "ip -o -4 addr show dev eth0.4000 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | grep -m1 '^10\\.' || true" + exit 0 + fi + + if [ "{{ dev2_passfile_used_lldp6 | default('NONE') }}" != "NONE" ] && [ -n "{{ lldp_dev2_ip6 | default('') }}" ]; then + IP6="{{ lldp_dev2_ip6 }}" + F="{{ dev2_passfile_used_lldp6 }}" + sshpass -p '{{ dev1_pass }}' ssh {{ ssh_opts_common }} \ + "{{ dev1_user }}@{{ ansible_host|default(inventory_hostname) }}" \ + "sshpass -f '/tmp/${F}' ssh \ + -o StrictHostKeyChecking=no -o PubkeyAuthentication=no \ + -o ConnectTimeout={{ ssh_timeout }} \ + '{{ dev2_ssh_user }}@\[${IP6}%{{ dev1_iface }}\]' \ + \"ip -o -4 addr show dev eth0.4000 2>/dev/null | awk '{print \\\\\$4}' | cut -d/ -f1 | grep -m1 '^10\\\\.' || true\"" + exit 0 + fi + + exit 0 + args: + executable: /bin/bash + register: dev2_eth04000_ip + changed_when: false + failed_when: false + ignore_errors: true + + - name: Indoor | Select indoor_ip (ppp0 > eth0.4000 > fallback) + delegate_to: localhost + set_fact: + indoor_ip_value: >- + {%- if (dev2_ppp0_ip.stdout | default('') | trim) is match('^10\.') -%} + {{ dev2_ppp0_ip.stdout | trim }} + {%- elif (dev2_eth04000_ip.stdout | default('') | trim) is match('^10\.') -%} + {{ dev2_eth04000_ip.stdout | trim }} + {%- else -%} + {{ indoor_conn_ip_fallback | default('na') | trim }} + {%- endif -%} + changed_when: false + + - name: Dev2 | indoor_ip debug + delegate_to: localhost + debug: + msg: + - "ppp0_ip={{ dev2_ppp0_ip.stdout | default('') | trim }}" + - "eth0.4000_ip={{ dev2_eth04000_ip.stdout | default('') | trim }}" + - "fallback_ip={{ indoor_conn_ip_fallback | default('') | trim }}" + - "selected indoor_ip={{ indoor_ip_value | default('') | trim }}" + + - name: Publish Dev2 indoor_ip custom field + 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_ip', + 'task_result': (indoor_ip_value | default('na') | trim) + } | to_json }}" + payload_encoding: "string" + changed_when: false + # ----------------------- Final journal: scan status ----------------------- - name: Journal final scan status (success / partial / fail) delegate_to: localhost