refactor ♻️: Refactored Wake-on-LAN task for specific bridge interface
Renamed `wol_interface` to `wol_bridge`, updated comments, and refactored task using `bridge link show` and `ethtool`. Added udev rules for persistence and set `Restart=always` for the service.
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
# defaults/main.yml
|
# defaults/main.yml
|
||||||
# Network interface to enable Wake-on-LAN on
|
# Bridge interface to enable Wake-on-LAN on
|
||||||
wol_interface: "" # user override (physical NIC)
|
wol_bridge: vmbr0
|
||||||
wol_detected_bridge: ""
|
|
||||||
wol_detected_phy: ""
|
|
||||||
|
|
||||||
# WOL mode:
|
# WOL mode:
|
||||||
# g = magic packet (most common)
|
# g = magic packet (most common)
|
||||||
|
|||||||
178
tasks/main.yml
178
tasks/main.yml
@@ -5,156 +5,110 @@
|
|||||||
state: present
|
state: present
|
||||||
update_cache: yes
|
update_cache: yes
|
||||||
|
|
||||||
- name: Gather network facts
|
# ------------------------------------------------------------
|
||||||
ansible.builtin.setup:
|
# Map vmbr0 → backing physical NIC
|
||||||
gather_subset:
|
# ------------------------------------------------------------
|
||||||
- network
|
- name: Get bridge link information
|
||||||
|
ansible.builtin.command: "bridge link show"
|
||||||
|
register: bridge_links
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
- name: Detect default route interface
|
- name: Detect physical NIC backing vmbr0
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
wol_detected_interface: "{{ ansible_default_ipv4.interface }}"
|
wol_detected_phy: >-
|
||||||
when: wol_interface | default('') | length == 0
|
|
||||||
|
|
||||||
- name: Debug facts interface
|
|
||||||
ansible.builtin.debug:
|
|
||||||
msg:
|
|
||||||
- "Detected bridge {{ wol_detected_interface }}"
|
|
||||||
|
|
||||||
# - name: Debug facts
|
|
||||||
# ansible.builtin.debug:
|
|
||||||
# msg:
|
|
||||||
# - "{{ hostvars[inventory_hostname]['ansible_' + wol_detected_interface][interfaces] }}"
|
|
||||||
|
|
||||||
# - name: Detect physical NIC enslaved to bridge
|
|
||||||
# ansible.builtin.set_fact:
|
|
||||||
# wol_detected_phy: "{{ item }}"
|
|
||||||
# loop: "{{ ansible_interfaces }}"
|
|
||||||
# when:
|
|
||||||
# - wol_interface | default('') | length == 0
|
|
||||||
# - item != 'lo'
|
|
||||||
# - item is not match('^v')
|
|
||||||
# - item is match('^e')
|
|
||||||
# - hostvars[inventory_hostname]['ansible_' + item] is defined
|
|
||||||
# - hostvars[inventory_hostname]['ansible_' + item].module is defined
|
|
||||||
# - hostvars[inventory_hostname]['ansible_' + item].pciid is defined
|
|
||||||
# - hostvars[inventory_hostname]['ansible_' + item].type is defined
|
|
||||||
# - hostvars[inventory_hostname]['ansible_' + item].type == 'ether'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# - name: Detect physical NIC behind bridge
|
|
||||||
# ansible.builtin.set_fact:
|
|
||||||
# wol_detected_phy: "{{ ansible_facts[wol_detected_bridge].interfaces[0] }}"
|
|
||||||
# when:
|
|
||||||
# - wol_interface | default('') | length == 0
|
|
||||||
# - ansible_facts[wol_detected_bridge] is defined
|
|
||||||
# - ansible_facts[wol_detected_bridge].interfaces is defined
|
|
||||||
# - ansible_facts[wol_detected_bridge].interfaces | length > 0
|
|
||||||
|
|
||||||
- name: Detect physical NICs in bridge
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
wol_bridge_phys: >-
|
|
||||||
{{
|
{{
|
||||||
ansible_facts[wol_detected_interface].interfaces
|
bridge_links.stdout_lines
|
||||||
| select('match', '^(e|en)')
|
| select('search', wol_bridge)
|
||||||
| list
|
| select('search', 'master ' ~ wol_bridge)
|
||||||
|
| map('regex_search', '^\\d+: ([^:@]+)', '\\1')
|
||||||
|
| select('string')
|
||||||
|
| first
|
||||||
}}
|
}}
|
||||||
|
|
||||||
- name: Debug WoL interface selection
|
- name: Fail if vmbr0 backing NIC could not be detected
|
||||||
ansible.builtin.debug:
|
|
||||||
msg:
|
|
||||||
- "Detected interface: {{ wol_detected_interface }}"
|
|
||||||
- "Detected physical NICs: {{ wol_detected_phys }}"
|
|
||||||
|
|
||||||
- name: Select physical NIC if exactly one found
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
wol_detected_phy: "{{ wol_bridge_phys[0] }}"
|
|
||||||
when: wol_bridge_phys | length == 1
|
|
||||||
|
|
||||||
- name: Select final WoL interface
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
wol_final_interface: >-
|
|
||||||
{{
|
|
||||||
wol_interface
|
|
||||||
if wol_interface | default('') | length > 0
|
|
||||||
else wol_detected_phy
|
|
||||||
}}
|
|
||||||
|
|
||||||
- name: Fail if multiple NICs are attached to bridge
|
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: >
|
msg: >
|
||||||
Multiple physical NICs found in {{ wol_detected_bridge }}:
|
Unable to detect physical NIC backing {{ wol_bridge }}.
|
||||||
{{ wol_bridge_phys }}.
|
|
||||||
Please set wol_interface explicitly.
|
Please set wol_interface explicitly.
|
||||||
when: wol_bridge_phys | length > 1
|
when: wol_detected_phy | default('') | length == 0
|
||||||
|
|
||||||
- name: Fail if no physical NIC was detected
|
# ------------------------------------------------------------
|
||||||
ansible.builtin.fail:
|
# Validate WOL capability
|
||||||
msg: >
|
# ------------------------------------------------------------
|
||||||
Unable to detect a physical NIC for Wake-on-LAN.
|
- name: Check WOL capability on detected NIC
|
||||||
Detected bridge: {{ wol_detected_bridge | default('none') }}.
|
ansible.builtin.command: "ethtool {{ wol_detected_phy }}"
|
||||||
Please set wol_interface explicitly.
|
|
||||||
when: wol_final_interface | default('') | length == 0
|
|
||||||
|
|
||||||
- name: Check WOL support on interface
|
|
||||||
ansible.builtin.command: ethtool {{ wol_final_interface }}
|
|
||||||
register: wol_capabilities
|
register: wol_capabilities
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Fail if NIC does not support Wake-on-LAN
|
- name: Fail if NIC does not support Wake-on-LAN
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: "Interface {{ wol_final_interface }} does not support Wake-on-LAN."
|
msg: "Interface {{ wol_detected_phy }} does not support Wake-on-LAN."
|
||||||
when: "'Wake-on:' not in wol_capabilities.stdout"
|
when: "'Supports Wake-on: g' not in wol_capabilities.stdout"
|
||||||
|
|
||||||
- name: Create systemd service for Wake-on-LAN
|
# ------------------------------------------------------------
|
||||||
ansible.builtin.template:
|
# Enable WOL immediately
|
||||||
src: wol.service.j2
|
# ------------------------------------------------------------
|
||||||
dest: /etc/systemd/system/wol.service
|
- name: Enable Wake-on-LAN immediately
|
||||||
|
ansible.builtin.command: >
|
||||||
|
ethtool -s {{ wol_detected_phy }} wol {{ wol_mode }}
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Persist WOL via udev (correct + recommended)
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
- name: Create udev rule to persist Wake-on-LAN
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/udev/rules.d/90-wol.rules
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
notify:
|
content: |
|
||||||
- Reload systemd and restart WOL
|
ACTION=="add", SUBSYSTEM=="net", KERNEL=="{{ wol_detected_phy }}", RUN+="/sbin/ethtool -s {{ wol_detected_phy }} wol {{ wol_mode }}"
|
||||||
|
|
||||||
- name: Enable WOL immediately (without reboot)
|
- name: Reload udev rules
|
||||||
ansible.builtin.command: ethtool -s {{ wol_final_interface }} wol {{ wol_mode }}
|
ansible.builtin.command: udevadm control --reload
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Trigger udev for network interfaces
|
||||||
|
ansible.builtin.command: udevadm trigger --subsystem-match=net
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Verification & Reporting
|
||||||
|
# ------------------------------------------------------------
|
||||||
- name: Verify Wake-on-LAN status
|
- name: Verify Wake-on-LAN status
|
||||||
ansible.builtin.command: ethtool {{ wol_final_interface }}
|
ansible.builtin.command: "ethtool {{ wol_detected_phy }}"
|
||||||
register: wol_status
|
register: wol_status
|
||||||
changed_when: false
|
changed_when: false
|
||||||
when: wol_verify
|
when: wol_verify
|
||||||
|
|
||||||
- name: Get MAC address of WOL interface
|
- name: Get MAC address
|
||||||
set_fact:
|
ansible.builtin.set_fact:
|
||||||
wol_mac_address: >-
|
wol_mac_address: "{{ ansible_facts.interfaces[wol_detected_phy].macaddress | default('') }}"
|
||||||
{{
|
|
||||||
ansible_facts['ansible_' + wol_final_interface]['macaddress']
|
- name: Fail if MAC address could not be detected
|
||||||
| default('')
|
ansible.builtin.fail:
|
||||||
}}
|
msg: "Unable to determine MAC address for interface {{ wol_detected_phy }}"
|
||||||
|
when:
|
||||||
|
- wol_report_mac
|
||||||
|
- wol_mac_address | length == 0
|
||||||
|
|
||||||
- name: Show WOL status
|
- name: Show WOL status
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ wol_status.stdout_lines }}"
|
msg: "{{ wol_status.stdout_lines }}"
|
||||||
when: wol_verify
|
when: wol_verify
|
||||||
|
|
||||||
- name: Fail if MAC address could not be detected
|
|
||||||
fail:
|
|
||||||
msg: "Unable to determine MAC address for interface {{ wol_final_interface }}"
|
|
||||||
when:
|
|
||||||
- wol_report_mac
|
|
||||||
- wol_mac_address | length == 0
|
|
||||||
|
|
||||||
- name: Report Wake-on-LAN sender details
|
- name: Report Wake-on-LAN sender details
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg:
|
msg:
|
||||||
- "Wake-on-LAN enabled on interface: {{ wol_final_interface }}"
|
- "Wake-on-LAN enabled successfully"
|
||||||
|
- "Bridge: {{ wol_bridge }}"
|
||||||
|
- "Physical NIC: {{ wol_detected_phy }}"
|
||||||
- "MAC address: {{ wol_mac_address }}"
|
- "MAC address: {{ wol_mac_address }}"
|
||||||
- "Example WOL commands:"
|
- "Example commands:"
|
||||||
- " wakeonlan {{ wol_mac_address }}"
|
- " wakeonlan {{ wol_mac_address }}"
|
||||||
- " etherwake {{ wol_mac_address }}"
|
- " etherwake {{ wol_mac_address }}"
|
||||||
- "Home Assistant:"
|
- "Home Assistant:"
|
||||||
- " mac: {{ wol_mac_address }}"
|
- " mac: {{ wol_mac_address }}"
|
||||||
when: wol_report_mac
|
when: wol_report_mac
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Enable Wake-on-LAN on {{ wol_interface_final }}
|
Description=Enable Wake-on-LAN on {{ wol_final_interface }}
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=/sbin/ethtool -s {{ wol_interface_final }} wol {{ wol_mode }}
|
ExecStart=/sbin/ethtool -s {{ wol_final_interface }} wol {{ wol_mode }}
|
||||||
|
Restart=always
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
Reference in New Issue
Block a user