--- # ============================================================ # Install required packages # ============================================================ - name: Install required packages ansible.builtin.apt: name: ethtool state: present update_cache: true # ============================================================ # Detect physical NICs with WOL support using Ansible facts # ============================================================ - name: Gather network interface facts ansible.builtin.setup: gather_subset: - network when: ansible_facts.interfaces is not defined - name: Display interfaces ansible.builtin.debug: msg: > {{ ansible_facts.interfaces }} # - name: Get interfaces starting with "en" or "eth" # ansible.builtin.set_fact: # en_interfaces: "{{ ansible_facts.interfaces | select('match', '^eth|^ens|^enp') | unique | list }}" - name: Get interfaces starting with "en" or "eth" ansible.builtin.set_fact: en_interfaces: >- {{ ansible_facts.interfaces | select('match', '^(eth|en)') | list }} # ============================================================ # 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: msg: "Interfaces to configure for WOL: {{ wol_final_interfaces }}" - name: Check supported Wake-on-LAN modes ansible.builtin.shell: "ethtool {{ item }} | grep 'Supports Wake-on' | tail -1 | awk '{print $3}'" loop: "{{ wol_final_interfaces }}" register: wol_supported changed_when: false when: wol_final_interfaces | length > 0 - name: Check if WOL is enabled ansible.builtin.shell: "ethtool {{ item }} | grep 'Wake-on' | tail -1 | awk '{print substr($0,length,1)}'" register: wol_enabled changed_when: false failed_when: false loop: "{{ wol_final_interfaces }}" when: wol_final_interfaces | length > 0 # ============================================================ # Enable or disable WOL as needed # ============================================================ - name: Set Wake-on-LAN mode ansible.builtin.command: "ethtool -s {{ item.0 }} wol {{ wol_mode }}" loop: "{{ wol_final_interfaces | zip(wol_enabled.results, wol_supported.results) | list }}" loop_control: label: "{{ item.0 }}" when: - item.1.stdout is defined - item.2.stdout is defined - wol_mode not in item.1.stdout - wol_mode in item.2.stdout # ============================================================ # Create udev rules for persistence # ============================================================ - name: Create udev rule for WOL persistence ansible.builtin.template: src: 90-wol.rules.j2 dest: /etc/udev/rules.d/90-wol.rules owner: root group: root mode: '0644' notify: - Reload_udev_rules - Trigger_udev_net # ============================================================ # Verification & Reporting # ============================================================ - name: Verify Wake-on-LAN status ansible.builtin.command: "ethtool {{ item }}" register: wol_status changed_when: false loop: "{{ wol_final_interfaces }}" loop_control: label: "{{ item }}" when: wol_verify and wol_final_interfaces | length > 0 - name: Display WOL status per interface ansible.builtin.debug: msg: > Interface {{ item.item }} WOL Status: {{ item.stdout_lines | select('search', 'Wake-on:') | first | default('Status Unknown') }} loop: "{{ wol_status.results | default([]) }}" loop_control: label: "{{ item.item }}" when: wol_verify - name: Get MAC addresses for all interfaces ansible.builtin.set_fact: wol_mac_addresses: >- {{ wol_final_interfaces | map('extract', ansible_facts, attribute='macaddress') | list }} - name: Report WOL configuration ansible.builtin.debug: msg: | Wake-on-LAN Configuration Summary: =================================== Bridges Configured: {{ wol_bridges | join(', ') }} Physical Interfaces: {{ wol_final_interfaces | join(', ') }} WOL Mode: {{ wol_mode }} {% if bond0_stat.stat.exists %} Bond0 Detected: Yes Bond0 Slaves: {{ bond0_slaves.stdout_lines | join(', ') }} {% endif %} {% if wol_report_mac and wol_mac_addresses | length > 0 %} MAC Addresses: {% for iface, mac in (wol_final_interfaces | zip(wol_mac_addresses) | list) %} - {{ iface }}: {{ mac | default('Unable to detect') }} {% endfor %} {% endif %}