Files
forge-tools-proxmox/internal/tools/backup.go
T

91 lines
3.2 KiB
Go

package tools
import (
"context"
"fmt"
"net/url"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// backup.go — бэкапы (vzdump): list (read) и create (async UPID).
// В v1 НЕ реализованы restore/delete/prune: это тяжёлые необратимые
// операции, требующие выверенной семантики; их лучше сделать отдельным
// модулем-уточнением, чем рисковать в базовом. (см. README «Roadmap».)
func registerBackupTools(s *mcp.Server) {
s.AddTool(&mcp.Tool{
Name: "backup_list",
Description: "List recent backup (vzdump) tasks. Read-only.",
InputSchema: schema(map[string]any{
"node": strProps("Node name (empty = whole cluster)", false),
"host": strProps("Cluster alias (default: primary)", false),
}, nil),
}, backupListHandler)
registerPatternTool(s, &mcp.Tool{
Name: "backup_create",
Description: "Create a backup (vzdump) of a VM/CT. Async — returns UPID; poll via task_status(wait). Requires confirm + write permission.",
InputSchema: schema(map[string]any{
"node": strProps("Node name", true),
"vmid": strProps("VM/CT ID", true),
"storage": strProps("Backup storage (default: node local)", false),
"mode": strProps("Backup mode", true, "snapshot", "suspend", "stop"),
"compress": strProps("Compression", false, "zstd", "gzip", "lzo", "none"),
"kind": strProps("Guest type", false, "qemu", "lxc"),
"confirm": strProps("Set to \"true\" to confirm", true, "true"),
}, []string{"node", "vmid", "confirm"}),
}, vmPatterns, backupCreateHandler)
}
func backupListHandler(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
t, err := tenantFor(ctx, req)
if err != nil {
return errorResult(err.Error()), nil
}
args := requestArgs(req)
host, err := resolveHost(t, args)
if err != nil {
return errorResult(err.Error()), nil
}
cctx, cancel := timeout(ctx, t)
defer cancel()
data, err := t.BackupList(cctx, host, getString(args, "node", ""))
if err != nil {
return errorResult(err.Error()), nil
}
return textResult(pretty(data)), nil
}
func backupCreateHandler(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
t, err := tenantFor(ctx, req)
if err != nil {
return errorResult(err.Error()), nil
}
args := requestArgs(req)
node, vmid, host, r := resolveVMArgs(t, args)
if r != nil {
return r, nil
}
if err := confirm(args, "backup_create"); err != nil {
return errorResult(err.Error()), nil
}
if err := gateVMWrite(t, host, vmid); err != nil {
return errorResult(err.Error()), nil
}
kind := guestKind(args)
// mode: snapshot/suspend/stop. Если задан storage/compress — кладём в form.
form := url.Values{"mode": {getString(args, "mode", "snapshot")}}
if s := getString(args, "storage", ""); s != "" {
form.Set("storage", s)
}
if c := getString(args, "compress", ""); c != "" && c != "none" {
form.Set("compress", c)
}
upid, err := t.BackupCreate(ctx, host, node, kind, vmid, form)
if err != nil {
return errorResult(err.Error()), nil
}
return textResult(upidMsg("backup_create", fmt.Sprintf("%s/%d", node, vmid), upid)), nil
}