chore(ansible): remove the Shelly NTP play #1501
@@ -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 <network1> [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()
|
||||
@@ -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 }}
|
||||
==========================================
|
||||
+1
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user