From 56a1abb898090b127291702b07d2f90678540590 Mon Sep 17 00:00:00 2001 From: pavel Date: Tue, 20 Jan 2026 09:37:24 +0200 Subject: [PATCH] 0937 --- files/ansible-playbooks/ptsd-migrate.yml | 109 ++++++++++------------- 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/files/ansible-playbooks/ptsd-migrate.yml b/files/ansible-playbooks/ptsd-migrate.yml index 9fdd295..3560a25 100644 --- a/files/ansible-playbooks/ptsd-migrate.yml +++ b/files/ansible-playbooks/ptsd-migrate.yml @@ -1,10 +1,10 @@ # ptsd-migration.yml — PPPoE to super DHCP (phase 0: connectivity prove-out) -# Goal: reliably connect to DEV2 using: -# 1) direct LLDP IPv4 (10.x) if available and auth works -# 2) tunnel via DEV1 (default / primary) -# 3) LLDP IPv4 (10.x) fallback if tunnel auth fails -# 4) LLDP IPv6 fallback via DEV1 (nested ssh to [ip6%iface]) if all else fails -# +# Focus: reliable connectivity to DEV2 +# Paths: +# A) direct LLDP IPv4 (10.x) if available and auth works +# B) tunnel via DEV1 (default) +# C) LLDP IPv4 (10.x) fallback if tunnel auth fails +# D) LLDP IPv6 fallback via DEV1 (nested ssh to [ip6%iface]) if all else fails # After connection: run "uptime" on DEV2 and print it. - name: PPPoE to super DHCP | Phase 0 | Prove reliable DEV2 connectivity + uptime @@ -12,30 +12,26 @@ gather_facts: no vars: - # Busybox-safe PATH prefix for all DEV1 raw calls pathprefix: "PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH; " # DEV1 credentials dev1_user: "root" dev1_pass: "wavewave" - # DEV2 "default" behind DEV1 + # DEV2 default behind DEV1 dev2_host: "192.168.1.1" dev2_port: 22 # Temp IP we add to DEV1 so it can reach DEV2 dev2_side_ip: "192.168.1.11/24" dev2_side_ip_addr: "{{ dev2_side_ip.split('/')[0] }}" - dev1_iface: "br-wan" # used for temp IP, ARP, and IPv6 scope-id (link-local) - arping_iface: "eth0" # optional refresh on DEV1 + dev1_iface: "br-wan" # also used as IPv6 scope-id + arping_iface: "eth0" # DEV2 credentials dev2_ssh_user: "root" - dev2_passfiles: - - "basicpass" - - "basicpass2" + dev2_passfiles: [ "basicpass", "basicpass2" ] - # SSH options used from controller (and outer hop to DEV1) ssh_opts_common: >- -o PreferredAuthentications=password -o PubkeyAuthentication=no @@ -44,19 +40,15 @@ -o NumberOfPasswordPrompts=1 -o ConnectTimeout=30 - # Debug toggle debugging: true - # Final connection outputs (set dynamically) + # Connection state dev2_conn_method: "" - dev2_passfile_used: "NONE" # for tunnel or direct-lldp - dev2_passfile_used_lldp: "NONE" # for direct LLDP IPv4 fallback - dev2_passfile_used_lldp6: "NONE" # for IPv6 via DEV1 fallback - dev2_ssh_host: "" - dev2_ssh_port: "" + dev2_passfile_used: "NONE" # tunnel or direct_lldp primary + dev2_passfile_used_lldp: "NONE" # LLDP IPv4 fallback + dev2_passfile_used_lldp6: "NONE" # LLDP IPv6 via DEV1 fallback pre_tasks: - # ------------------------------- DEV1 hostname sanity ------------------------------- - name: Read DEV1 hostname (busybox-safe) ansible.builtin.raw: > {{ pathprefix }} @@ -130,7 +122,6 @@ - "LLDP IPv4 class={{ lldp_ip_class | default('none') }}" - "LLDP IPv6 candidate={{ lldp_dev2_ip6 | default('') }}" - # -------------------- If LLDP shows 192.168.x, override dev2_host for tunnel target -------------------- - name: Override dev2_host from LLDP when candidate is 192.168.x.x when: (lldp_ip_class | trim) == "192_168" and (lldp_dev2_ip | trim | length > 0) delegate_to: localhost @@ -138,7 +129,7 @@ dev2_host: "{{ lldp_dev2_ip | trim }}" changed_when: false - # ============================ PATH 1: DIRECT LLDP IPv4 (10.x) IF IT WORKS ============================ + # ============================ PATH A: DIRECT LLDP IPv4 (10.x) PRIMARY ============================ - name: Try DEV2 login via direct LLDP IPv4 (10.x) with basicpass when: (lldp_ip_class | trim) == "10" delegate_to: localhost @@ -151,8 +142,7 @@ -o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 \ -o ConnectTimeout=30 \ "{{ dev2_ssh_user }}@${HOST}" echo OK >/dev/null 2>&1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: direct_lldp_try_basicpass changed_when: false ignore_errors: true @@ -179,8 +169,7 @@ -o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 \ -o ConnectTimeout=30 \ "{{ dev2_ssh_user }}@${HOST}" echo OK >/dev/null 2>&1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: direct_lldp_try_basicpass2 changed_when: false ignore_errors: true @@ -195,7 +184,7 @@ dev2_ssh_port: 22 changed_when: false - # ============================ PATH 2: TUNNEL VIA DEV1 (PRIMARY DEFAULT) ============================ + # ============================ PATH B: TUNNEL VIA DEV1 (DEFAULT) ============================ - name: Set connection method to tunnel if not already direct LLDP when: dev2_conn_method != "direct_lldp" delegate_to: localhost @@ -279,8 +268,7 @@ return 1 } pick - args: - executable: /bin/bash + args: { executable: /bin/bash } register: pick_port changed_when: false @@ -288,13 +276,21 @@ when: dev2_conn_method == "tunnel" and (pick_port.stdout | trim | length) == 0 ansible.builtin.meta: end_host - - name: Record chosen local port and create control dir for SSH ControlMaster + # ---- FIX: create ctrl dir first, then derive sock ---- + - name: Create control dir for SSH ControlMaster + when: dev2_conn_method == "tunnel" + delegate_to: localhost + ansible.builtin.set_fact: + _ctrl_dir: "{{ lookup('ansible.builtin.pipe', 'mktemp -d') }}" + changed_when: false + + - name: Record chosen local port and build ControlMaster socket path when: dev2_conn_method == "tunnel" delegate_to: localhost ansible.builtin.set_fact: _local_port: "{{ pick_port.stdout | trim }}" - _ctrl_dir: "{{ lookup('ansible.builtin.pipe', 'mktemp -d') }}" _ctrl_sock: "{{ _ctrl_dir }}/ssh_tunnel_ctl" + changed_when: false - name: Start SSH ControlMaster and forward 127.0.0.1:local_port → DEV2:22 via DEV1 when: dev2_conn_method == "tunnel" @@ -307,8 +303,7 @@ -M -S "{{ _ctrl_sock }}" \ -L "127.0.0.1:{{ _local_port }}:{{ dev2_host }}:{{ dev2_port }}" \ "${USER}@${HOST}" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: start_tunnel changed_when: true @@ -318,8 +313,7 @@ ansible.builtin.shell: | set -e nc -z -w5 127.0.0.1 "{{ _local_port }}" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: nc_probe changed_when: false ignore_errors: true @@ -340,8 +334,7 @@ -o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 \ -o ConnectTimeout=30 \ -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" echo OK >/dev/null 2>&1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_try_basicpass changed_when: false ignore_errors: true @@ -367,8 +360,7 @@ -o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 \ -o ConnectTimeout=30 \ -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" echo OK >/dev/null 2>&1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_try_basicpass2 changed_when: false ignore_errors: true @@ -382,7 +374,6 @@ dev2_ssh_port: "{{ _local_port }}" changed_when: false - # -------------------- Safety guard: validate tunnel reached correct device by MAC (if discovered) -------------------- - name: Read remote eth0 MAC via tunnel (guard) when: dev2_conn_method == "tunnel" and dev2_passfile_used != "NONE" and (dev2_mac | default('') | trim | length > 0) delegate_to: localhost @@ -396,8 +387,7 @@ -o ConnectTimeout=30 \ -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \ "cat /sys/class/net/eth0/address 2>/dev/null || echo" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_eth0_mac_read changed_when: false failed_when: false @@ -411,7 +401,7 @@ expected_dev2_mac={{ dev2_mac | trim }}, remote_eth0_mac={{ dev2_eth0_mac_read.stdout | default('') | trim }}. - # ============================ FALLBACK 3: DIRECT LLDP IPv4 (10.x) IF TUNNEL AUTH FAILED ============================ + # ============================ FALLBACK C: DIRECT LLDP IPv4 (10.x) ============================ - name: Try DEV2 login via LLDP IPv4 10.x (fallback if tunnel auth failed) when: - dev2_conn_method == "tunnel" @@ -432,8 +422,7 @@ fi done exit 1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_auth_lldp changed_when: false ignore_errors: true @@ -448,7 +437,7 @@ dev2_passfile_used_lldp: "{{ (dev2_auth_lldp.rc == 0) | ternary((dev2_auth_lldp.stdout | trim), 'NONE') }}" changed_when: false - # ============================ FALLBACK 4: IPv6 LLDP VIA DEV1 (LAST RESORT) ============================ + # ============================ FALLBACK D: IPv6 LLDP VIA DEV1 (LAST RESORT) ============================ - name: Copy DEV2 passfiles to DEV1 for IPv6 nested SSH (last resort) when: - dev2_conn_method == "tunnel" @@ -486,8 +475,7 @@ fi done exit 1 - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_auth_lldp6 changed_when: false ignore_errors: true @@ -504,7 +492,7 @@ changed_when: false # ============================ FINAL CONNECTION RESOLUTION ============================ - - name: Decide final DEV2 connection mode (tunnel > lldp4 > lldp6) + - name: Decide final DEV2 connection mode (direct_lldp > tunnel > lldp4 > lldp6) delegate_to: localhost ansible.builtin.set_fact: dev2_conn_final: >- @@ -541,7 +529,7 @@ - "lldp ipv4={{ lldp_dev2_ip | default('') }}" - "lldp ipv6={{ lldp_dev2_ip6 | default('') }}" - # ============================ ACTION (PHASE 0): DEV2 UPTIME ============================ + # ============================ PHASE 0 ACTION: DEV2 UPTIME ============================ - name: DEV2 | uptime (tunnel) when: dev2_conn_final == "tunnel" delegate_to: localhost @@ -550,11 +538,9 @@ PORT="{{ _local_port }}" sshpass -f "{{ dev2_passfile_used }}" ssh {{ ssh_opts_common }} \ -o AddressFamily=inet \ - -o ConnectTimeout=30 \ -p "$PORT" "{{ dev2_ssh_user }}@127.0.0.1" \ "uptime 2>/dev/null || true" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_uptime changed_when: false @@ -563,14 +549,12 @@ delegate_to: localhost ansible.builtin.shell: | set -e - HOST="{{ dev2_ssh_host }}" + HOST="{{ lldp_dev2_ip }}" sshpass -f "{{ dev2_passfile_used }}" ssh {{ ssh_opts_common }} \ -o AddressFamily=inet \ - -o ConnectTimeout=30 \ "{{ dev2_ssh_user }}@${HOST}" \ "uptime 2>/dev/null || true" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_uptime changed_when: false @@ -582,11 +566,9 @@ HOST="{{ lldp_dev2_ip }}" sshpass -f "{{ dev2_passfile_used_lldp }}" ssh {{ ssh_opts_common }} \ -o AddressFamily=inet \ - -o ConnectTimeout=30 \ "{{ dev2_ssh_user }}@${HOST}" \ "uptime 2>/dev/null || true" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_uptime changed_when: false @@ -605,8 +587,7 @@ -o ConnectTimeout=30 \ '{{ dev2_ssh_user }}@\[${IP6}%{{ dev1_iface }}\]' \ 'uptime 2>/dev/null || true'" - args: - executable: /bin/bash + args: { executable: /bin/bash } register: dev2_uptime changed_when: false