diff --git a/app/api/ansible.py b/app/api/ansible.py index 0963237..342e1d9 100644 --- a/app/api/ansible.py +++ b/app/api/ansible.py @@ -37,9 +37,10 @@ def get_inventory_raw(): @ansible_bp.route('/inventory/sync', methods=['POST']) def sync_inventory(): - """Sync all active app devices into monitoring_devices inventory group""" + """Sync all active app devices into monitoring_devices and wmt_clients inventory groups""" try: result = ansible_service.sync_devices_to_inventory() + ansible_service.sync_wmt_devices_to_inventory() status = 200 if result.get('success') else 400 return jsonify(result), status except Exception as e: @@ -116,6 +117,7 @@ def refresh_inventory(): """Refresh Ansible inventory from database (legacy alias for /sync)""" try: result = ansible_service.sync_devices_to_inventory() + ansible_service.sync_wmt_devices_to_inventory() return jsonify(result), 200 if result.get('success') else 400 except Exception as e: logging.error(f"Error refreshing inventory: {e}") diff --git a/app/services/ansible_service.py b/app/services/ansible_service.py index 4e6f908..e39ad36 100644 --- a/app/services/ansible_service.py +++ b/app/services/ansible_service.py @@ -174,6 +174,52 @@ class AnsibleService: logging.error(f"Error syncing devices to inventory: {e}") return {'success': False, 'error': str(e)} + def sync_wmt_devices_to_inventory(self) -> Dict: + """Sync all active WMT-enabled devices into the wmt_clients inventory group. + Only devices that have checked in via the WMT client API (wmt_last_seen IS NOT NULL) + are included. Preserves all other inventory groups.""" + try: + data = self._read_inventory() + children = data['all'].setdefault('children', {}) + children['wmt_clients'] = {'hosts': {}} + synced = 0 + with self.db.get_session() as session: + devices = ( + session.query(Device) + .filter(Device.status == 'active', + Device.wmt_last_seen.isnot(None)) + .all() + ) + settings = self.load_settings() + use_password = settings.get('use_password_auth', False) + ssh_password = settings.get('ssh_fallback_password', '') + for device in devices: + if device.device_ip == '127.0.0.1' or device.hostname == 'localhost': + hvars = {'ansible_connection': 'local', 'ansible_host': '127.0.0.1'} + elif use_password and ssh_password: + hvars = { + 'ansible_host': device.device_ip, + 'ansible_user': 'pi', + 'ansible_password': ssh_password, + 'ansible_become_password': ssh_password, + 'ansible_ssh_common_args': '-o PubkeyAuthentication=no -o PreferredAuthentications=password -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + } + else: + hvars = { + 'ansible_host': device.device_ip, + 'ansible_user': 'pi', + 'ansible_ssh_private_key_file': str(self.ssh_key_path.resolve()), + 'ansible_ssh_common_args': '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + } + children['wmt_clients']['hosts'][device.hostname] = hvars + synced += 1 + self._write_inventory(data) + return {'success': True, 'synced': synced, + 'message': f'Synced {synced} WMT device(s) to wmt_clients group'} + except Exception as e: + logging.error(f'Error syncing WMT devices to inventory: {e}') + return {'success': False, 'error': str(e)} + def add_group_to_inventory(self, group_name: str) -> Dict: """Add a new empty group to the inventory.""" import re as _re @@ -193,9 +239,9 @@ class AnsibleService: def remove_group_from_inventory(self, group_name: str) -> Dict: """Remove a custom group from the inventory.""" - if group_name == 'monitoring_devices': + if group_name in ('monitoring_devices', 'wmt_clients'): return {'success': False, - 'error': 'Cannot remove the default monitoring_devices group'} + 'error': f'Cannot remove the built-in "{group_name}" group'} try: data = self._read_inventory() children = data['all'].get('children', {}) or {} @@ -264,6 +310,7 @@ class AnsibleService: def generate_dynamic_inventory(self) -> Dict: """Sync DB devices into inventory and return the full inventory dict.""" self.sync_devices_to_inventory() + self.sync_wmt_devices_to_inventory() return self._read_inventory() def create_update_playbook(self) -> str: diff --git a/data/wmt_releases/latest.json b/data/wmt_releases/latest.json index 0e31deb..6a0f7d9 100644 --- a/data/wmt_releases/latest.json +++ b/data/wmt_releases/latest.json @@ -1,6 +1,6 @@ { - "version": "2.9", - "notes": "", - "uploaded_at": "2026-05-13T13:17:18", - "filename": "wmt_v2.9.zip" + "version": "3.0", + "notes": "Auto-update from server; TestTemplate silent mode; notconfig devices surface in To Be Configured section", + "uploaded_at": "2026-06-26T07:56:55", + "filename": "wmt_v3.0.zip" } \ No newline at end of file diff --git a/data/wmt_releases/wmt_v3.0.zip b/data/wmt_releases/wmt_v3.0.zip new file mode 100644 index 0000000..7db3c7b Binary files /dev/null and b/data/wmt_releases/wmt_v3.0.zip differ