package storage import ( "strings" "gitea.dooplex.hu/admin/felhom-agent/internal/proxmox" ) // deriveDurableID computes the DR-load-bearing durable identifier for a target (doc 03 // §7). It MUST be deterministic: the hub stores it and, on host loss, re-attaches the // RIGHT physical target by it — the false-id failure mode is re-attaching the WRONG disk. // // Per type: // - usb / local-dir: the filesystem UUID of the backing device (survives re-cabling / // re-enumeration that renames /dev/sdX). // - nfs / cifs: "server:export" (or "server:share") — the network identity. // - pbs: "server:datastore" plus the cert fingerprint ("…#") — the repo // identity (the fingerprint pins WHICH PBS, so a spoofed server is a different id). // - lvmthin / lvm: "vgname/thinpool" (or "vgname") — informational but stable; the VG // is local and not re-attached cross-host, so a stable name is enough. // - local (builtin): the backing fs UUID if resolvable, else the path — informational. // // uuid is the already-resolved backing-device UUID ("" when unresolved); the caller // resolves it once (it also needs it for nothing else, so we pass it in to avoid a second // by-uuid scan). func deriveDurableID(typ string, s proxmox.Storage, backingDevice, uuid string) string { switch typ { case hubTypeNFS: if s.Server != "" && s.Export != "" { return s.Server + ":" + s.Export } case hubTypeCIFS: if s.Server != "" && s.Share != "" { return s.Server + ":" + s.Share } case hubTypePBS: repo := s.Datastore if s.Server != "" { repo = s.Server + ":" + s.Datastore } if repo != "" { if s.Fingerprint != "" { return repo + "#" + strings.ToLower(s.Fingerprint) } return repo } case hubTypeLVMThin, "lvm": if s.VGName != "" { if s.ThinPool != "" { return s.VGName + "/" + s.ThinPool } return s.VGName } case hubTypeUSB, hubTypeLocalDir, hubTypeLocal: if uuid != "" { return "uuid:" + uuid } if backingDevice != "" { return "dev:" + backingDevice } if s.Path != "" { return "path:" + s.Path } } // Fallback: a stable, unambiguous id from the storage name — never empty (an empty // durable_id would defeat the hub's re-attach lookup). return "store:" + s.Storage } // Reported storage-type strings (mirror hub's StorageType* constants without importing // hub here for the bare strings — the observer maps to these). const ( hubTypeLocalDir = "local-dir" hubTypeLVMThin = "lvmthin" hubTypeUSB = "usb" hubTypeNFS = "nfs" hubTypeCIFS = "cifs" hubTypePBS = "pbs" hubTypeLocal = "local" )