""" MikrotikGetNTPAction — reads NTP client configuration from RouterOS via SSH. """ import re from app.models.device import Device from app.models.object import Object from app.plugins.base import ActionResult, BaseAction, Emitter from app.services import ssh as ssh_service def _parse_ntp_print(output: str) -> dict: """Parse key=value pairs from RouterOS print output.""" data: dict = {} for line in output.splitlines(): line = line.strip() # RouterOS format: " servers: pool.ntp.org" or "enabled: yes" match = re.match(r"^([\w-]+)\s*:\s*(.*)$", line) if match: data[match.group(1)] = match.group(2).strip() return data class MikrotikGetNTPAction(BaseAction): name = "mikrotik_get_ntp" display_name = "Mikrotik: Get NTP Config" compatible_categories = ["mikrotik"] params_schema = [] async def execute( self, device: Device, obj: Object, params: dict, emit: Emitter, db=None ) -> ActionResult: await emit(f"[{device.ip}] /system ntp client print", "info") result = await ssh_service.run_command( device, obj, "/system ntp client print", db=db ) if result.error: await emit(f"[{device.ip}] Error: {result.error}", "error") return ActionResult( success=False, stdout=result.stdout, stderr=result.stderr, exit_code=result.exit_code, error=result.error, ) parsed = _parse_ntp_print(result.stdout) await emit(f"[{device.ip}] NTP: {result.stdout[:200]}", "info") return ActionResult( success=True, stdout=result.stdout, exit_code=result.exit_code, data={"ntp": parsed}, )