utp_service/backend/app/plugins/builtin/ssh/get_file.py

66 lines
2.1 KiB
Python

"""
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},
)