""" GetFileAction — reads a remote file via SSH and saves it as a config snapshot. Compatible with Linux-based devices (raspberry, server, embedded, other). """ from app.models.device import Device from app.models.object import Object from app.plugins.base import ActionResult, BaseAction, Emitter from app.services import snapshot as snapshot_service from app.services import ssh as ssh_service class GetFileAction(BaseAction): name = "get_file" display_name = "Get File (Snapshot)" compatible_categories = ["raspberry", "server", "embedded", "other"] params_schema = [ { "name": "path", "type": "string", "label": "File path", "required": True, "placeholder": "/etc/ntp.conf", }, ] async def execute( self, device: Device, obj: Object, params: dict, emit: Emitter, db=None ) -> ActionResult: path = params.get("path", "").strip() if not path: return ActionResult(success=False, error="No file path specified") await emit(f"[{device.ip}] Reading {path}", "info") result = await ssh_service.run_command(device, obj, f"cat {path}", db=db) if not result.success: msg = result.error or result.stderr or f"exit code {result.exit_code}" await emit(f"[{device.ip}] Failed: {msg}", "error") return ActionResult( success=False, stdout=result.stdout, stderr=result.stderr, exit_code=result.exit_code, error=msg, ) content = result.stdout snap_id, sha256, size = await snapshot_service.save_snapshot( device_id=device.id, content=content, label=path, ) await emit( f"[{device.ip}] Snapshot saved: {sha256[:12]}… ({size} bytes, id={snap_id})", "info", ) return ActionResult( success=True, stdout=content, exit_code=0, data={"snapshot_id": snap_id, "sha256": sha256, "size": size, "path": path}, )