1639
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
ssh_opts_common: "-o PreferredAuthentications=password -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o NumberOfPasswordPrompts=1 -o ConnectTimeout=30"
|
ssh_opts_common: "-o PreferredAuthentications=password -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o NumberOfPasswordPrompts=1 -o ConnectTimeout=30"
|
||||||
|
|
||||||
# Image to stage on DEV2 (we validate first; the actual write happens later)
|
# Image to stage on DEV2 (we validate first; the actual write happens later)
|
||||||
image_filename: "fox200-2.2.1-r6801.bin"
|
image_filename: "2.2.1-r6801.bin"
|
||||||
image_md5: "56b7211709de617e058b98d4204e2562"
|
image_md5: "56b7211709de617e058b98d4204e2562"
|
||||||
# Optional SHA256; leave empty to skip SHA256 checks
|
# Optional SHA256; leave empty to skip SHA256 checks
|
||||||
image_sha256: ""
|
image_sha256: ""
|
||||||
@@ -173,6 +173,57 @@
|
|||||||
- "dev2_conn_method={{ dev2_conn_method }}"
|
- "dev2_conn_method={{ dev2_conn_method }}"
|
||||||
- "lldp_dev2_ip={{ lldp_dev2_ip | default('<none>') }}"
|
- "lldp_dev2_ip={{ lldp_dev2_ip | default('<none>') }}"
|
||||||
|
|
||||||
|
# ------ LLDP IPv6 discovery for tunnel mode (Dev1 → Dev2 link-local) ------
|
||||||
|
- name: Discover DEV2 candidate IPv6 via LLDP on DEV1 (best-effort)
|
||||||
|
when: dev2_conn_method == "tunnel"
|
||||||
|
ansible.builtin.raw: >
|
||||||
|
{{ pathprefix }}
|
||||||
|
DIGITS="{{ dev2_lldp_digits }}";
|
||||||
|
cat /var/run/lldp_server.json 2>/dev/null \
|
||||||
|
| grep "${DIGITS}" -A 15 \
|
||||||
|
| grep 'address_ipv6' \
|
||||||
|
| awk -F'"' '{ print $4 }' \
|
||||||
|
| head -n1
|
||||||
|
register: dev2_lldp_ip6_raw
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Capture LLDP-derived DEV2 IPv6 (if any)
|
||||||
|
when: dev2_conn_method == "tunnel"
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
lldp_dev2_ip6: "{{ (dev2_lldp_ip6_raw.stdout | default('')) | trim }}"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Debug LLDP IPv6 candidate for DEV2 (new debug)
|
||||||
|
when: dev2_conn_method == "tunnel" and debugging | bool
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "LLDP candidate IPv6={{ lldp_dev2_ip6 | default('<none>') }}"
|
||||||
|
|
||||||
|
# Build the remote tunnel target: prefer LLDP IPv6 if present, else 192.168.1.1
|
||||||
|
- name: Build tunnel remote target for DEV2 (prefer LLDP IPv6 when available)
|
||||||
|
when: dev2_conn_method == "tunnel"
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
dev2_tunnel_target: >-
|
||||||
|
{{
|
||||||
|
(lldp_dev2_ip6 is defined and (lldp_dev2_ip6 | string | trim | length > 0))
|
||||||
|
| ternary(
|
||||||
|
'[' ~ (lldp_dev2_ip6 | string | trim) ~ '%' ~ (dev1_iface | string | trim) ~ ']:' ~ (dev2_port | string),
|
||||||
|
(dev2_host | string) ~ ':' ~ (dev2_port | string)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Debug tunnel remote target for DEV2 (IPv4/IPv6)
|
||||||
|
when: dev2_conn_method == "tunnel" and debugging | bool
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "dev2_tunnel_target={{ dev2_tunnel_target | default(dev2_host ~ ':' ~ dev2_port) }}"
|
||||||
|
|
||||||
|
|
||||||
# Direct LLDP 10.x login (no tunnel, reusing two-step auth style)
|
# Direct LLDP 10.x login (no tunnel, reusing two-step auth style)
|
||||||
- name: Try DEV2 login via direct LLDP IP with 'basicpass' (10.x)
|
- name: Try DEV2 login via direct LLDP IP with 'basicpass' (10.x)
|
||||||
when: dev2_conn_method == "direct_lldp"
|
when: dev2_conn_method == "direct_lldp"
|
||||||
@@ -408,7 +459,7 @@
|
|||||||
HOST="{{ ansible_host | default(inventory_hostname) }}"
|
HOST="{{ ansible_host | default(inventory_hostname) }}"
|
||||||
sshpass -p '{{ dev1_pass }}' ssh -f -N {{ ssh_opts_common }} \
|
sshpass -p '{{ dev1_pass }}' ssh -f -N {{ ssh_opts_common }} \
|
||||||
-M -S "{{ _ctrl_sock }}" \
|
-M -S "{{ _ctrl_sock }}" \
|
||||||
-L "127.0.0.1:{{ _local_port }}:{{ dev2_host }}:{{ dev2_port }}" \
|
-L "127.0.0.1:{{ _local_port }}:{{ dev2_tunnel_target | default(dev2_host ~ ':' ~ dev2_port) }}" \
|
||||||
"${USER}@${HOST}"
|
"${USER}@${HOST}"
|
||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
@@ -812,6 +863,33 @@
|
|||||||
_blocked: true
|
_blocked: true
|
||||||
_journal: "{{ _journal + [ 'Preparation markers already present on DEV2 (count=' ~ (dev2_prep_count.stdout | trim) ~ '). Skipping staging/write' ] }}"
|
_journal: "{{ _journal + [ 'Preparation markers already present on DEV2 (count=' ~ (dev2_prep_count.stdout | trim) ~ '). Skipping staging/write' ] }}"
|
||||||
|
|
||||||
|
- name: Check bootenv-updated marker on DEV2 (/tmp/bootenv_updated)
|
||||||
|
when: dev2_passfile_used != "NONE"
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -e
|
||||||
|
HOST="{{ dev2_ssh_host }}"
|
||||||
|
PORT="{{ dev2_ssh_port }}"
|
||||||
|
sshpass -f "{{ dev2_passfile_used }}" ssh \
|
||||||
|
-o StrictHostKeyChecking=no -o PubkeyAuthentication=no \
|
||||||
|
-o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 \
|
||||||
|
-o ConnectTimeout=10 \
|
||||||
|
-p "$PORT" "{{ dev2_ssh_user }}@${HOST}" \
|
||||||
|
"[ -f '/tmp/bootenv_updated' ] && echo PRESENT || echo ABSENT"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: dev2_bootenv_marker
|
||||||
|
changed_when: false
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Soft-block if bootenv-updated marker is present on DEV2
|
||||||
|
when: dev2_bootenv_marker is defined
|
||||||
|
and (dev2_bootenv_marker.stdout | default('') | trim) == 'PRESENT'
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_prep_blocked: true
|
||||||
|
_blocked: true
|
||||||
|
_journal: "{{ _journal + [ 'Bootenv updated marker present on DEV2 (/tmp/bootenv_updated). Skipping image staging/write' ] }}"
|
||||||
|
|
||||||
- name: Refresh ARP 1 on DEV1’s LAN (send unsolicited ARP from temporary IP)
|
- name: Refresh ARP 1 on DEV1’s LAN (send unsolicited ARP from temporary IP)
|
||||||
when: dev2_conn_method == "tunnel"
|
when: dev2_conn_method == "tunnel"
|
||||||
ansible.builtin.raw: arping -U -I eth0 192.168.1.11 -c 3
|
ansible.builtin.raw: arping -U -I eth0 192.168.1.11 -c 3
|
||||||
@@ -1165,16 +1243,16 @@
|
|||||||
HOST="{{ dev2_ssh_host }}"
|
HOST="{{ dev2_ssh_host }}"
|
||||||
PORT="{{ dev2_ssh_port }}"
|
PORT="{{ dev2_ssh_port }}"
|
||||||
sshpass -f "{{ dev2_passfile_used }}" scp \
|
sshpass -f "{{ dev2_passfile_used }}" scp \
|
||||||
-O \
|
|
||||||
-P "$PORT" \
|
-P "$PORT" \
|
||||||
|
-O \
|
||||||
-o StrictHostKeyChecking=no -o PubkeyAuthentication=no \
|
-o StrictHostKeyChecking=no -o PubkeyAuthentication=no \
|
||||||
"{{ image_filename }}" "{{ dev2_ssh_user }}@${HOST}:{{ dev2_ssh_user == 'root' | ternary('/', '') }}{{ dev2_image_dir }}/{{ image_filename }}"
|
"{{ image_filename }}" "{{ dev2_ssh_user }}@${HOST}:{{ (dev2_ssh_user == 'root') | ternary('/', '') }}{{ dev2_image_dir }}/{{ image_filename }}"
|
||||||
|
|
||||||
args:
|
args:
|
||||||
executable: /bin/bash
|
executable: /bin/bash
|
||||||
register: scp_push
|
register: scp_push
|
||||||
changed_when: true
|
changed_when: true
|
||||||
|
|
||||||
|
|
||||||
- name: Compute md5 of image on DEV2 after copy (or if already present)
|
- name: Compute md5 of image on DEV2 after copy (or if already present)
|
||||||
when: local_img.stat.exists and dev2_passfile_used != "NONE" and not (_blocked | default(false))
|
when: local_img.stat.exists and dev2_passfile_used != "NONE" and not (_blocked | default(false))
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
|
|||||||
Reference in New Issue
Block a user