/
/
/
1---
2# ============================================================================
3# Safe Network Bonding Configuration for NAS Server
4# ============================================================================
5# Configures 4x 2.5G interfaces in 802.3ad LACP bond with bridge
6# Uses safe asynchronous reconfiguration to prevent SSH lockout
7#
8# Network topology: enp1s0,enp2s0,enp3s0,enp4s0 â bond0 â br0 (192.168.34.200)
9# ============================================================================
10
11- name: Check current network configuration
12 debug:
13 msg: |
14 Current network interfaces: {{ ansible_interfaces | join(', ') }}
15 Current IP: {{ ansible_default_ipv4.address }}
16 Target IP: {{ nas_network_ip | default('192.168.34.200') }}
17
18- name: Install bonding and bridge utilities
19 package:
20 name:
21 - ifenslave
22 - bridge-utils
23 - vlan
24 state: present
25 become: true
26
27- name: Check if target network configuration already exists
28 stat:
29 path: /etc/netplan/50-br.yaml
30 register: netplan_config_exists
31
32- name: Check if we're already on target IP
33 set_fact:
34 network_already_configured: "{{ ansible_default_ipv4.address == nas_network_ip | default('192.168.34.200') }}"
35
36- name: Display current netplan configuration if exists
37 command: cat /etc/netplan/50-br.yaml
38 register: current_netplan
39 when: netplan_config_exists.stat.exists
40 changed_when: false
41 failed_when: false
42
43- name: Skip network reconfiguration if already correct
44 debug:
45 msg: |
46 Network is already configured correctly.
47 Current IP: {{ ansible_default_ipv4.address }}
48 Target IP: {{ nas_network_ip | default('192.168.34.200') }}
49 Skipping network reconfiguration.
50 when: network_already_configured | bool
51
52- name: Create netplan configuration for bonded bridge network
53 copy:
54 content: |
55 network:
56 version: 2
57 renderer: networkd
58
59 ethernets:
60 enp1s0: { dhcp4: no }
61 enp2s0: { dhcp4: no }
62 enp3s0: { dhcp4: no }
63 enp4s0: { dhcp4: no }
64
65 bonds:
66 bond0:
67 interfaces: [enp1s0, enp2s0, enp3s0, enp4s0]
68 parameters:
69 mode: 802.3ad
70 lacp-rate: fast
71 mii-monitor-interval: 100
72 dhcp4: no # no IP here
73
74 bridges:
75 br0:
76 interfaces: [bond0]
77 dhcp4: no # static only
78 addresses: [{{ nas_network_ip | default('192.168.34.200') }}/24]
79 routes:
80 - to: default
81 via: 192.168.34.1
82 nameservers:
83 addresses: [192.168.34.1]
84 dest: /etc/netplan/50-br.yaml
85 owner: root
86 group: root
87 mode: '0644'
88 backup: true
89 become: true
90 register: netplan_configuration
91 when: not (network_already_configured | bool)
92
93- name: Remove any conflicting netplan configurations
94 find:
95 paths: /etc/netplan/
96 patterns: "*.yaml,*.yml"
97 excludes: "50-br.yaml"
98 register: netplan_files
99 when: netplan_configuration.changed | default(false)
100
101- name: Backup and remove conflicting network configs
102 copy:
103 src: "{{ item.path }}"
104 dest: "{{ item.path }}.backup-{{ ansible_date_time.epoch }}"
105 remote_src: yes
106 loop: "{{ netplan_files.files }}"
107 when:
108 - netplan_configuration.changed | default(false)
109 - netplan_files.files | length > 0
110 become: true
111
112- name: Remove original conflicting configs
113 file:
114 path: "{{ item.path }}"
115 state: absent
116 loop: "{{ netplan_files.files }}"
117 when:
118 - netplan_configuration.changed | default(false)
119 - netplan_files.files | length > 0
120 become: true
121
122- name: Create network reconfiguration script for safe SSH transition
123 copy:
124 content: |
125 #!/bin/bash
126 # Safe network reconfiguration script
127 # This script applies netplan changes safely with rollback capability
128
129 LOG_FILE="/var/log/network-reconfig.log"
130
131 echo "$(date): Starting network reconfiguration" >> "$LOG_FILE"
132 echo "Current IP: $(ip route get 8.8.8.8 | grep -oP 'src \K\S+' 2>/dev/null || echo 'unknown')" >> "$LOG_FILE"
133
134 # Apply netplan configuration
135 echo "$(date): Applying netplan configuration..." >> "$LOG_FILE"
136 netplan apply >> "$LOG_FILE" 2>&1
137
138 # Wait for network to settle
139 echo "$(date): Waiting for network to settle..." >> "$LOG_FILE"
140 sleep 15
141
142 # Test connectivity
143 echo "$(date): Testing connectivity..." >> "$LOG_FILE"
144 if ping -c 3 192.168.34.1 > /dev/null 2>&1; then
145 echo "$(date): Network reconfiguration successful" >> "$LOG_FILE"
146 echo "New IP: $(ip route get 8.8.8.8 | grep -oP 'src \K\S+' 2>/dev/null || echo 'unknown')" >> "$LOG_FILE"
147
148 # Show bond status
149 echo "$(date): Bond status:" >> "$LOG_FILE"
150 cat /proc/net/bonding/bond0 >> "$LOG_FILE" 2>&1 || echo "Bond not yet active" >> "$LOG_FILE"
151
152 exit 0
153 else
154 echo "$(date): Network reconfiguration failed, connectivity test failed" >> "$LOG_FILE"
155 echo "$(date): Network interfaces after failure:" >> "$LOG_FILE"
156 ip addr show >> "$LOG_FILE" 2>&1
157 exit 1
158 fi
159 dest: /usr/local/bin/safe-network-reconfig.sh
160 mode: '0755'
161 owner: root
162 group: root
163 become: true
164 when: netplan_configuration.changed | default(false)
165
166- name: Apply network configuration safely (async with timeout)
167 shell: |
168 # Run the network reconfiguration in background
169 nohup /usr/local/bin/safe-network-reconfig.sh >> /var/log/network-reconfig.log 2>&1 &
170 # Give it a moment to start
171 sleep 3
172 echo "Network reconfiguration started in background"
173 become: true
174 when: netplan_configuration.changed | default(false)
175 async: 1
176 poll: 0
177
178- name: Wait for network reconfiguration to complete
179 wait_for:
180 host: "{{ nas_network_ip | default('192.168.34.200') }}"
181 port: 22
182 delay: 20
183 timeout: 180
184 msg: "Failed to reconnect to {{ nas_network_ip | default('192.168.34.200') }} after network reconfiguration"
185 delegate_to: localhost
186 when: netplan_configuration.changed | default(false)
187
188- name: Update connection for remaining tasks
189 set_fact:
190 ansible_host: "{{ nas_network_ip | default('192.168.34.200') }}"
191 when: netplan_configuration.changed | default(false)
192
193- name: Verify new network configuration
194 debug:
195 msg: |
196 â
Network reconfiguration completed successfully!
197 New IP: {{ nas_network_ip | default('192.168.34.200') }}
198 Bonded interfaces should be active on bond0 â br0
199 when: netplan_configuration.changed | default(false)
200
201- name: Display final network status
202 shell: |
203 echo "=== Network Interfaces ==="
204 ip addr show | grep -E "(bond0|br0|enp[1-4]s0)"
205 echo ""
206 echo "=== Bond Status ==="
207 if [ -f /proc/net/bonding/bond0 ]; then
208 echo "Bond0 is active:"
209 cat /proc/net/bonding/bond0 | head -20
210 else
211 echo "Bond0 not yet active - may need a few moments to initialize"
212 fi
213 echo ""
214 echo "=== Route Status ==="
215 ip route show | head -5
216 register: network_status
217 changed_when: false
218 failed_when: false
219
220- name: Show final network configuration
221 debug:
222 msg: "{{ network_status.stdout_lines }}"
223 when: network_status.stdout_lines is defined