docs 📝: Updated README.md for clarity and improved readability
Some checks failed
ansible-lint / Ansible Lint (push) Failing after 10s

Fixed minor grammatical errors and reorganized content in the README.md file.
This commit is contained in:
2025-12-26 11:00:41 +01:00
parent 06a82a8221
commit b94be8a6e4
3 changed files with 139 additions and 95 deletions

View File

@@ -5,10 +5,10 @@ A robust, idempotent Ansible role for enabling persistent Wake-on-LAN (WOL) on P
## Features ## Features
**Fully Idempotent**: Checks current WOL status and only applies changes when needed **Fully Idempotent**: Checks current WOL status and only applies changes when needed
**Multiple Bridge Support**: Configure WOL on multiple bridges simultaneously **Bridge Support**: Automatically detects physical interfaces backing configured bridges
**Bond0 Detection**: Automatically detects and configures bonded interfaces **Bond0 Detection**: Automatically detects and configures bonded interfaces
**Ansible Facts-Based**: Uses Ansible facts to detect and validate WOL-capable interfaces **Ansible Facts-Based**: Uses Ansible facts to detect and validate WOL-capable interfaces
**Safe & Persistent**: Uses udev rules for persistence across reboots **Persistent**: Uses udev rules for persistence across reboots
**Comprehensive Validation**: Verifies WOL capability before configuration **Comprehensive Validation**: Verifies WOL capability before configuration
**Detailed Reporting**: Shows configuration status and MAC addresses for WOL senders **Detailed Reporting**: Shows configuration status and MAC addresses for WOL senders
@@ -25,12 +25,12 @@ A robust, idempotent Ansible role for enabling persistent Wake-on-LAN (WOL) on P
1. **Package Installation**: Ensures `ethtool` is installed for WOL management 1. **Package Installation**: Ensures `ethtool` is installed for WOL management
2. **Interface Discovery**: Uses Ansible facts to identify all physical Ethernet interfaces 2. **Interface Discovery**: Uses Ansible facts to identify all physical Ethernet interfaces
3. **WOL Validation**: Tests each interface for Wake-on-LAN capability using ethtool 3. **Bridge Mapping**: Detects physical interfaces backing configured bridges
4. **Bridge Mapping**: Maps configured bridges to their backing WOL-capable physical NICs 4. **Bond0 Detection**: Identifies bonded interfaces and their slaves
5. **Bond0 Detection**: Detects if interfaces are bonded and extracts slave information 5. **WOL Validation**: Tests each interface for Wake-on-LAN capability using ethtool
6. **Idempotency Check**: Reads current WOL status to avoid redundant changes 6. **Idempotency Check**: Reads current WOL status to avoid redundant changes
7. **Enable WOL**: Applies WOL settings only to interfaces that need it 7. **Enable WOL**: Applies WOL settings only to interfaces that need it
8. **Persist Settings**: Creates/updates udev rules for persistence across reboots 8. **Persist Settings**: Creates udev rules for persistence across reboots
9. **Reload Udev**: Reloads udev rules and triggers network interface refresh 9. **Reload Udev**: Reloads udev rules and triggers network interface refresh
10. **Verification & Reporting**: Displays WOL configuration status and MAC addresses 10. **Verification & Reporting**: Displays WOL configuration status and MAC addresses
@@ -155,10 +155,7 @@ This role is fully idempotent. Running it multiple times has the same effect as
## Implementation Details ## Implementation Details
### Persistence Method ### Persistence Method
WOL settings are persisted using udev rules at `/etc/udev/rules.d/90-wol.rules`. This is the most reliable method for Debian/Proxmox systems and survives: WOL settings are persisted using udev rules at `/etc/udev/rules.d/90-wol.rules`. This ensures WOL is re-enabled whenever network interfaces are added or the system reboots.
- System reboots
- Network service restarts
- Interface state changes
Example generated udev rule: Example generated udev rule:
``` ```
@@ -167,10 +164,14 @@ ACTION=="add", SUBSYSTEM=="net", KERNEL=="eno1", RUN+="/sbin/ethtool -s eno1 wol
### Detection Logic ### Detection Logic
1. **Interface Discovery**: Uses Ansible facts to enumerate all network interfaces 1. **Interface Discovery**: Uses Ansible facts to enumerate all network interfaces
2. **Physical Interface Filtering**: Filters for Ethernet interfaces, excluding virtual interfaces (veth, tap, fw*, docker, br*) 2. **Bridge Mapping**: Identifies physical interfaces backing configured bridges using `bridge link show`
3. **WOL Capability Testing**: Tests each physical interface with ethtool to verify WOL support 3. **Bond0 Detection**: Detects bonded interfaces and extracts slave information from `/proc/net/bonding/bond0`
4. **Bridge Mapping**: Maps configured bridges to their backing WOL-capable physical NICs 4. **WOL Capability Testing**: Tests each physical interface with ethtool to verify WOL support
5. **Bond0 Detection**: Extracts slave interfaces from `/proc/net/bonding/bond0` when present 5. **Idempotency Check**: Reads current WOL status to avoid redundant changes
6. **Enable WOL**: Applies WOL settings only to interfaces that need it
7. **Persist Settings**: Creates/updates udev rules for persistence
8. **Reload Udev**: Reloads udev rules and triggers network interface refresh
9. **Verification & Reporting**: Displays WOL configuration status and MAC addresses
## Troubleshooting ## Troubleshooting

