From 2111189ec76216d4f5097448474cffa21129dc52 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Tue, 27 Oct 2026 22:43:02 +0100 Subject: [PATCH] chore(ansible): remove the Shelly NTP play Shelly devices are not Ansible-managed. Drops plays/configure-shelly-ntp.yml, its only helper files/discover_shelly.py, and the mention in site.yml. Co-Authored-By: Claude Opus 5.5 --- ansible/files/discover_shelly.py | 67 ------------- ansible/plays/configure-shelly-ntp.yml | 125 ------------------------- ansible/site.yml | 3 +- 3 files changed, 1 insertion(+), 194 deletions(-) delete mode 100755 ansible/files/discover_shelly.py delete mode 100644 ansible/plays/configure-shelly-ntp.yml diff --git a/ansible/files/discover_shelly.py b/ansible/files/discover_shelly.py deleted file mode 100755 index 31309e0d..00000000 --- a/ansible/files/discover_shelly.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 -""" -Discover Shelly devices on the network via HTTP API -Returns JSON array of discovered devices -""" - -import sys -import json -import ipaddress -import concurrent.futures -import urllib.request -import urllib.error - -def check_shelly(ip): - """Check if IP is a Shelly device and return info""" - try: - url = f"http://{ip}/shelly" - req = urllib.request.Request(url, headers={'User-Agent': 'Ansible-Shelly-Discovery'}) - with urllib.request.urlopen(req, timeout=2) as response: - data = json.loads(response.read().decode()) - # Gen1 devices don't have 'gen' field, default to 1 - gen = data.get('gen', 1) - if gen is None: - gen = 1 - return { - 'ip': str(ip), - 'type': data.get('type', 'unknown'), - 'mac': data.get('mac', ''), - 'gen': gen, - 'name': data.get('name', data.get('id', str(ip))), - 'fw_id': data.get('fw_id', data.get('fw', 'unknown')) - } - except (urllib.error.URLError, urllib.error.HTTPError, OSError, json.JSONDecodeError): - return None - except Exception: - return None - -def main(): - if len(sys.argv) < 2: - print("Usage: discover_shelly.py [network2] ...") - print("Example: discover_shelly.py 10.2.30.0/24 10.2.20.0/24") - sys.exit(1) - - networks = sys.argv[1:] - devices = [] - - # Collect all IPs to scan - all_ips = [] - for network in networks: - try: - all_ips.extend(ipaddress.IPv4Network(network).hosts()) - except ValueError as e: - print(f"Invalid network: {network} - {e}", file=sys.stderr) - continue - - # Scan in parallel - with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor: - results = executor.map(check_shelly, all_ips) - for result in results: - if result: - devices.append(result) - - # Output JSON - print(json.dumps(devices, indent=2)) - -if __name__ == "__main__": - main() diff --git a/ansible/plays/configure-shelly-ntp.yml b/ansible/plays/configure-shelly-ntp.yml deleted file mode 100644 index 7217e39f..00000000 --- a/ansible/plays/configure-shelly-ntp.yml +++ /dev/null @@ -1,125 +0,0 @@ ---- -# Configure NTP server on all Shelly devices -# Discovers Shelly devices via network scan and configures them to use local NTP server -# -# Usage: -# ansible-playbook plays/configure-shelly-ntp.yml -# ansible-playbook plays/configure-shelly-ntp.yml -e "shelly_ntp_server=10.2.40.4" -# ansible-playbook plays/configure-shelly-ntp.yml -e "shelly_networks=10.2.30.0/24,10.2.20.0/24" - -- name: Configure Shelly NTP Settings - hosts: localhost - connection: local - gather_facts: no - - vars: - shelly_ntp_server: "ntp.renner.uno" - shelly_networks: "10.2.30.0/24 10.2.20.0/24" - shelly_timeout: 5 - - tasks: - - name: Discover Shelly devices on network - script: "{{ playbook_dir }}/../files/discover_shelly.py {{ shelly_networks }}" - args: - executable: python3 - register: discovered_devices - changed_when: false - - - name: Parse discovered devices - set_fact: - shelly_devices: "{{ discovered_devices.stdout | from_json }}" - - - name: Display discovered Shelly devices - debug: - msg: "Found {{ shelly_devices | length }} Shelly devices" - - - name: Show device list - debug: - msg: "{{ item.name }} ({{ item.type }}) - {{ item.ip }} - Gen{{ item.gen }}" - loop: "{{ shelly_devices }}" - when: shelly_devices | length > 0 - - - name: Configure NTP on Gen1 devices - uri: - url: "http://{{ item.ip }}/settings?sntp_server={{ shelly_ntp_server }}" - method: GET - timeout: "{{ shelly_timeout }}" - return_content: yes - loop: "{{ shelly_devices | selectattr('gen', 'equalto', 1) | list }}" - register: gen1_results - ignore_errors: yes - when: shelly_devices | length > 0 - - - name: Configure NTP on Gen2+ devices - uri: - url: "http://{{ item.ip }}/rpc/Sys.SetConfig" - method: POST - body_format: json - body: - config: - sntp: - server: "{{ shelly_ntp_server }}" - timeout: "{{ shelly_timeout }}" - return_content: yes - loop: "{{ shelly_devices | selectattr('gen', 'greaterthan', 1) | list }}" - register: gen2_results - ignore_errors: yes - when: shelly_devices | length > 0 - - - name: Verify Gen1 NTP configuration - uri: - url: "http://{{ item.ip }}/settings" - method: GET - timeout: "{{ shelly_timeout }}" - return_content: yes - loop: "{{ shelly_devices | selectattr('gen', 'equalto', 1) | list }}" - register: gen1_verify - ignore_errors: yes - when: shelly_devices | length > 0 - - - name: Verify Gen2+ NTP configuration - uri: - url: "http://{{ item.ip }}/rpc/Sys.GetConfig" - method: GET - timeout: "{{ shelly_timeout }}" - return_content: yes - loop: "{{ shelly_devices | selectattr('gen', 'greaterthan', 1) | list }}" - register: gen2_verify - ignore_errors: yes - when: shelly_devices | length > 0 - - - name: Summary - Gen1 devices configured - debug: - msg: "{{ item.item.name }} ({{ item.item.ip }}): NTP={{ item.json.sntp.server | default('unknown') }}" - loop: "{{ gen1_verify.results | default([]) }}" - when: - - gen1_verify is defined - - gen1_verify.results is defined - - item.json is defined - - item.json.sntp is defined - loop_control: - label: "{{ item.item.name | default(item.item.ip) }}" - - - name: Summary - Gen2+ devices configured - debug: - msg: "{{ item.item.name }} ({{ item.item.ip }}): NTP={{ item.json.sntp.server | default('unknown') }}" - loop: "{{ gen2_verify.results | default([]) }}" - when: - - gen2_verify is defined - - gen2_verify.results is defined - - item.json is defined - - item.json.sntp is defined - loop_control: - label: "{{ item.item.name | default(item.item.ip) }}" - - - name: Final summary - debug: - msg: | - ========================================== - Shelly NTP Configuration Complete - ========================================== - Total devices found: {{ shelly_devices | length }} - Gen1 devices: {{ shelly_devices | selectattr('gen', 'equalto', 1) | list | length }} - Gen2+ devices: {{ shelly_devices | selectattr('gen', 'greaterthan', 1) | list | length }} - NTP Server: {{ shelly_ntp_server }} - ========================================== diff --git a/ansible/site.yml b/ansible/site.yml index 8fd43702..6637a525 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -6,8 +6,7 @@ # ansible-playbook site.yml # # One-off actions are not state and stay separate: plays/update-os.yml, -# plays/update-dist-upgrade.yml, plays/rotate-netbird-secrets.yml, -# plays/configure-shelly-ntp.yml (devices outside the inventory). +# plays/update-dist-upgrade.yml, plays/rotate-netbird-secrets.yml. - name: Base system ansible.builtin.import_playbook: plays/common.yml -- 2.54.0