pve-fclu (0.1.0~alpha42) stable; urgency=medium

  * feat(#8): auto-assign new volumes to a consistency/protection group. New optional store
    property `auto_cg <group>`: alloc_image tags every newly allocated volume's `cg`
    attribute to that group, so new disks automatically join `pve-fclu-cg` group snapshots
    without per-disk tagging (schedule the snapshot op via cron for hands-off protection).
    On Hitachi VSP One / E-series the CM REST exposes no bare-LDEV protection construct or
    native schedule, so the mechanism is the existing per-volume `cg` tag — a registry-only
    write inside the alloc register(), so it never issues an array call and cannot fail
    provisioning; idempotent, and register()'s merge preserves the tag on resize. Fresh
    allocations only (not clones/adopted volumes); empty auto_cg = unset. Live-validated on
    the E590H. 229 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 29 Jul 2026 12:46:47 -0300

pve-fclu (0.1.0~alpha41) stable; urgency=medium

  * feat(#7): surface array-side (out-of-band) snapshots, read-only + opt-in. Thin Image
    snapshots taken outside PVE (array schedules, replication, the array UI/CLI) were
    invisible; a new `surface_oob_snapshots` store option (default off) lists them as
    read-only `oob-*` entries. Classification is registry-authoritative (snap_id in neither
    the PVE nor CG records, and S-VOL not a registered volume — excludes clone backing
    pairs); they are added as detached roots (never spliced into the `current` rollback
    ancestry); the `oob-` prefix is reserved (create + rename reject it); and delete/rollback
    of an `oob-` entry are refused so an array replication/retention base cannot be destroyed
    through PVE. Fail-soft (discovery errors surface zero OOB snaps). Architect-designed,
    independently code-reviewed; live-validated on the E590H. 228 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 29 Jul 2026 12:30:41 -0300

pve-fclu (0.1.0~alpha40) stable; urgency=medium

  * hitachi: memoize the ensure-time WWN reconcile per (port,hg) (#17). A multi-disk
    qm clone re-activates the same node for every disk and publish_lu self-ensures, so
    ensure_host_access re-issued its never-cached foreign-WWN guard read (list_host_wwns)
    up to 3x per disk/port — the dominant remaining clone host-mapping cost after
    alpha34's T2-5/T2-6. A process-lifetime _wwn_ok{"port,hg"} memo (mirroring _hmo_ok)
    runs the guard read + WWN registration + #4 rollback ONCE per (port,hg); across a
    3-disk/2-port burst that cuts list_host_wwns 18 -> 8. SAFETY: the memo is confined to
    the ensure-time reconcile — the map authorization (_assert_hg_ownership) still reads
    fresh before every map_lun and is never memoized, so a foreign WWN appearing after
    the memo is still caught before any LUN maps. Invalidated with _hmo_ok plus on a
    pre-map conflict re-resolve. Architect-designed, independently code-reviewed APPROVE.
    227 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 29 Jul 2026 11:34:54 -0300

pve-fclu (0.1.0~alpha39) stable; urgency=medium

  * hitachi: shard nodes across FC target-port groups (#5). Optional port_groups +
    node_port_groups (default off => every node maps to all target_ports, unchanged).
    A LU path is consumed per (LDEV x host-group x port) and the per-FE-port budget is
    the aggregate across all host groups on that port, so a whole cluster sharing two
    ports caps at ~2,048 mapped disks regardless of node count; sharding nodes across N
    disjoint port groups multiplies that ceiling by N, within one storeid so migration
    is preserved. _resolve_local_ports narrows the four per-node mapping loops; validation
    fails loud on stranding typos and warns on a single-port (non-HA) group. Manual zoning
    prerequisite; derive-from-login + auto-policy deferred to the Fabric plane. New
    docs/adr/0003 + driver-hitachi.md section. 223 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 22 Jul 2026 14:31:47 -0300

pve-fclu (0.1.0~alpha38) stable; urgency=medium

  * hitachi: offload a linked clone from a LIVE ('current') volume (#19). A Thin Image
    pair binds its S-VOL directly onto a live P-VOL, so `qm clone` (linked) of a running
    / non-template disk is now offloaded instead of falling back to a host-side copy. No
    intermediate snapshot object is created — the auto_split IS the crash-consistent
    instant — and the backing pair is released on free like any linked clone (#23). Gated
    on a new `clone.from_current` capability leaf, so a backend whose clone API requires a
    snapshot source (Nimble model) declines and PVE keeps host-copying (core stays
    vendor-neutral). Crash-consistent only for a running guest; fsfreeze for app
    consistency. 220 unit tests.
  * tools: add `validate-copy-offload-freeze.sh` + docs (#22) — a supervised live-
    validation harness for the upstream copy-offload freeze bracket (all-offloaded /
    vm_suspend fallback / mixed / last-disk-deferred; asserts guest-always-thawed and a
    real torn-vs-consistent multi-disk check). Dry-run by default; refuses to run unless
    BOTH patched packages are installed (else a running clone falls back to drive-mirror
    and false-PASSes) and positively asserts the offload path ran. Prod-VMID denylist +
    test-window backstops; the live run is a gated operator step.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 22 Jul 2026 00:42:58 -0300

pve-fclu (0.1.0~alpha37) stable; urgency=medium

  * pve-fclu-cg: fix a `$vmid's` in the `clone` output that Perl parsed as the archaic
    `'` package separator ($vmid::s), so the attach hint rendered "VM  config" (blank)
    and warned "Old package separator used in string" on every invocation. Drop the
    possessive apostrophe. Found during the alpha36 grouped-clone live validation on the
    E590H (which otherwise PASSED: 2 independent full clones, correct size, no parent).

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Tue, 21 Jul 2026 11:10:00 -0300

pve-fclu (0.1.0~alpha36) stable; urgency=medium

  * fclu: wire the grouped full-clone primitives to a consumer. New `pve-fclu-cg clone
    <store> <cg> <target-vmid>` (Plugin cg_clone_create): clones every member of a
    consistency group as an INDEPENDENT full copy, all captured at the SAME instant.
    Because the array fixes the point-in-time by the GROUP ACTION, it prepares every
    member's S-VOL + idle pair up front (prepare_full_clone), triggers the whole group
    in ONE action (start_clone_group), then polls each copy to completion
    (clone_copy_state). New clones are registered as disks of the target VM (independent —
    no CoW parent); the operator attaches them (`qm set <vmid> -scsiN <volid>`). Rolls back
    prepared S-VOLs AND reservations on any failure with no double-free (prepare_full_clone
    already reaps its own unpaired S-VOL). Capability-gated on copy.full. This is the
    array-side consumer the sister session's primitives were built for; the #7780
    copy-offload hook can drive the same primitives once upstream lands. 219 unit tests;
    independent code review. user-guide CG section updated.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Tue, 21 Jul 2026 10:30:00 -0300

pve-fclu (0.1.0~alpha35) stable; urgency=medium

  * fclu: implement check_connection() — the plugin inherited the base method, which
    always returns 1, so PVE::Storage::activate_storage() could never report an
    unreachable array as offline. It now connects and reaches the pool, using a
    throwaway session so the probe neither populates nor tears down the driver cache,
    and returns false (not die) so an unreachable array reads as offline.
  * packaging: ship the operator documentation. usr/share/doc/pve-fclu-core now carries
    user-guide.md, and usr/share/doc/pve-fclu-hitachi carries driver-hitachi.md and
    migration-hitachi.md. Previously an operator who installed the .deb got the sample
    configs but no guide, with the documentation only readable from the git tree.
    Developer docs (test-plan, packaging-obs, implementation-plan, branding) stay
    in-tree deliberately — they describe building the project, not running it.
  * docs: correct stale project-status claims. CLAUDE.md said "design phase, no
    implementation"; docs/test-plan.md said "never run against live hardware" with an
    empty A–H results table. Both contradicted many releases of live validation. The
    alpha label is kept, with the structural reason stated: one production driver plus
    a mock, so the vendor-neutral abstraction is still unproven by a second vendor.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sat, 18 Jul 2026 15:40:00 -0300

pve-fclu (0.1.0~alpha34) stable; urgency=medium

  * hitachi: cut clone host-mapping REST amplification (HBSD backlog T2, GH #17).
  * T2-6 consistent LUN-id across a node's ports: publish_lu maps the ldev on the HEAD
    port (array auto-assigns), captures the LUN, then REQUESTS that same LUN on the other
    ports -- so multipath sees ONE consistent LUN across every path AND the LUN is known
    without a post-map list_luns read per non-head port (the query amplifier). If the
    requested LUN is held by another ldev on a port (conflict / SSB B958,0947) it falls
    back to auto-assign there. map_lun gains an explicit-lun option.
  * T2-5 HMO-reconcile cache: once a (port,host-group) is confirmed to carry the required
    host-mode options, cache that for the process so subsequent per-disk activates in a
    multi-disk clone skip the get_host_group read (a per-disk x per-port amplifier).
  * Net: for an N-port node, ~N-1 fewer list_luns per disk mapped + the HMO get_host_group
    dropped after the first disk. The WWN-ownership safety gate (fresh reads) is untouched.
    213 unit tests; independent code review.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sun, 12 Jul 2026 12:30:00 -0300

pve-fclu (0.1.0~alpha33) stable; urgency=medium

  * hitachi: structured messageId/SSB error classification (HBSD backlog T3-8). The
    RestClient now throws a `RestError` carrying the array's `messageId` +
    `errorCode.SSB1/SSB2` (extracted from the CM REST error body / job error) instead of a
    bare string; it stringifies to the same human message so every existing warn/regex/
    re-die keeps working. `_translate_rest_error` classifies off the STABLE code first
    (SSB pairs + KART ids -> §13 codes: 2E22/0001 & B958/015A already_exists, B958/0947
    conflict, B957/4184 & 2E11/2209 limit, 2E30/600E invalid, 2E11/2205-2207 &
    KART00003-E & KART40050-52-E array_busy, KART30013-E not_found), falling back to the
    HTTP-status + English-text regex only when the array gives no code we recognise. This
    retires the fragile English-regex band-aids (e.g. the "does not have LU paths"
    ordering hack): a stable code now wins over misleading message text, and the
    messageId/SSB are preserved in the error's vendor blob for logs. 210 unit tests;
    independent code review.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sun, 12 Jul 2026 11:55:00 -0300

pve-fclu (0.1.0~alpha32) stable; urgency=medium

  * OpenStack HBSD re-review batch (net-new items N1-N16; replication-gated + a few larger
    items deferred with notes in the backlog).
  * T1 correctness: N1 plain + CG snapshots now set canCascade + isDataReductionForceCopy
    (a snapshot of a dedup/compression P-VOL was array-rejected; without canCascade a
    snapshot could not be a clone source). N2 restore_snapshot uses a dedicated 24h budget
    and FAILS instead of splitting mid-restore (no torn P-VOL). N3 restore verifies the
    pair's P-VOL matches the target volume.
  * Transport (RestClient): N5 HTTP keep-alive (reuse the TCP+TLS connection across the
    create-then-poll / per-port clone calls - GH#17). N9 retry a genuine transport error on
    a single-endpoint non-idempotent POST (the request never reached the array). N10
    configurable http_timeout. N11 validate Content-Type before decode_json (middlebox HTML
    200 -> classified error, not an opaque die). N16 extract composite (port,hg,lun) job ids.
  * Data/host path: N7 full clone waits for copy completion + surfaces a PSUE copy failure.
    N8 publish_lu maps idempotently (LU-path-already-defined = success) with bounded
    array_busy retry; matching unmap retry. N12 new `pve-fclu-host reclaim-groups` reaps THIS
    node's empty host groups (WWN-ownership-gated) so a decommissioned node doesn't exhaust
    per-port host-group slots.
  * Config/parity: N14 colon-hex ldev_range (00:03:E8, the Storage Navigator display form).
    N15 adaptive per-GiB QoS (upperIopsPerGB) scaling the IOPS ceiling by volume size.
  * 209 unit tests; independent code review.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sun, 12 Jul 2026 10:20:00 -0300

pve-fclu (0.1.0~alpha31) stable; urgency=medium

  * Consistency groups (explicit-reference model). CG membership is a per-volume `cg`
    attribute (update_volume_attribute); a volume belongs to at most one group, a VM may
    span several groups, a group may span VMs. Because PVE's storage API is per-volume with
    no multi-volume snapshot hook, a group snapshot is an EXPLICIT out-of-band operation --
    per-volume qm/pvesm snapshots are untouched. It resolves a group's members and issues
    ONE crash-consistent array snapshot (create_cg_snapshot -> single split_snapshotgroup).
  * New vendor-neutral CLI `pve-fclu-cg` (ships in pve-fclu-core): tag/untag/members/
    snapshot/snapshots/snapshot-delete. Registry gains find_cg_members/list_cgs +
    add/remove/find/list_all_cg_snapshots (records under a separate `cg_snapshots` subtree
    so they never leak into volume_snapshot_info). Plugin gains cg_snapshot_create/delete/
    list, capability-gated on snapshot.consistency_group. 199 unit tests.
  * docs/user-guide.md CG section; docs/rfc/consistency-group-snapshot.md.
  * Upstream RFC filed as Proxmox Bugzilla #7812: an optional volume_group_snapshot storage
    hook so a plain `qm snapshot` of a multi-disk VM becomes crash-consistent (companion to
    #7780). Also cross-posted the latest copy_image RFC feedback to #7780 (pve-devel
    moderation delay).

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sun, 12 Jul 2026 09:35:00 -0300

pve-fclu (0.1.0~alpha30) stable; urgency=medium

  * hitachi: fix a `$hostname's` in the alpha29 host-group rollback warning that Perl
    parsed as the archaic `'` package separator ($hostname::s), so the message dropped
    the node name and it warned "Old package separator used in string" on every module
    load. Drop the possessive apostrophe. Regression test asserts the warning names the
    node. Found during the alpha29 live CG-snapshot validation on the E590H.
  * Live-validated the alpha29 crash-consistent CG snapshot on the E590H: two in-range
    LDEVs -> create_cg_snapshot -> both S-VOLs PSUS under ONE derived group after a single
    split_snapshotgroup (the new REST call works on real microcode), clean teardown.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Fri, 10 Jul 2026 14:05:00 -0300

pve-fclu (0.1.0~alpha29) stable; urgency=medium

  * Tier-1 correctness/safety batch from the OpenStack HBSD review (hbsd-review-backlog):
  * hitachi: crash-consistent CG snapshots. create_cg_snapshot now creates every pair
    UNSPLIT under one snapshot group (isConsistencyGroup, autoSplit off), waits all pairs
    to PAIR, then issues a SINGLE split_snapshotgroup so all S-VOLs suspend at the same
    instant -- the old code split one autoSplit pair per LU, so cg_snapshot was advertised
    but the S-VOLs were NOT mutually crash-consistent. Unique derived group name (the
    static 'pve_cg' collided); best-effort pair sweep if the split fails (no shared-pool
    leak). New RestClient split_snapshotgroup.
  * core: id-recycle delete guard. free_image re-reads the LU's array label before any
    destructive op and, if it names a different volume, drops the stale registry entry
    WITHOUT unmapping/deleting -- backstops the ldev_range fence against a same-range LDEV
    recycle on a shared array. Matches on the parsed volname (tolerant of a storeid-prefix
    scheme change).
  * hitachi: wait for a deleted snapshot pair to fully dissolve (SMPP -> gone) before
    deleting the S-VOL, in the linked-clone rollback and free_image backing-pair release
    -- closes a #23-class S-VOL leak on the shared pool. Skipped when the pair delete
    itself failed (no full-budget hang).
  * hitachi: atomic host-group create. A group we freshly create that registers NONE of
    the node's WWNs is rolled back (HBSD NO_HBA_WWN_ADDED) and the port treated as
    no-access; activation fails loud only if NO configured port yields a path (a partial/
    asymmetric fabric still activates). Existing groups stay additive/best-effort.
  * hitachi: also carries the committed fix classifying "P-VOL does not have LU paths" as
    invalid (not not_found).
  * Independent code review (APPROVE, no CRITICAL/HIGH): addressed the per-port-abort and
    label-scheme MEDIUMs + the wait-budget / CG-uniqueness / CG-sweep LOWs. 197 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Fri, 10 Jul 2026 11:40:00 -0300

pve-fclu (0.1.0~alpha28) stable; urgency=medium

  * hitachi: simplify linked clones to a single Thin Image pair creation (the OpenStack
    HBSD recipe). create_linked_clone now creates a DP S-VOL and creates the autoSplit
    pair WITH svolLdevId + canCascade + isDataReductionForceCopy in ONE step -- the
    array binds the S-VOL at creation with NEITHER volume mapped. This replaces the old
    4-step #24 workaround (poolId-1 v-vol -> data-only pair -> map S-VOL -> assign),
    which existed only because a plain svolLdevId was rejected ("S-VOL does not have LU
    paths"); the two extra flags remove that constraint. Effects: clones no longer need
    the source (or clone) mapped, so a clone of an unmapped base now works;
    create_linked_clone no longer needs host_ctx (accepted but ignored); simpler + no
    mid-flow host mapping.
  * Live-validated on the E590H (embedded + Ops Center CM control planes): clone of an
    UNMAPPED base -> space-efficient CoW child (S-VOL usedBlocks 0, reads P-VOL data),
    no orphans. Found by reviewing the OpenStack Cinder Hitachi driver
    (hbsd_rest.py _create_snap_pair). Contract + fake-rest + snapshot tests updated. 190
    unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Fri, 10 Jul 2026 18:00:00 -0300

pve-fclu (0.1.0~alpha27) stable; urgency=medium

  * hitachi: support an Ops Center Configuration Manager (CM) control plane (§10). The
    CM server and the array's embedded GUM REST speak the SAME Configuration Manager
    REST API, so this is config, not a new driver: a new `control_plane` option
    ('embedded' default / 'cm') that only picks the default endpoint port (cm -> 23451),
    orthogonal to `platform` (the array MODEL, which still governs capabilities like
    QoS -- a CM-fronted VSP E is control_plane=cm + platform=vsp_e, QoS still off).
  * hitachi: poll async jobs at the storage-scoped URL
    .../objects/storages/<id>/jobs/<id> (was the flat /objects/jobs/<id>). This is the
    documented, universal form -- it works on BOTH a fronting CM server (where the flat
    form 404s, since one CM fronts many arrays) AND the array's embedded GUM REST
    (verified live on both). A CM store must stay session-less (the default), as the CM
    does not expose the per-storage session endpoint.
  * Validated live: the E590H registered on an Ops Center CM, driven through the CM at
    :23451 -- connect + 5/5 create->read->delete cycles, clean, correct QoS gating.
    190 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Thu, 09 Jul 2026 15:00:00 -0300

pve-fclu (0.1.0~alpha26) stable; urgency=medium

  * hitachi: wire up discard_zero_page (thin-pool zero-page reclaim). The property +
    GUI field + RestClient reclaim_zero_pages existed but nothing called them -- the
    §9 migration dropped the reference plugin's wiring. Restored via a vendor-neutral
    best-effort _after_deactivate hook on FCLU::Plugin::deactivate_volume (default
    no-op); the hitachiblock subclass overrides it to reclaim the LU's zero pages when
    discard_zero_page is set, after the LU is unmapped on this node. Off by default;
    matches the reference behaviour (reclaim on deactivate). Found by the live E590H
    G-phase battery (G4).
  * Also validated live in the same battery: G2 SCSI-3 PR readiness detection, G5
    concurrent registry-lock (no lost updates across nodes), F5 manage/unmanage
    adopt-release. 189 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 08 Jul 2026 12:00:00 -0300

pve-fclu (0.1.0~alpha25) stable; urgency=medium

  * hitachi: model-gate the QoS capability. Per Hitachi's support matrix (OpenStack
    HBSD "System requirements for a QoS"), QoS exists only on VSP F/G350-900 and VSP
    5000 (fw 88-06-01+ / CM REST 10.2.0+). The VSP E series (vsp_e) and VSP One Block
    (vsp_one) have no QoS REST surface at all -- live-confirmed on an E590H: the LDEV
    object carries no QoS fields and every io-control endpoint 404s. So qos=0 for
    vsp_e/vsp_one, qos=1 only for vsp_g (Ops Center CM; unvalidated pending the CM
    connector). alloc now capability-gates set_lu_qos so it is never attempted (and no
    longer draws an [invalid]) on a platform without QoS.
  * plugin: fix `pvesm free` of a volume that was allocated but never activated. PVE's
    content DELETE handler resolves the volume vtype via path() before vdisk_free, and
    filesystem_path used to die ("no resolvable device identity") for a never-mapped
    volume -- wedging the free and orphaning the LU. It now returns metadata with an
    undef device path; real device consumers only call path() post-activation.
  * Both surfaced by the live E590H F/G validation battery (F1-F4 + F6 all passed,
    including no data corruption under load). 187 unit tests.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Wed, 08 Jul 2026 09:00:00 -0300

pve-fclu (0.1.0~alpha24) stable; urgency=medium

  * hitachi: default host_group_prefix to a stable short "PVE" instead of the harmful
    auto-derived "PVE-<clustername>" (context-dependent + >16 chars -> truncation
    collapse). This was the true cause of the per-clone host-group WWN scan; with the
    prefix matching the array groups, #2's truncation-tolerant resolver eliminates it.

 -- Ciro Iriarte <ciro.iriarte+software@gmail.com>  Sat, 04 Jul 2026 02:15:00 -0300