View File

@@ -26,7 +26,7 @@
# ansible.builtin.set_fact: # ansible.builtin.set_fact:
# en_interfaces: "{{ ansible_facts.interfaces | select('match', '^eth|^ens|^enp') | unique | list }}" # en_interfaces: "{{ ansible_facts.interfaces | select('match', '^eth|^ens|^enp') | unique | list }}"
- name: Get interfaces starting with "en or "eth" - name: Get interfaces starting with "en" or "eth"
ansible.builtin.set_fact: ansible.builtin.set_fact:
en_interfaces: >- en_interfaces: >-
{{ {{
@@ -35,112 +35,152 @@
| list | list
}} }}
- name: Display debug selected interfaces # ============================================================
# Detect physical interfaces backing configured bridges
# ============================================================
- name: Get physical interfaces for configured bridges
ansible.builtin.command: bridge link show {{ item }}
register: bridge_links
loop: "{{ wol_bridges | list }}"
changed_when: false
failed_when: false
- name: Extract physical interfaces from bridge info
ansible.builtin.set_fact:
bridge_physical: >-
{{
bridge_links.results
| selectattr('rc', 'equalto', 0)
| map(attribute='stdout_lines')
| flatten
| map('regex_replace', '^\\d+: ([^ ]+).*', '\\1')
| select
| unique
| list
}}
# ============================================================
# Check for bond0 and get slaves
# ============================================================
- name: Check if bond0 exists
ansible.builtin.stat:
path: /proc/net/bonding/bond0
register: bond0_stat
- name: Get bond0 slaves
ansible.builtin.command: cat /proc/net/bonding/bond0 | grep "Slave Interface" | awk '{print $3}'
register: bond0_slaves
changed_when: false
when: bond0_stat.stat.exists
# ============================================================
# Set final list of interfaces to configure
# ============================================================
- name: Set final interfaces
ansible.builtin.set_fact:
wol_final_interfaces: >-
{{
(bridge_physical if bridge_physical else en_interfaces)
+ (bond0_slaves.stdout_lines if bond0_stat.stat.exists else [])
| unique
| list
}}
- name: Display selected interfaces
ansible.builtin.debug: ansible.builtin.debug:
msg: > msg: "Interfaces to configure for WOL: {{ wol_final_interfaces }}"
{{ en_interfaces }}
- name: Check supported Wake-on-LAN modes - name: Check supported Wake-on-LAN modes
ansible.builtin.shell: "ethtool {{ item }} | grep 'Supports Wake-on' | tail -1 | awk '{print $3}'" ansible.builtin.shell: "ethtool {{ item }} | grep 'Supports Wake-on' | tail -1 | awk '{print $3}'"
loop: "{{ en_interfaces }}" loop: "{{ wol_final_interfaces }}"
register: wol_supported register: wol_supported
changed_when: false changed_when: false
when: en_interfaces | length > 0 when: wol_final_interfaces | length > 0
- name: WOL | Check if enabled - name: Check if WOL is enabled
shell: > ansible.builtin.shell: "ethtool {{ item }} | grep 'Wake-on' | tail -1 | awk '{print substr($0,length,1)}'"
ethtool {{ item }} | grep 'Wake-on' | tail -1 | awk '{print substr($0,length,1)}'
register: wol_enabled register: wol_enabled
changed_when: false changed_when: false
failed_when: false failed_when: false
loop: "{{ en_interfaces }}" loop: "{{ wol_final_interfaces }}"
when: en_interfaces | length > 0 when: wol_final_interfaces | length > 0
- name: "Set Wake-on-LAN to {{ wol_mode }}" # ============================================================
# Enable or disable WOL as needed
# ============================================================
- name: Set Wake-on-LAN mode
ansible.builtin.command: "ethtool -s {{ item.0 }} wol {{ wol_mode }}" ansible.builtin.command: "ethtool -s {{ item.0 }} wol {{ wol_mode }}"
loop: "{{ en_interfaces | zip(wol_enabled.results, wol_supported.results) | list }}" loop: "{{ wol_final_interfaces | zip(wol_enabled.results, wol_supported.results) | list }}"
loop_control: loop_control:
label: "{{ item.0 }}" label: "{{ item.0 }}"
when: when:
- item.1.stdout is defined
- item.2.stdout is defined
- wol_mode not in item.1.stdout - wol_mode not in item.1.stdout
- wol_mode in item.2.stdout - wol_mode in item.2.stdout
- name: "Disable Wake-on-LAN" # ============================================================
ansible.builtin.command: "ethtool -s {{ item.0 }} wol {{ wol_mode }}" # Create udev rules for persistence
loop: "{{ en_interfaces | zip(wol_enabled.results, wol_supported.results) | list }}" # ============================================================
loop_control: - name: Create udev rule for WOL persistence
label: "{{ item.0 }}"
when:
- wol_mode == 'd'
- wol_mode not in item.1.stdout
# -------------------------
# 4. Create systemd service for persistence
# -------------------------
- name: Create systemd service from template
ansible.builtin.template: ansible.builtin.template:
src: wol-interfaces.service.j2 src: 90-wol.rules.j2
dest: /etc/systemd/system/wol-interfaces.service dest: /etc/udev/rules.d/90-wol.rules
owner: root owner: root
group: root group: root
mode: '0644' mode: '0644'
notify: notify:
- Reload systemd - Reload_udev_rules
- Trigger_udev_net
- name: Enable and start WoL service
ansible.builtin.systemd:
name: wol-interfaces.service
enabled: yes
state: started
# # ============================================================ # ============================================================
# # Verification & Reporting # Verification & Reporting
# # ============================================================ # ============================================================
# - name: Verify Wake-on-LAN status - name: Verify Wake-on-LAN status
# ansible.builtin.command: "ethtool {{ item }}" ansible.builtin.command: "ethtool {{ item }}"
# register: wol_status register: wol_status
# changed_when: false changed_when: false
# loop: "{{ wol_final_interfaces }}" loop: "{{ wol_final_interfaces }}"
# loop_control: loop_control:
# label: "{{ item }}" label: "{{ item }}"
# when: wol_verify when: wol_verify and wol_final_interfaces | length > 0
# - name: Display WOL status per interface - name: Display WOL status per interface
# ansible.builtin.debug: ansible.builtin.debug:
# msg: > msg: >
# Interface {{ item.item }} WOL Status: Interface {{ item.item }} WOL Status:
# {{ item.stdout_lines | select('search', 'Wake-on:') | first | default('Status Unknown') }} {{ item.stdout_lines | select('search', 'Wake-on:') | first | default('Status Unknown') }}
# loop: "{{ wol_status.results | default([]) }}" loop: "{{ wol_status.results | default([]) }}"
# loop_control: loop_control:
# label: "{{ item.item }}" label: "{{ item.item }}"
# when: wol_verify when: wol_verify
# - name: Get MAC addresses for all interfaces - name: Get MAC addresses for all interfaces
# ansible.builtin.set_fact: ansible.builtin.set_fact:
# wol_mac_addresses: >- wol_mac_addresses: >-
# {{ {{
# wol_final_interfaces wol_final_interfaces
# | map('extract', hostvars[inventory_hostname]['ansible_' ~ item] | default({}), 'macaddress') | map('extract', ansible_facts, attribute='macaddress')
# | list | list
# }} }}
# - name: Report WOL configuration - name: Report WOL configuration
# ansible.builtin.debug: ansible.builtin.debug:
# msg: | msg: |
# Wake-on-LAN Configuration Summary: Wake-on-LAN Configuration Summary:
# =================================== ===================================
# Bridges Configured: {{ wol_bridges_list | join(', ') }} Bridges Configured: {{ wol_bridges | join(', ') }}
# Physical Interfaces: {{ wol_final_interfaces | join(', ') }} Physical Interfaces: {{ wol_final_interfaces | join(', ') }}
# WOL Mode: {{ wol_mode }} WOL Mode: {{ wol_mode }}
# {% if wol_has_bond0 | default(false) %} {% if bond0_stat.stat.exists %}
# Bond0 Detected: Yes Bond0 Detected: Yes
# Bond0 Slaves: {{ wol_bond0_slaves | join(', ') }} Bond0 Slaves: {{ bond0_slaves.stdout_lines | join(', ') }}
# {% endif %} {% endif %}
# {% if wol_report_mac and wol_mac_addresses | length > 0 %} {% if wol_report_mac and wol_mac_addresses | length > 0 %}
# MAC Addresses: MAC Addresses:
# {% for iface, mac in (wol_final_interfaces | zip(wol_mac_addresses) | list) %} {% for iface, mac in (wol_final_interfaces | zip(wol_mac_addresses) | list) %}
# - {{ iface }}: {{ mac | default('Unable to detect') }} - {{ iface }}: {{ mac | default('Unable to detect') }}
# {% endfor %} {% endfor %}
# {% endif %} {% endif %}

View File

@@ -0,0 +1,3 @@
{% for interface in wol_final_interfaces %}
ACTION=="add", SUBSYSTEM=="net", KERNEL=="{{ interface }}", RUN+="/sbin/ethtool -s {{ interface }} wol {{ wol_mode }}"
{% endfor %}