v0.8.31~beta1 MIT License

jt-pve-storage-dellemc

Dell EMC Storage Plugins for Proxmox VE Dell EMC 儲存伺服器的 Proxmox VE 儲存外掛

One package, one shared host-side layer, and one PVE storage type per Dell EMC product family: PowerStore over iSCSI or Fibre Channel, PowerVault ME4/ME5, and PowerFlex over NVMe/TCP or SDC. Direct volume provisioning — one VM disk is one array volume — so array snapshots, thin clones, compression and replication all act on a single VM disk as their natural unit. 一個套件、一組共用的主機端底層,Dell EMC 每個產品系列各自對應一個 PVE storage type:PowerStore(iSCSI 或 Fibre Channel)、PowerVault ME4/ME5,以及 PowerFlex(NVMe/TCP 或 SDC)。採用直接配置 volume 的模型 —— 一顆 VM 磁碟就是一個儲存伺服器 volume —— 讓儲存伺服器端的快照、精簡複製、壓縮與複寫都以「一顆 VM 磁碟」為自然單位運作。

Disclaimer & Risk 免責聲明與風險

BETA SOFTWARE. Two arrays have run this. A PowerVault ME4024 over Fibre Channel boots guests, grows disks, backs up and restores, runs containers and survives a reboot. A PowerStore creates, maps and snapshots volumes, and runs guests off them. PowerFlex and Unity have never been connected to anything, PowerVault's iSCSI path has not been run, and SAS is not implemented. Use at your own risk. BETA 版軟體。目前有兩台儲存伺服器跑過它。一台走 Fibre Channel 的 PowerVault ME4024,已通過客體開機、磁碟擴充、備份與還原、容器,以及重開機。一台 PowerStore 則已能建立、對應與快照磁碟區,並且有客體實際跑在上面。PowerFlex 與 Unity 從未連上過任何東西,PowerVault 的 iSCSI 路徑沒有跑過,而 SAS 尚未實作。使用風險自負。
  • On every family except PowerVault-over-FC, the array-facing behaviour is unverified: REST endpoints and field names, the SCSI vendor and product strings that decide which devices the plugin touches, and the WWN to WWID conversion. The verification tables below name each item. 除了走 FC 的 PowerVault 之外,各系列面向儲存伺服器的行為都尚未驗證:REST 端點與欄位名稱、決定外掛會碰哪些裝置的 SCSI vendor/product 字串、以及 WWN 轉 WWID 的換算。下方的驗證表逐項列出。
  • A storage plugin runs as root, creates and deletes volumes on the array, and manipulates block devices on every node. A defect can destroy virtual machine data, take a storage offline, or leave a node in a state that only a reboot clears. 儲存外掛以 root 權限執行,會在儲存伺服器上建立與刪除 volume,並在每台節點上操作區塊裝置。缺陷可能毀掉虛擬機資料、讓儲存離線,或讓節點進入只能重開機才能恢復的狀態。
  • Multipath and SCSI state is shared across the whole node, so the damage is not necessarily limited to this plugin's own storage. multipath 與 SCSI 狀態是全節點共用的,因此受害範圍不一定只限於本外掛自己的儲存。
  • Provided under the MIT license, AS IS and without warranty of any kind. In no event shall the author be liable for any claim or damages, including data loss or business interruption. 以 MIT 授權提供,依現狀(AS IS)提供且不附帶任何形式的保固。在任何情況下,作者均不對任何主張或損害負責,包括資料遺失與營運中斷。
  • Use a non-production cluster and a non-production array, and keep independent backups. A storage snapshot is not a backup. 請使用非正式環境的叢集與儲存伺服器,並保留獨立備份。儲存快照不是備份。
  • An independent community project. Not affiliated with, endorsed by, or supported by Dell Technologies. "Dell", "Dell EMC", "PowerStore", "PowerVault", "PowerFlex", "Unity", "PowerMax" and "PowerScale" are trademarks of their respective owners. 本專案為獨立的社群專案,與 Dell Technologies 無隸屬關係,亦未經其背書或提供支援。「Dell」、「Dell EMC」、「PowerStore」、「PowerVault」、「PowerFlex」、「Unity」、「PowerMax」、「PowerScale」為各自所有權人之商標。

1.0.0 is the on-hardware test pass, not more code. What has and has not been verified is tracked in docs/TESTING.md. 1.0.0 的門檻是實機測試通過,而不是再寫更多程式。哪些已驗證、哪些還沒,記錄在 docs/TESTING_zh-TW.md。

Product Families 產品系列

Dell EMC's product lines differ too much to share one PVE storage type, so each family gets its own. They share the host-side layer, so adding a family is a plugin file and an API client rather than a restructuring. Dell EMC 各產品線的差異太大,無法共用同一個 PVE storage type,因此每個系列各自對應一個。它們共用主機端底層,所以新增一個系列只需要一個 plugin 檔加一個 API 客戶端,不必重構。

Family系列 Storage typeStorage type Data path資料路徑 Status狀態
PowerStore dellpowerstore iSCSI / FC (dm-multipath) Implemented已實作
PowerVault ME4 / ME5 dellpowervault iSCSI / FC (dm-multipath) Verified on an ME4024 over FC已在 ME4024 以 FC 驗證
PowerFlex dellpowerflex NVMe/TCP or SDC Implemented已實作
PowerMax dellpowermax FC / iSCSI, NVMe/FC, NVMe/TCP Planned規劃中
PowerScale dellpowerscale NFS Not scheduled未排入
Unity XT dellunity FC / iSCSI Code complete, no hardware run程式碼完成,尚無實機執行
ObjectScale, PowerProtect — — Out of scope不列入範圍

Why not one plugin with a type option: PVE asks a plugin for its content types and disk formats before any configuration is parsed, so one type cannot describe families that differ in what they can hold. The type string is also a permanent contract — changing it later invalidates every existing storage.cfg. 為什麼不做成單一 plugin 加型號參數:PVE 會在解析任何設定之前就向 plugin 詢問支援的 content type 與磁碟格式,因此單一 type 無法描述「能放的東西不同」的系列。而且 type 字串一旦公開就不能再改 —— 日後修改會讓所有既有的 storage.cfg 失效。

Features 功能特性

1 VM disk = 1 array volume 1 顆 VM 磁碟 = 1 個儲存伺服器 volume
No LVM layer and no shared large LUN carved up locally. The array's snapshots, thin clones, compression and replication act on a single VM disk as their natural unit. 沒有 LVM 層,也不會切一顆大 LUN 再在本地分割。儲存伺服器的快照、精簡複製、壓縮與複寫都以一顆 VM 磁碟為自然單位運作。
Snapshots keep the VM configuration 快照連同 VM 設定一起保存
A storage snapshot restores the disk; the configuration lives in /etc/pve. On PowerStore, every snapshot also writes the VM config to a 1 MB volume, readable back by pve-dell-config-get even when /etc/pve is gone. Not offered on PowerVault ME, whose volume ceiling is too low to spend one volume per snapshot; set dell-config-backup 0 to turn it off on PowerStore too. 儲存快照只還原磁碟,設定放在 /etc/pve。因此在 PowerStore 上,每次快照都會另外把 VM 設定寫進一個 1 MB 的 volume,即使 /etc/pve 已不存在,也能用 pve-dell-config-get 讀回來。PowerVault ME 系列不提供此功能,因為它的 volume 數量上限太少,無法為每個快照再多花一個 volume;在 PowerStore 上也可以用 dell-config-backup 0 關閉。
Instant linked clones 即時連結複製
Templates and linked clones use the array's thin clone or writable snapshot, so nothing is copied. Full Clone remains a PVE-side block copy — a PVE architectural decision, not a plugin limitation. 範本與連結複製使用儲存伺服器的精簡複製或可寫快照,完全不複製資料。完整複製仍是 PVE 端的逐區塊複製 —— 那是 PVE 的架構決策,不是外掛的限制。
Ownership boundary 歸屬邊界
Every list, delete and cleanup path filters on the pve-<storeid>- name prefix first. Objects on the array that do not carry it are never read, renamed or deleted. 所有列舉、刪除與清理路徑都會先以 pve-<storeid>- 名稱前置字串過濾。儲存伺服器上沒有這個前置字串的物件,一律不讀取、不改名、不刪除。
Cluster-aware mapping 叢集感知的對應
Volumes are mapped to every node at creation, so live migration does not have to remap first. Unmapping always precedes deletion, so an in-flight rescan cannot rebuild the device behind the delete. volume 在建立時就對應到所有節點,讓線上遷移不必先重新對應。解除對應一律在刪除之前,避免進行中的重新掃描在刪除的背後又把裝置建回來。
Orphan device reaping 殘留裝置自動清理
A volume deleted from another node leaves this one with a device pointing at storage that no longer answers. It is removed only after a grace period, three consecutive absences and an idle check — reaping a device in use destroys a running VM's disk. 從其他節點刪除的 volume,會在本節點留下一個指向已不存在儲存的裝置。它只會在通過寬限期、連續三次未出現、且裝置閒置之後才被移除 —— 清掉使用中的裝置等於毀掉執行中 VM 的磁碟。

Which Proxmox VE operations work 支援的 Proxmox VE 操作

The right-hand column says where each row has actually been driven. “Code” means it is implemented and covered by tests, and no array has run it — which is most of this table, and the reason this is beta software. 最右欄寫的是每一列實際跑過的地方。「僅程式」表示已實作、有測試涵蓋,但沒有任何儲存伺服器跑過 — 本表大多數列都是如此,這也是本軟體仍為 beta 的原因。

Operation操作 VM虛擬機 Container容器 Driven on實際跑過
Create and remove a disk建立、移除磁碟 ✓✓ ME4024, FCME4024,FC
Boot a guest from an array volume客體從儲存伺服器磁碟區開機 ✓✓ ME4024, FCME4024,FC
Grow a disk擴充磁碟
The array grows the volume, then this node’s paths and multipath map are refreshed until they report the new size. Other nodes catch up when they next activate the volume.先由儲存伺服器擴充磁碟區,接著重新整理本節點的路徑與 multipath map,直到它們回報新的大小。其他節點會在下次啟用該磁碟區時跟上。
✓✓ ME4024, FC (VM stopped)ME4024,FC(VM 已停)
Shrink a disk縮小磁碟 refused拒絕 refused拒絕 ME4024, FCME4024,FC
Snapshot, list, delete快照建立、列出、刪除 ✓✓ ME4024, FCME4024,FC
Rollback快照倒回
Refused while a newer snapshot exists, because the array would discard it. A container’s filesystem is frozen first; a backup snapshot is taken and kept until the rollback succeeds.有更新的快照存在時會拒絕,因為儲存伺服器會把它丟掉。容器的檔案系統會先凍結;倒回前會先取一份備份快照,直到倒回成功才移除。
✓✓ ME4024, FC (container)ME4024,FC(容器)
Template and linked clone範本與連結複製
A linked clone is a thin clone on the array. Deleting a template while a clone still reads from it is refused by the array, and reported as such.連結複製在儲存伺服器上是一個精簡複製。複製還在讀取時刪除範本,儲存伺服器會拒絕,外掛也照實回報。
✓✓ Code僅程式
Clone from a snapshot從快照複製 ✓✓ Code僅程式
Backup and restore (vzdump snapshot mode)備份與還原(vzdump snapshot 模式)
The backup reads through a temporary clone of the snapshot, which is removed afterwards.備份是透過該快照的一個臨時複製去讀取,結束後移除。
✓✓ ME4024, FCME4024,FC
Live migration線上遷移
The volume stays mapped: unmapping on migration is what breaks it. The target maps the volume itself if it does not already have it.磁碟區保持對應狀態:遷移時解除對應正是會弄壞它的做法。目標節點若尚未擁有該對應,會自行建立。
✓ offline離線 Code僅程式
Move a disk to another storage把磁碟移到其他儲存 ✓✓ Code僅程式
pvesm export / import, cluster-to-cluster migrationpvesm export/import、叢集對叢集移轉 ✓✓ Code僅程式
EFI disk, TPM state, cloud-initEFI 磁碟、TPM 狀態、cloud-init ✓— Code僅程式
Node reboot, storage returns on its own節點重開機後儲存自動回來 ✓✓ ME4024, FCME4024,FC
Rename a snapshot重新命名快照
Refused with a message that says why: a snapshot name is part of the array object’s name here.會拒絕並說明原因:在這裡,快照名稱是儲存伺服器物件名稱的一部分。
refused拒絕 refused拒絕 Code僅程式

Why this plugin has to be verified on hardware 為什麼這個外掛需要實機驗證

Dell publishes documentation for all four families, and it is not enough. The documentation site refuses the pages that carry the collection-query syntax; a printed column heading is not a property name; and two firmware generations of the same array document the same command with its arguments in a different order. So every array-facing fact here was cross-checked against Dell’s own client code — python-powerstore, python-powerflex, gounity, the ansible collections — and where those disagreed with the prose, the code won. Dell 四個系列都有公開文件,而那並不足夠。文件網站會拒絕提供帶有集合查詢語法的頁面;指令印出的欄位標題不等於屬性名稱;同一台儲存伺服器的兩個韌體世代,還會把同一個指令的參數順序記載成不同的樣子。所以這裡每一項面向儲存伺服器的認知,都與 Dell 自己的客戶端程式碼交叉比對過 — python-powerstore、python-powerflex、gounity、ansible collections — 兩者不一致時,以程式碼為準。

It still is not enough. The first run on a real ME4024 found three defects in a row, each hidden by the one before it, and none of them reachable by reading. The first run on a real PowerStore found four more, starting with a WWPN written without colons. That is what this table is for: a row that says “Code” means nobody has been able to be wrong about it yet. 而這樣仍然不夠。在真正的 ME4024 上第一次執行,一口氣找出三個缺陷,每一個都被前一個遮住,而且沒有一個是用讀的能找到的。在真正的 PowerStore 上第一次執行,又找出四個,第一個是沒有冒號的 WWPN。上面那張表就是為此存在的:標示「僅程式」的那一列,代表還沒有人有機會在它上面犯錯。

Where nothing could be established, this plugin refuses the operation rather than guessing at it. A refusal that names what it could not establish is recoverable; a guess that deletes the wrong volume is not. 凡是無法確立的地方,這個外掛會拒絕該操作,而不是用猜的。一個說得出「什麼無法確立」的拒絕是可以挽回的;一個刪錯磁碟區的猜測不是。

How to help this project 如何協助這個專案

What this project needs is not code. It is time on other people’s arrays: one PowerVault ME4024 over Fibre Channel has run it, and one PowerStore is running it now. PowerFlex and Unity XT have never been connected to anything. 這個專案缺的不是程式,是在別人儲存伺服器上的時間:目前有一台走 Fibre Channel 的 PowerVault ME4024 跑過,另有一台 PowerStore 正在跑。PowerFlex 與 Unity XT 從來沒有連上過任何東西。

  • Run it against a non-production array. docs/FIRST_RUN.md is nine steps and stops before anything is created if the array does not answer as expected. 拿一台非正式環境的儲存伺服器跑跑看。docs/FIRST_RUN.md 有九個步驟,而且只要儲存伺服器的回應不如預期,它會在建立任何東西之前停下來。
  • Report what broke. The useful details are the model and firmware, the protocol, what you were doing, and the error exactly as it appeared — including the array’s own message, which is usually the part that names the real cause. 回報壞在哪裡。有用的細節是機型與韌體、使用的協定、當時在做什麼,以及錯誤訊息原本的樣子 — 包含儲存伺服器自己那一段,通常真正的原因就寫在那裡。
  • Three things only an array can answer, and they take minutes: sg_inq /dev/sdX on a mapped volume, whether the WWID this plugin reports matches multipath -ll, and whether a qm rollback leaves the expected snapshot on the array. 有三件事只有儲存伺服器答得出來,而且幾分鐘就好:對已對應的磁碟區跑 sg_inq /dev/sdX、外掛回報的 WWID 是否與 multipath -ll 一致,以及 qm rollback 之後儲存伺服器上是否留下預期的快照。

Issues and reports: github.com/jasoncheng7115/jt-pve-storage-dellemc/issues 問題回報:github.com/jasoncheng7115/jt-pve-storage-dellemc/issues

Requirements 系統需求

Proxmox VE

PVE VersionPVE 版本 Storage API Compatibility相容性
PVE 9.1+13–15, negotiated13–15,自動協商 Supported — the ME4024 run was on PVE 9.2.5 (APIVER 15)支援 — ME4024 的實測就在 PVE 9.2.5(APIVER 15)上
PVE 9.012 Untested未測試
PVE 8.x10–11 Not supported不支援

Arrays 儲存伺服器

Family系列 Version版本 Management interface管理介面
PowerStorePowerStore OS 3.0+ (4.x targeted)REST API v3
PowerVault MEME4 / ME5CLI over HTTPSHTTPS 上的 CLI
PowerFlex3.x / 4.x (NVMe/TCP needs 4.0+)(NVMe/TCP 需 4.0 以上)REST API
Unity XTUnity OE 5.x targeted以 Unity OE 5.x 為目標Unisphere REST APIUnisphere REST API

Node packages 節點套件

Package套件 Purpose用途
libwww-perl, libjson-perl, liburi-perl REST clientREST 客戶端
open-iscsi iSCSI initiator (SAN families)iSCSI initiator(SAN 系列)
multipath-tools dm-multipath (SAN families)dm-multipath(SAN 系列)
sg3-utils, psmisc SCSI inquiry, in-use detectionSCSI 查詢、使用中偵測
nvme-cli PowerFlex over NVMe/TCPPowerFlex 走 NVMe/TCP 時需要

Installation 安裝

Install on every node of the cluster. A node without the package answers "Parameter verification failed (400)" or "No such storage", and cannot be a live migration target. 叢集內每一台節點都必須安裝。沒有安裝的節點會回應「Parameter verification failed (400)」或「No such storage」,也無法成為線上遷移的目的地。
1
Download the release package 下載發行版套件

Every release carries a prebuilt .deb and a SHA256SUMS beside it. This is the package to install; it is the same build that was tested for that release. 每個 release 都附有預先建置的 .deb 與 SHA256SUMS。請安裝這一份 —— 它就是該版本測試時所用的建置。

# always the newest build; this URL never has to be edited
curl -LO https://github.com/jasoncheng7115/jt-pve-storage-dellemc/releases/latest/download/jt-pve-storage-dellemc_all.deb
curl -LO https://github.com/jasoncheng7115/jt-pve-storage-dellemc/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing # must say OK before installing

# which version did that fetch?
dpkg-deb -f jt-pve-storage-dellemc_all.deb Version

Check the sum before installing: this package writes to /etc/multipath/conf.d and talks to your array. 安裝前先核對雜湊值:這個套件會寫入 /etc/multipath/conf.d,也會與你的儲存伺服器通訊。

The version is inside the package, not in that file name, so the command above never goes stale. Each release also carries a versioned copy — ..._0.7.66.beta1-1_all.deb, spelled with a dot because GitHub will not serve an asset name containing ~ — and that is the name to quote in a bug report. SHA256SUMS lists both, which is why the check above passes --ignore-missing. 版本在套件裡面,不在那個檔名上,所以上面那道指令永遠不會過期。每一版同時也附一份帶版號的副本 — ..._0.7.66.beta1-1_all.deb,版本用點分隔是因為 GitHub 不會提供檔名含 ~ 的附件 — 回報問題時請引用那個檔名。SHA256SUMS 兩份都列,這就是上面要加 --ignore-missing 的原因。

2
Install on every node 在每台節點上安裝
apt install ./jt-pve-storage-dellemc_all.deb

Use apt install ./file.deb rather than dpkg -i: dpkg does not install dependencies, and the missing binaries only surface much later as failures inside the plugin. 請用 apt install ./file.deb 而不是 dpkg -i:dpkg 不會安裝相依套件,缺少的執行檔要到很後面才會以外掛內部的錯誤浮現。

3
After an upgrade 升級之後
systemctl restart pvestatd

A reload does not reliably replace Perl modules that are already loaded. Run this on every node. reload 無法可靠地替換已載入記憶體的 Perl 模組。請在每台節點上執行。

Building from source 從原始碼建置

Only needed to work on the plugin, or to run the test suite against your own PVE version. For installing it, use the release package above — that is the build the release was tested with. 只有在要修改這個外掛、或想針對你自己的 PVE 版本跑測試套件時才需要。單純安裝請用上面的發行版套件 — 那才是該版本測試時所用的建置。

git clone https://github.com/jasoncheng7115/jt-pve-storage-dellemc.git
cd jt-pve-storage-dellemc
make test    # syntax checks, unit tests, safety guard
make deb

Upgrading 升級

Volumes created by an older version keep working, and nothing needs doing. Every name the plugin creates begins with a prefix, which is pve unless a storage sets dell-name-prefix — and that is the literal the plugin used before the option existed. A storage that has never set it produces byte-identical names after an upgrade, so every volume already on the array stays recognised. 由舊版建立的磁碟區會繼續正常運作,而且什麼都不用做。外掛建立的每一個名稱都以一個前置字串開頭,除非該 storage 設定了 dell-name-prefix,否則就是 pve — 而那正是這個選項存在之前外掛寫死的那個字串。從未設定過它的 storage,升級後會產生逐位元組相同的名稱,因此儲存伺服器上既有的每一個磁碟區都仍然被認得。

Object created by an older version由舊版建立的物件 Still recognised是否仍被認得
pve-ps1-100-disk0yes, as a VM disk是,視為 VM 磁碟
pve-ps1-100-efidisk0, -tpmstate0, -cloudinityes是
pve-ps1-100-vmconf-beforeyes, as a config backup是,視為設定備份
pve-ps1-100-disk0.pve-snap-beforeyes, as a snapshot是,視為快照
pve-ps1-100-disk0.pve-baseyes, as a template marker是,視為範本標記

Nothing acts on old volumes unattended. The orphan reaper touches only the node’s own devices and never deletes an array volume; the temporary-clone reaper works from a state file this plugin wrote, which old volumes are not in; and per-VM volume groups are off by default and never add existing volumes retroactively. 沒有任何路徑會在無人值守的情況下動到舊磁碟區。孤兒回收器只處理節點自己的裝置,從不刪除儲存伺服器上的磁碟區;暫時複製回收器依據的是外掛自己寫下的狀態檔,而舊磁碟區不在其中;每 VM 一個 volume group 預設關閉,也不會把既有磁碟區追溯加入群組。

Two things that do change, and both are fixes有兩件事確實會改變,而兩者都是修正

  • A multipath map may be built on first use. Older versions could accept a single /dev/sdX and leave the guest with no failover. From 0.8.28 the WWID is claimed and the map is waited for, so multipath -a appearing in the journal for an existing volume is expected. 第一次使用時可能會建立 multipath map。舊版可能接受單一的 /dev/sdX,讓客體沒有任何路徑備援。從 0.8.28 起會認領 WWID 並等待 map 出現,因此在日誌中看到對既有磁碟區執行 multipath -a,是預期的。
  • Adding an existing storage warns that volumes already exist under its prefix. That is the cross-cluster check; for a storage you are re-adding it is expected, and the message says so. 加入既有 storage 時會警告該前綴下已經有磁碟區。那是跨叢集檢查;對於你自己重新加入的 storage,這是預期的,訊息裡也寫明了這種讀法。
Do not set dell-name-prefix on a storage that already has volumes. It would leave the plugin unable to find any of them. pvesm set refuses it for that reason: the prefix can only be chosen when the storage is created. 不要對已經有磁碟區的 storage 設定 dell-name-prefix。那會讓外掛再也找不到它們。pvesm set 正是因此會拒絕:前置字串只能在建立 storage 時決定。

Quick Start 快速入門

PowerStore

pvesm add dellpowerstore ps1 \
    --dell-portal 192.168.1.50 \
    --dell-username pveadmin \
    --dell-password 'SecurePassword' \
    --dell-protocol iscsi \
    --content images,rootdir \
    --shared 1

PowerVault ME4 / ME5

pvesm add dellpowervault me5 \
    --dell-portal 192.168.1.60,192.168.1.61 \
    --dell-username manage \
    --dell-password 'SecurePassword' \
    --pvault-pool A \
    --content images,rootdir \
    --shared 1
Why two addresses? An ME has no virtual management IP: controller A and B each keep their own, and a failed controller's address disappears with it. List both at creation time — dell-portal cannot be edited afterwards, and during an incident it is too late. Verify the pair on the array with show network-parameters. 為什麼要填兩個位址? ME 沒有虛擬管理 IP:控制器 A 與 B 各自持有位址,故障控制器的位址會跟著它一起消失。請在建立時就把兩個都列入 — dell-portal 事後不能修改,事故當下才想改就來不及了。可在儲存伺服器上以 show network-parameters 確認這兩個位址。
PowerVault names are limited to 32 bytes, so keep the storage id short. A name that would not fit raises an error rather than being truncated into a collision. PowerVault 的名稱上限是 32 bytes,所以 storage id 請取短一點。放不下的名稱會直接報錯,而不是被截斷成可能撞名的名稱。

PowerFlex

pvesm add dellpowerflex pflex1 \
    --dell-portal 192.168.1.70 \
    --dell-username admin \
    --dell-password 'SecurePassword' \
    --dell-protocol nvme \
    --pflex-storage-pool pool1 \
    --content images,rootdir \
    --shared 1

Unity XT

pvesm add dellunity u480 \
    --dell-portal 192.168.1.80 \
    --dell-username admin \
    --dell-password 'SecurePassword' \
    --dell-protocol fc \
    --unity-pool pool_1 \
    --content images,rootdir \
    --shared 1
Unity's management IP follows the master SP, so one address is enough. --unity-pool is required on an array with more than one pool. This family has never run against an array — see the verification section below. Unity 的管理 IP 會跟著主 SP 走,填一個位址即可。儲存伺服器有多個儲存池時 --unity-pool 為必填。這個系列從未在儲存伺服器上執行過 —— 請見下方驗證狀態。

Verify 驗證

pvesm status
journalctl -t pvestatd | grep dellpowerstore

Configuration 設定選項

Options shared by every family use the dell- prefix and are declared once; family options use their own prefix. PVE registers storage properties in one shared schema, so a name may only have one definition across all plugins. 所有系列共用的選項使用 dell- 前置字串且只宣告一次;各系列專屬選項使用自己的前置字串。PVE 的 storage property 註冊在同一份共用 schema,同一個名稱在所有外掛之間只能有一種定義。

Common options 共通選項

Option選項 Default預設 Description說明
dell-portal— Management address(es), comma-separated. Required, cannot be changed later. PowerVault ME has one fixed IP per controller and no floating address — unlike a NetApp cluster LIF or a Pure vir0, nothing moves to the surviving controller — so list both controllers up front; the plugin fails over between them. The data path needs none of this: dm-multipath handles controller failover on its own 管理位址(可逗號分隔多個)。必填,且建立後不可變更。PowerVault ME 每個控制器各有固定 IP、沒有浮動位址 — 不像 NetApp 的 cluster LIF 或 Pure 的 vir0,故障時不會有位址漂移到存活的控制器 — 所以請一開始就把兩個控制器都列入,外掛會在其間自動容錯。資料路徑完全不需要這些:dm-multipath 自己處理控制器容錯
dell-username— API user. RequiredAPI 帳號。必填
dell-password— API password. RequiredAPI 密碼。必填
dell-protocoliscsi iscsi or fc on the SAN families; sdc or nvme on PowerFlex SAN 系列為 iscsi 或 fc;PowerFlex 為 sdc 或 nvme
dell-host-modeper-node One host object per node, or one for the cluster 每節點一個 host 物件,或整個叢集共用一個
dell-status-timeout5 Health-path timeout. PVE polls storages sequentially, so a slow array delays every storage after it 健康路徑逾時。PVE 依序輪詢儲存,因此慢的儲存伺服器會拖累排在後面的每一個儲存
dell-device-timeout60 Seconds to wait for a volume's device 等待 volume 裝置出現的秒數
dell-rescan-interval300 Rate limit for the periodic SAN rescan. A new portal login always rescans immediately 週期性 SAN 掃描的頻率限制。登入新 portal 時一律立即掃描

Family options 系列專屬選項

Family系列 Options選項
PowerStorepstore-appliance, pstore-volume-group, pstore-performance-policy, pstore-protection-policy, pstore-lun-id-base
PowerVault MEpvault-pool, pvault-volume-group, pvault-tier-affinity, pvault-lun-id-base
PowerFlexpflex-storage-pool (required)(必填), pflex-protection-domain, pflex-thick
Unity XTunity-pool, unity-thin

Full reference: docs/CONFIGURATION.md. 完整說明:docs/CONFIGURATION_zh-TW.md。

Host objects the array already has 儲存伺服器上原本就有的 host 物件

An array usually has a host object for each node before this plugin ever runs — built by whoever zoned the fabric — holding that node’s WWPNs or IQN under a name of its own. An initiator belongs to one host object, so the plugin cannot register the same ports a second time under its own name. 在這個外掛跑起來之前,儲存伺服器上通常每台節點都已經有一個 host 物件 — 由當初做 fabric 分區的人建立 — 以它自己的命名持有該節點的 WWPN 或 IQN。一個 initiator 只能屬於一個 host 物件,所以外掛沒辦法用自己的名稱把同樣的埠再註冊一次。

On PowerStore it does not try. When there is no host under pve-<cluster>-<node>, it asks the array which host holds this node’s initiators and uses that one, recording the name in /var/lib/pve-storage-dellemc/<storeid>-host. Nothing is renamed, nothing is removed, and no initiator is moved. 在 PowerStore 上它不會去試。當 pve-<叢集>-<節點> 底下沒有 host 時,它會問儲存伺服器「本節點的 initiator 在哪個 host 上」,改用那一個,並把名稱記在 /var/lib/pve-storage-dellemc/<storeid>-host。不改名、不刪除,也不搬動任何 initiator。

It adopts only a host whose initiators are a subset of this node’s. One that also carries another host’s ports is refused, by name: a volume mapped there would be visible to whatever those belong to. Ports split across two host objects are refused as well — a node is one host object, and merging them is the operator’s call. 它只會採用 initiator 是本節點子集的 host。若那個 host 同時持有別台的埠,就會被拒絕並指名是哪一個:對應到它的磁碟區會被那些東西看見。本節點的埠散在兩個 host 物件上也一樣拒絕 — 一個節點就是一個 host 物件,要合併是操作者的決定。

System Architecture 系統架構

DellPowerStorePlugin / DellPowerVaultPlugin      # SAN families
        |
        v
DellEMC::Common::BlockBase           # activation, allocation, device
        |                            # discovery, snapshots, clones,
        |                            # multipath drop-in, orphan reaper
        +-- Common::REST             # retries, timeouts, sessions
        +-- Common::ISCSI            # initiator, portals, rescan
        +-- Common::FC               # HBA discovery, WWN handling
        +-- Common::Multipath        # SCSI lifecycle, dm-multipath
        +-- Common::Naming           # PVE names <-> array objects
        +-- Common::WwidState        # WWID tracking, reap guards
        +-- Common::Health           # outage and capacity reporting
        +-- Common::Schema           # the shared dell-* options

DellPowerFlexPlugin                  # no SCSI LUN, no multipath
        +-- PowerFlex::Host          # SDC or NVMe/TCP device access

Why the plugin is careful about the host 為什麼外掛在主機端如此謹慎

Failure mode故障模式 What the plugin does about it外掛的因應
Uninterruptible sleep (D state)不可中斷睡眠(D state) Reading an unresponsive device puts a process into a state no signal clears. Every sysfs access runs in a forked, timeout-bounded child; every command under an alarm. 讀取沒有回應的裝置會讓行程進入任何訊號都無法清除的狀態。所有 sysfs 存取都在有逾時限制的子行程中進行,所有外部指令都有 alarm 保護。
Blast radius影響範圍 The system-wide multipath flush is never issued, and neither is an FC LIP. Destructive operations are vendor-gated and act on one object at a time. 絕不執行全系統的 multipath flush,也不發 FC LIP。具破壞性的操作都有 vendor 過濾,且一次只處理一個物件。
The sequential poll依序輪詢 PVE polls storages one after another, so a slow array starves its neighbours. The health path uses a short timeout and a single attempt; expensive periodic work is rate-limited and detached. PVE 一個接一個輪詢儲存,慢的儲存伺服器會餓死鄰居。健康路徑採短逾時且只嘗試一次;昂貴的週期性工作有頻率限制並丟到背景執行。

PowerFlex: SDC vs NVMe/TCP PowerFlex:SDC 與 NVMe/TCP

PowerFlex volumes do not arrive as SCSI LUNs. There are two ways a node can see them, and the choice outlives this plugin. PowerFlex 的 volume 不是以 SCSI LUN 出現。節點有兩種方式看到它們,而這個選擇的影響會比這個外掛活得更久。

SDC NVMe/TCP
Host component主機端元件 Dell's scini kernel moduleDell 的 scini kernel module in-kernel nvme_tcpkernel 內建的 nvme_tcp
PowerFlex versionPowerFlex 版本 3.x / 4.x 4.0+ (needs SDT)4.0 以上(需要 SDT)
Devices裝置 /dev/disk/by-id/emc-vol-* /dev/nvme*n*
Survives a kernel upgradekernel 升級後仍可用 only if the module rebuilds只有模組成功重建時 yes是
Installed by this plugin由本外掛安裝 no否 nothing to install無需安裝
What Dell says about the SDC on Proxmox VE Dell 對「在 Proxmox VE 上使用 SDC」的說法
  • Dell ships the packages and documents the procedure. KB 000462918 covers installing the SDC on “Debian and Ubuntu operating systems, including Proxmox Virtual Environment”, names Debian 12 / Proxmox VE 8.x directly, and the SDC tarball contains a Debian13_SDC variant — Debian 13 is what Proxmox VE 9 is built on. PowerFlex 5.1.x documentation is published. Dell 有提供套件,也有寫操作步驟。KB 000462918 說明如何在「Debian 與 Ubuntu 作業系統,包含 Proxmox Virtual Environment」上安裝 SDC,並直接點名 Debian 12/Proxmox VE 8.x;SDC 的 tarball 裡也包含 Debian13_SDC 變體 —— Debian 13 正是 Proxmox VE 9 的基底。PowerFlex 5.1.x 的文件也已發布。
  • Proxmox VE is not in the official OS support matrix. KB 000272738 lists Ubuntu LTS, RHEL, Oracle Linux, SLES, CentOS and AIX. Debian is not there, and neither is Proxmox VE, at any PowerFlex version. 但 Proxmox VE 並不在官方的作業系統支援矩陣裡。KB 000272738 列出的是 Ubuntu LTS、RHEL、Oracle Linux、SLES、CentOS 與 AIX。Debian 不在其中,Proxmox VE 也不在,任何 PowerFlex 版本皆然。
  • So the SDC here is something Dell publishes instructions for, not something its support matrix commits to. What that means for a support case is a question for your Dell account team. Separately: Dell ships no prebuilt scini for the Proxmox kernel, so it is compiled on the node and a kernel upgrade can leave that node with no storage until it rebuilds. That is why dell-protocol nvme is the default. 也就是說,在這裡使用 SDC 是 Dell 有發布安裝說明的事,但不是它的支援矩陣所承諾的事。這對一張支援案件單代表什麼,是要問您的 Dell 業務窗口的問題。另外一件事:Dell 未為 Proxmox kernel 提供預編譯的 scini,必須在節點上編譯,因此一次 kernel 升級就可能讓該節點在模組重建之前沒有儲存。這就是 dell-protocol nvme 是預設值的原因。
  • Checked 2026-07-27. Both KBs change; read them rather than trusting this page. 查證日期 2026-07-27。兩份 KB 都會變動,請以它們為準,不要相信這一頁。

Official Dell references Dell 官方資料

Bookmark these; they are the authority on what is supported, and they change. 請加入書籤;支援範圍以它們為準,而且內容會變動。

What內容 Link連結
SDC on Proxmox VE在 Proxmox VE 上設定 SDC KB 000466868
Support matrix (OS and kernels)支援矩陣(OS 與 kernel) E-Lab Navigator: PowerFlex_OS.pdf
Is my kernel supported?我的 kernel 有支援嗎? KB 000332118
On-demand driver compilation驅動程式隨選編譯 KB 000224134
Prebuilt .ko files by OS and version依 OS 與版本分類的預編譯 .ko mft.dell.com
NVMe/TCP overviewNVMe/TCP 概觀 PowerFlex 4.5.x Technical Overview

Dell notes that the E-Lab matrix does not always list every kernel a distribution has released, and gives a prefix rule: a kernel is supported if its version prefix matches a listed one — 4.18.0-553 covers 4.18.0-553.51.1.el8_10.x86_64. Details and the commands to check a node are in docs/POWERFLEX_SDC.md. Dell 也說明 E-Lab 矩陣不一定涵蓋各發行版釋出的每一個 kernel,並給了一條前置字串規則:版本前置字串相符即視為支援 —— 4.18.0-553 涵蓋 4.18.0-553.51.1.el8_10.x86_64。細節與節點檢查指令請見 docs/POWERFLEX_SDC_zh-TW.md。

Whichever path is used, one VM disk is one PowerFlex volume created through the REST API. There is no LVM layer and no shared volume carved up locally — the SDC or the NVMe initiator only presents that volume as a block device. 無論使用哪一條路徑,一顆 VM 磁碟就是一個透過 REST API 建立的 PowerFlex volume。中間沒有 LVM 層,也不會切一顆大 volume 再在本地分割 —— SDC 或 NVMe initiator 只負責把那個 volume 呈現成區塊裝置。

Multipath Safety Multipath 安全規則

These rules are not stylistic. Breaking any of them can take a whole node out of service, including storage that has nothing to do with this plugin. 以下規則不是風格偏好。違反任何一條都可能讓整台節點失去服務能力,包括與本外掛完全無關的其他儲存。
Rule規則 Why原因
Never run the system-wide multipath flush (capital F). Flush one map: multipath -f /dev/mapper/<wwid> 絕不執行全系統的 multipath flush(大寫 F)。只清單一 map:multipath -f /dev/mapper/<wwid> It removes every unused map on the node, including other vendors' storage that happens to be idle. The build fails if that form appears anywhere in this repository. 它會清掉節點上所有未使用的 map,包含當下剛好閒置的其他廠商儲存。只要該指令出現在本專案任何檔案中,建置就會失敗。
Use systemctl restart multipathd, never reload 用 systemctl restart multipathd,不要用 reload Reload only re-reads the file; restart is what reapplies device-mapper state. reload 只會重讀檔案,restart 才會重新套用 device-mapper 狀態。
Avoid no_path_retry queue and dev_loss_tmo infinity 避免 no_path_retry queue 與 dev_loss_tmo infinity With every path down, queued I/O that can never complete puts processes into uninterruptible sleep and the node has to be power-cycled. Use 30 / 5 / 60. 所有路徑失效時,永遠無法完成的排隊 I/O 會讓行程進入不可中斷睡眠,該節點只能斷電重開。請用 30 / 5 / 60。
The plugin never rewrites a multipath file it did not create 外掛不會改寫非它建立的 multipath 設定檔 Its own drop-in carries a version marker; a file without one is treated as operator-owned and left untouched. 它自己的 drop-in 帶有版本標記;沒有標記的檔案視為管理者自有,完全不動。

Supported Features 功能支援表

Feature功能 PowerStore PowerVault ME PowerFlex Unity XT
VM disks and container root filesystemsVM 磁碟與容器根檔案系統✓
Snapshots快照✓
Snapshot rollback快照還原 ✓ — to the most recent snapshot; rolling back past newer ones is refused unless dell-rollback-any-snapshot 1✓ —— 僅限最新的快照;除非設定 dell-rollback-any-snapshot 1,否則會拒絕跨過較新快照的還原
Templates and linked clones範本與連結複製✓
Online grow線上擴充✓
Shrink縮小 Refused on all families — it would truncate the guest filesystem所有系列都拒絕 —— 會截斷客體的檔案系統
Live migration線上遷移✓
VM config backup volumeVM 設定備份卷 ✓ (optional)✓(可關閉) — (volume ceiling too low)—(volume 上限太少)— — (off until a hardware run)—(實機測試前先關閉)
Multipath I/O多路徑 I/Odm-multipathdm-multipath SDC or NVMe ANASDC 或 NVMe ANA dm-multipath
Orphan device reaping殘留裝置清理✓✓—✓
Full clone via the array儲存伺服器端完整複製 Not possible: PVE implements it as a qemu-img block copy and never calls the plugin無法做到:PVE 以 qemu-img 逐區塊複製實作,完全不呼叫外掛

Verification Status 驗證狀態

3,411 unit tests run without an array or a device. What they cannot tell you is whether the endpoints exist, whether the field names are right, or whether a device ever appears — only an array can, and exactly one has. 3,411 個單元測試不需要儲存伺服器或實體裝置即可執行。它們無法告訴你的是:端點是否存在、欄位名稱是否正確、裝置到底會不會出現 — 那隻有儲存伺服器能回答,而目前只有一台回答過。

What has run on hardware 哪些在實機上跑過

Family產品系列 Data path資料路徑 Hardware實機 On what在什麼上面
PowerVault ME4 / ME5 Fibre Channel full first-run pass完整首次執行通過 ME4024, firmware GT280R011-01, since 0.7.65ME4024,韌體 GT280R011-01,自 0.7.65 起
PowerVault ME4 / ME5 iSCSI not verified未驗證 the array above ran FC; this path shares the CLI client but not the data path上面那台走的是 FC;這條路徑共用 CLI 用戶端,但資料路徑不同
PowerStore iSCSI, FCiSCSI、FC partly verified部分驗證 create, map, device discovery, snapshot creation and guests running off it are confirmed on a customer's array. Snapshot deletion, rollback and migration between nodes are not. That array is on Fibre Channel, so iSCSI on PowerStore remains entirely unrun建立、對應、裝置探索、快照建立,以及客體實際跑在上面,都已在客戶的儲存伺服器上確認。快照刪除、倒回與節點間遷移則沒有。那台走的是 Fibre Channel,所以 PowerStore 上的 iSCSI 完全沒有跑過
PowerFlex NVMe/TCP, SDCNVMe/TCP、SDC not verified未驗證 never run against an array從未在任何儲存伺服器上執行過
Unity XT FC, iSCSIFC、iSCSI not verified未驗證 never run against an array; a customer's Unity 480 (FC) is the intended first. The transport has been driven over real HTTP against an API emulator, which proves shapes, not storage從未在任何儲存伺服器上執行過;預定的第一台是客戶的 Unity 480(FC)。傳輸層已對 API 模擬器以真實 HTTP 驗證 —— 那證明的是結構,不是儲存行為

The ME4024 run covered the whole of the first-run test: capacity agreeing with the array's own GUI, several allocations with LUNs in sequence, dm-multipath with two paths, dd read and write verified by checksum, snapshot, rollback, snapshot delete, template, a linked clone in seconds, the array correctly refusing to delete a template with a live clone, and unmap, delete and local device cleanup. It also found three defects that reading Dell's documentation had not — each hidden behind the one before it. 那次 ME4024 的測試涵蓋了整套首次執行測試:容量與儲存伺服器自己的 GUI 一致、連續數次配置且 LUN 依序遞增、dm-multipath 兩條路徑、以雜湊驗證的 dd 讀寫、快照、倒回、刪除快照、範本、秒級完成的連結複製、儲存伺服器正確拒絕刪除仍有存活複製的範本,以及解除對應、刪除與本機裝置清理。它同時找出三個讀 Dell 文件找不出來的缺陷 — 而且一個藏在另一個後面。

Where the rest came from 其餘的依據是什麼

Area項目 Source來源 Hardware實機
PowerVault CLI grammar, field names, mapping modelPowerVault CLI 語法、欄位名稱、對應模型 ME5 CLI Reference Guide, then corrected by the arrayME5 CLI Reference Guide,之後由儲存伺服器修正 verified已驗證
WWN to WWID, SCSI vendor / product stringsWWN 轉 WWID、SCSI vendor/product 字串 inferred推斷 verified on ME4 only僅在 ME4 上驗證
Fibre Channel pathFibre Channel 路徑 — verified on ME4 only僅在 ME4 上驗證
PowerStore REST endpoints and fieldsPowerStore REST 端點與欄位 PowerStore 4.x documentation and Dell's own SDK, audited key-for-key 2026-08-06: all eight request bodies matchPowerStore 4.x 文件與 Dell 自己的 SDK,2026-08-06 逐鍵稽核:八組請求內容全數相符 not verified未驗證
PowerFlex login, volume, mapping, snapshot APIPowerFlex 登入、磁碟區、對應、快照 API Dell's own python-powerflex, audited key-for-key; the 3.x rollback form alone remains documentation-onlyDell 自己的 python-powerflex,已逐鍵稽核;僅 3.x 的倒回寫法仍只有文件依據 not verified未驗證
Unity URIs, request bodies, field listsUnity 的 URI、請求內容、欄位清單 Dell's own gounity client and the Unisphere Programmer's Guide; multipath settings follow the kernel's own DGC entryDell 自己的 gounity 客戶端與 Unisphere Programmer's Guide;multipath 設定跟隨核心自己的 DGC 條目 not verified未驗證

The full matrix, including what came from official documentation and what did not, is in docs/TESTING.md. 完整矩陣(包含哪些來自官方文件、哪些不是)請見 docs/TESTING_zh-TW.md。

Before the first run against an array, work through docs/FIRST_RUN.md: the order to do it in, what to check after each step, and what each failure most likely means. 第一次接上儲存伺服器之前,請照著 docs/FIRST_RUN_zh-TW.md 走一遍:該用什麼順序做、每一步之後要看什麼,以及每種失敗最可能代表什麼。

Troubleshooting 疑難排解

Every message carries a [type:storeid] prefix, so one storage can be grepped out of a busy journal. 每一則訊息都帶有 [type:storeid] 前置字串,可以從繁忙的 journal 中過濾出單一儲存。

journalctl -t pvestatd -t pvedaemon | grep dellpowerstore
Symptom症狀 Most likely cause最可能的原因
Parameter verification failed (400) The package is not installed on that node. Install it everywhere. 該節點沒有安裝套件。請在每台節點安裝。
Storage shows inactive儲存顯示 inactive Credentials, the management network, or a slow array. If other storages went inactive at the same time, suspect this one was slow — PVE polls sequentially. 帳密、管理網路,或儲存伺服器太慢。若其他儲存同時變 inactive,請懷疑是這個儲存慢 —— PVE 是依序輪詢的。
New disks stop appearing新磁碟掃不到 On PowerStore, the REST-side LUN id sequence climbing past what the host scans. The plugin assigns LUN ids itself to avoid it. 在 PowerStore 上,是 REST 端的 LUN ID 序列爬過主機掃描範圍。外掛改為自行配發 LUN ID 以迴避。
Cannot delete: device still in use無法刪除:裝置仍在使用中 Usually host LVM having auto-activated a volume group that lives inside a guest disk. Deactivate it and add an LVM global_filter. 通常是主機端 LVM 自動啟用了客體磁碟內部的 volume group。請停用它並設定 LVM global_filter。
Processes stuck in D state行程卡在 D state Queued I/O to a device with no working path. Check for no_path_retry queue, then restart multipathd. 對沒有可用路徑的裝置持續排隊 I/O。請檢查 no_path_retry queue,然後 restart multipathd。

Full guide: docs/TROUBLESHOOTING.md. 完整指南:docs/TROUBLESHOOTING_zh-TW.md。

Changelog 變更紀錄

v0.8.31~beta1
2026-08-29
Documentation: what an upgrade does to volumes an older version created, which is nothing. A new Upgrading section here and in NAMING_CONVENTIONS lists every object kind an older version could have made and confirms each is still recognised, records what nothing touches them, and names the two things that do change — a multipath map built on first use, and the prefix warning when re-adding a storage. The prefix-isolation text also said every object is named pve-, which stopped being true in 0.8.29. 文件:升級對舊版建立的磁碟區有什麼影響 — 答案是沒有影響。這裡與 NAMING_CONVENTIONS 都新增了「升級」章節,列出舊版可能建立過的每一種物件並逐一確認仍被認得,記下有哪些機制不會動到它們,並指出確實會改變的兩件事:第一次使用時建立 multipath map,以及重新加入 storage 時的前綴警告。另外,「前綴隔離」原本寫著每個物件都以 pve- 命名,那在 0.8.29 之後已不成立。
v0.8.30~beta1
2026-08-27
The recovery tool did not know about dell-name-prefix, added one release earlier, so against a storage that sets it it would have found no backups at all — not an error, an empty listing, at the moment somebody is recovering a VM configuration. The third time that tool's deliberate independence from the plugin has left it behind. It reads the key now and takes --name-prefix when storage.cfg cannot be read. 復原工具不知道前一版才加入的 dell-name-prefix,所以對有設定它的 storage 會完全找不到備份 — 不是錯誤,是一份空清單,而且就發生在有人正要復原 VM 設定的時候。這是那個工具刻意與外掛保持獨立、因而脫隊的第三次。它現在會讀這個鍵,並在 storage.cfg 讀不到時接受 --name-prefix。
v0.8.29~beta1
2026-08-27
dell-name-prefix, the leading component of every name a storage creates on the array, defaulting to pve. For two Proxmox clusters sharing one array, where the namespace is otherwise the storage id. This is the shape Kubernetes CSI uses for the identical problem: a configured value, not one derived from the cluster name, because a derived name would have to be truncated and two clusters truncating alike would collide again. Upgrading changes no name. Requested by Alexander Gott (@alexandergott-afk), issue #4. 新增 dell-name-prefix,一個 storage 在儲存伺服器上建立的每個名稱的開頭元件,預設 pve。它是為了兩個 Proxmox 叢集共用同一台儲存伺服器的情境,否則命名空間就只有 storage id。這正是 Kubernetes CSI 對同一問題採用的形式:由操作者設定,而不是從叢集名稱推導 — 推導出來的名稱勢必要截斷,而兩個截斷後相同的叢集會再次撞名。升級不會改變任何名稱。由 Alexander Gott(@alexandergott-afk)在 issue #4 提出。
v0.8.28~beta1
2026-08-27
A live-migration target ran the guest on a single path: 0.8.26 claimed the WWID and then checked for the map immediately, but multipathd builds it asynchronously, so the check missed and the plugin settled for the bare sd path. It waits now, bounded, and only when there is no map at all. Reported by Alexander Gott (@alexandergott-afk), issue #7 — his reading was right. 線上遷移的目標節點會讓客體跑在單一路徑上:0.8.26 認領 WWID 之後立刻檢查 map,但 multipathd 是非同步建立它的,所以檢查落空,外掛就退回裸 sd 路徑。現在它會等待,有上限,而且只在完全沒有 map 時才等。由 Alexander Gott(@alexandergott-afk)在 issue #7 回報 — 他的判讀是對的。
v0.8.27~beta1
2026-08-26
Adding a storage now asks the array whether its volume-name prefix is already in use, and warns if it is: two Proxmox clusters on one array using the same storage id share a volume namespace, and the existing check cannot see another cluster. A warning, never a refusal, since re-adding a storage that already has volumes is legitimate. The prefix itself is deliberately not changed to carry the cluster name. Raised by Alexander Gott (@alexandergott-afk), issue #4. 加入儲存時會去問儲存伺服器「這個 storage 的磁碟區名稱字首是不是已經有人在用」,有的話就警告:兩個 Proxmox 叢集接到同一台儲存伺服器、又用同一個 storage id 時,會共用同一個命名空間,而既有的檢查看不到另一個叢集。這是警告而非拒絕,因為重新加入一個已有磁碟區的 storage 是正當的。字首本身刻意不改成帶叢集名稱。由 Alexander Gott(@alexandergott-afk)在 issue #4 提出。
v0.8.26~beta1
2026-08-26
A guest could run on a single path with no multipath map and no failover. activate_volume accepted a bare /dev/sdX from the by-id fallback and returned early, so the WWID was never claimed and no map was ever built — the LUN was live, the VM ran, and multipath -ll was empty. A map is now what qualifies for the fast path. Found from diagnostics posted by Alexander Gott (@alexandergott-afk), issue #7. 客體可能跑在單一路徑上,沒有 multipath map、也沒有備援。activate_volume 接受了 by-id 退路給出的裸 /dev/sdX 就提早返回,於是 WWID 永遠不會被認領、map 永遠不會建立 — LUN 是活的、虛擬機在跑,而 multipath -ll 是空的。現在能走快速路徑的必須是 map。這是從 Alexander Gott(@alexandergott-afk)在 issue #7 貼出的診斷資料查出來的。
v0.8.25~beta1
2026-08-26
A volume mapped through a host group could not be deleted: a group-level mapping row carries host_group_id and no host_id, so reading only host_id called the volume unmapped and nothing was detached. And the message for a refused delete asserted thin clones existed, because it matched the plugin's own 422 hint rather than the array's answer. The array's words are quoted now. Reported by Alexander Gott (@alexandergott-afk), issue #11. 透過 host group 對應的磁碟區刪不掉:群組層級的對應資料列只帶 host_group_id、沒有 host_id,所以只讀 host_id 會把磁碟區當成沒有對應,什麼也沒解除。而刪除被拒時的訊息會斷言有精簡複製存在,因為它比對到的是外掛自己附加的 422 提示,而不是儲存伺服器的回答。現在改為直接引用儲存伺服器的說法。由 Alexander Gott(@alexandergott-afk)在 issue #11 回報。
v0.8.24~beta1
2026-08-25
Creating a disk failed outright on any node whose host is in a PowerStore host group: the attach carried both host_id and host_group_id, which the array answers with HTTP 500 "Volume internal error" rather than a 422, so it read as an array fault. Attach and detach now share one helper that can name only one of the two. Present since 0.8.10 and affecting every host mode, not only the host-group mode added in 0.8.23. Reported by Alexander Gott (@alexandergott-afk), issue #11 — thank you. 只要節點的 host 屬於某個 PowerStore host group,建立磁碟就會直接失敗:attach 同時帶了 host_id 與 host_group_id,而儲存伺服器對此回應的是 HTTP 500「Volume internal error」而不是 422,於是看起來像儲存伺服器故障。現在 attach 與 detach 共用同一個輔助函式,它只可能指名兩者之一。這個問題自 0.8.10 就存在,影響每一種 host 模式,不只是 0.8.23 新增的 host-group 模式。由 Alexander Gott(@alexandergott-afk)在 issue #11 回報 — 在此致謝。
v0.8.23~beta1
2026-08-25
A new host mode, dell-host-mode host-group (PowerStore only): per-node host objects placed in an array host group named after the cluster, so one mapping reaches every node. A host belongs to at most one host group and is mapped through it, so a host already in somebody else's group is left there and reported, never moved. Also: the cluster name is detected from corosync.conf when a storage is added, and a refused volume name now names the recycled object holding it. Requested by Alexander Gott (@alexandergott-afk), issues #4 and #5. 新增一種 host 模式 dell-host-mode host-group(僅 PowerStore):各節點的 host 物件會被放進一個以叢集命名的儲存伺服器 host group,讓一次對應就能觸及每一台節點。一個 host 最多只能屬於一個 host group,而且是透過它被對應的,所以已經在別人群組裡的 host 會被留在原處並回報,絕不搬動。另外:加入儲存時會從 corosync.conf 偵測叢集名稱,而被拒絕的磁碟區名稱現在會指出是哪個被回收的物件佔住了它。由 Alexander Gott(@alexandergott-afk)在 issue #4 與 #5 提出。
v0.8.22~beta1
2026-08-25
dell-host-mode shared was described, in the option's own text and in the configuration guide, as registering a single host group for the whole cluster. It registers one host object with every node's initiators in it, which is a different object with different mapping behaviour. Raised by Alexander Gott (@alexandergott-afk), issue #5. The documentation now also records what is available today: the plugin does not create host groups, but it does map through one that already exists. dell-host-mode shared 在選項自己的說明與設定指南中,都被寫成「為整個叢集註冊一個 host group」。它註冊的其實是一個 host 物件,把每台節點的 initiator 放進去,那是不同的物件、對應行為也不同。由 Alexander Gott(@alexandergott-afk)在 issue #5 指出。文件現在也寫上了今天就已經可用的部分:本外掛不會建立 host group,但會沿用已經存在的。
v0.8.21~beta1
2026-08-24
A correction. The code and the 0.8.19 entry both said the kernel's "LUN assignments on this target have changed" is what a stale sd path produces. It is not: that line is the unit attention any array raises when its LUN inventory changes, so this plugin causes one on every map and unmap. A node here with only NetApp iSCSI and no Dell storage has logged it 396 times in sixty days. The reporter of issue #7 came back with the message still appearing, which is how it was caught. The cleanup added in 0.8.19 stands, for a different reason than was given. 一則更正。程式碼與 0.8.19 的紀錄都說核心那句「LUN assignments on this target have changed」是殘留 sd 路徑造成的。並不是:那是任何儲存伺服器在 LUN 清單變動時都會送出的 unit attention,所以本外掛每一次對應與解除對應都會觸發。這裡一台只有 NetApp iSCSI、沒有任何 Dell storage 的節點,六十天內記了 396 次。issue #7 的回報者升級後回來說訊息還在,才讓它被抓到。0.8.19 加入的清理仍然成立,只是理由與當初給的不同。
v0.8.20~beta1
2026-08-24
Creating a VM could fail with ten identical retries and then blame other nodes that were not there. A volume deleted from PowerStore Manager stays in the recycle bin: no listing shows it and the array still refuses its name, so the retry asked the view that was wrong and got the same answer every round. It remembers what was refused now, which converges whatever holds the name. Reported by Alexander Gott (@alexandergott-afk), issue #9 — thank you. 建立虛擬機時可能出現十次一模一樣的重試,然後歸咎於根本不存在的其他節點。在 PowerStore Manager 中刪掉的磁碟區會留在回收筒裡:任何列表都看不到它,而儲存伺服器仍然拒絕它的名字,於是重試每一輪都去問那個出錯的視角、得到同樣的答案。現在它會記住被拒絕過的 ID,不論是什麼東西佔住名字都會收斂。由 Alexander Gott(@alexandergott-afk)在 issue #9 回報 — 在此致謝。
v0.8.19~beta1
2026-08-24
A newly mapped LUN never got a multipath map on a default Debian or Proxmox node: find_multipaths strict builds a map only for a WWID already in /etc/multipath/wwids, however many healthy paths exist, and nothing wrote that entry. The plugin now claims the one WWID with multipath -a rather than changing a node-wide setting. Reported by Alexander Gott (@alexandergott-afk), issue #6 — thank you. Also: the delete path for config volumes and temporary clones did no local device cleanup, which is what leaves stale sd paths behind, and a volume in somebody else's volume group could never be deleted. 在 Debian 或 Proxmox 的預設節點上,新對應的 LUN 從來不會產生 multipath map:find_multipaths strict 只會替已經列在 /etc/multipath/wwids 裡的 WWID 建立 map,無論有幾條健康路徑,而從來沒有東西寫入那一筆。外掛現在改用 multipath -a 認領那一個 WWID,而不是去改動整台節點的設定。由 Alexander Gott(@alexandergott-afk)在 issue #6 回報 — 在此致謝。另外:設定磁碟區與暫時複製的刪除路徑沒有做本機裝置清理,那正是殘留 sd 路徑的來源;而位於他人 volume group 中的磁碟區則永遠刪不掉。
v0.8.18~beta1
2026-08-24
A volume group per VM on PowerStore, off by default, so protection policies and consistent group snapshots can be applied per VM from PowerStore Manager. Requested by Alexander Gott (@alexandergott-afk), issue #3 — thank you. A volume belongs to at most one volume group, so it is mutually exclusive with pstore-volume-group, it never fails a disk creation, only VM disks join, and an empty group is deleted only when this plugin created it, the array answered, and no protection policy is attached. Also: two arrays have run this plugin, not one, and the release pages no longer contradict the install instructions. PowerStore 每台 VM 一個 volume group,預設關閉,讓保護原則與一致性群組快照可以直接在 PowerStore Manager 上以 VM 為單位套用。由 Alexander Gott(@alexandergott-afk)在 issue #3 提出 — 在此致謝。一個磁碟區最多只能屬於一個群組,所以它與 pstore-volume-group 互斥;它永遠不會讓磁碟建立失敗,只有 VM 磁碟會加入,而空群組只有在「本外掛建立的、儲存伺服器有回答、且沒有保護原則」三者同時成立時才會刪除。另外:跑過本外掛的儲存伺服器是兩台而不是一台,release 頁面的安裝說明也不再與其他文件矛盾。
v0.8.17~beta1
2026-08-21
Taking a snapshot froze a running guest for about eight seconds. volume_snapshot runs between PVE's guest fs-freeze and its thaw, so everything it does is time the guest does no I/O — and the VM configuration backup, on by default, creates a volume, maps it, rescans the transport, waits for a device and makes a filesystem. The array snapshot itself took 0.00s. That work is now detached. Reported with timestamps by Alexander Gott (@alexandergott-afk), issue #2 — thank you. Also: the documentation offered SAS as a PowerVault data path, which is not implemented and cannot be configured. 建立快照會讓執行中的客體凍結大約八秒。volume_snapshot 跑在 PVE 的客體檔案系統凍結與解凍之間,所以它做的每一件事都是客體不做任何 I/O 的時間 — 而預設開啟的 VM 設定備份會建立磁碟區、對應、重新掃描傳輸層、等待裝置、建立檔案系統。儲存伺服器上的快照本身只花了 0.00 秒。這些工作現在已脫離出去。由 Alexander Gott(@alexandergott-afk)附時間戳記回報,issue #2 — 在此致謝。另外:文件把 SAS 列為 PowerVault 的資料路徑,但它並未實作,也無法被設定。
v0.8.16~beta1
2026-08-21
PowerStore refused every OVMF EFI disk, so no UEFI guest could be migrated or cloned onto the storage while its ordinary disks went across without complaint. PVE allocates an EFI disk at 540672 bytes and PowerStore rejects anything below 1 MiB — and 540672 is already an exact multiple of the array's 8 KiB granularity, so rounding had nothing to say about it. A granularity and a minimum are different rules. Reported with a working fix by Alexander Gott (@alexandergott-afk), issue #1 — thank you. PowerStore 拒絕了每一顆 OVMF EFI 磁碟,於是沒有任何一台 UEFI 客體能遷移或複製到這個儲存上,而同一台虛擬機的一般磁碟卻毫無阻礙地搬了過去。PVE 配置 EFI 磁碟的大小是 540672 位元組,而 PowerStore 會拒絕任何小於 1 MiB 的磁碟區 — 偏偏 540672 本身就是儲存伺服器 8 KiB 對齊單位的整數倍,所以進位什麼也沒做。對齊單位與最小值是兩條不同的規則。由 Alexander Gott(@alexandergott-afk)在 issue #1 回報並附上可用的修正 — 在此致謝。
v0.8.15~beta1
2026-08-17
The logout was sent without the session key, so the array ended nothing — every logout since 0.8.9 was a no-op. no_auth means "do not go and get a session", not "this request needs no credential". The test fixture accepted a logout without looking at its headers, which is why it survived five releases. 登出請求沒有帶 session key,所以儲存伺服器什麼也沒結束 — 自 0.8.9 起每一次登出都是空操作。no_auth 的意思是「不要去取得連線」,不是「這個請求不需要憑證」。測試裡的假儲存伺服器不看標頭就接受登出,這是它撐過五個版本的原因。
v0.8.14~beta1
2026-08-17
A forked process still leaked its management session: is_worker is PVE's label for one kind of fork, and any other forked child cached a client that POSIX::_exit then discarded without cleanup. Only the process that loaded the plugin caches one now. Also: a dedicated ME account with a short session timeout, measured by a customer at 180 sessions down to 16. 分叉出來的行程仍然會漏掉管理連線:is_worker 只是 PVE 對其中一種 fork 的稱呼,其他分叉子行程會快取 client,而 POSIX::_exit 不跑任何清理就把它丟掉。現在只有載入外掛的那個行程會快取。另外:為外掛建立連線逾時很短的 ME 專用帳號,客戶實測從 180 個降到 16 個。
v0.8.13~beta1
2026-08-13
A Related projects section at the foot of this site, one card per sibling plugin. They share the host-side layer, and several defects fixed here were found by reading their incident records. 本站最下方新增「相關專案」區塊,每個相關外掛一張卡片。它們共用主機端那一層,而這裡修掉的缺陷有好幾個,是讀它們的事故紀錄找到的。
v0.8.12~beta1
2026-08-12
A snapshot rollback flushed and invalidated whatever the device lookup handed it. Devices are resolved fresh on every use and the lookup has fallbacks; a rollback writes, so the wrong one means the flush lands elsewhere and this volume's dirty pages go back on top of the restored snapshot. 快照倒回會對「查出來的那個裝置」做 flush 與 invalidate,而沒有先確認它是誰。裝置是每次現查的、查找有退路;倒回是要寫的,所以查錯就會讓 flush 落到別處,而這一顆的髒頁被寫回到剛還原好的快照上面。
v0.8.11~beta1
2026-08-12
The lines inside a table are visible now — they are what a reader follows across four family columns, and at the old tone there was nothing to follow. 表格內的框線現在看得見了 — 讀者要沿著它橫跨四個系列欄位找到自己那一格,而原本的色調根本沒有線可以跟。
v0.8.10~beta1
2026-08-12
The session release added in 0.8.9 could not run in a PVE worker: fork_worker ends the child with POSIX::_exit, which skips END blocks entirely. A worker now gets an uncached client, so the session goes back when the call returns. 0.8.9 加的連線歸還在 PVE worker 裡跑不到:fork_worker 是以 POSIX::_exit 結束子行程的,那會完全跳過 END 區塊。現在 worker 拿到的是不快取的 client,呼叫返回時連線就歸還。
v0.8.9~beta1
2026-08-11
Management sessions were opened and never given back — reported from a customer's ME, where they accumulate and the CLI has no command to clear one. Released now when a process exits and when the TTL replaces a session. 管理連線建立之後從來沒有歸還 — 由客戶的 ME 回報,連線會累積,而 CLI 沒有任何指令清得掉。現在會在行程結束時、以及 TTL 汰換連線時歸還。
v0.8.8~beta1
2026-08-09
The host-side layer was exercised against real SAN devices for the first time outside a customer's array — the vendor gate holds, every device helper answers correctly and within its bound. Fixed: a long outage repeated a 297-character message every ten seconds in the journal. 主機端那一層第一次在客戶儲存伺服器以外的地方面對真實 SAN 裝置 — 廠商閘門成立,每個裝置輔助函式的回答都正確且在界限內。並修正:長時間中斷時,journal 每十秒重複一段 297 字元的訊息。
v0.8.7~beta1
2026-08-09
Chinese now says 儲存伺服器 for an array, never 陣列 — 463 occurrences across every Chinese document, and a test that keeps it that way. 中文一律以「儲存伺服器」稱呼 array,不再使用 陣列 — 全部中文文件共 463 處,並由測試維持。
v0.8.6~beta1
2026-08-09
Two of the four volume names PVE builds itself — efi-enroll and fleece-<n> — were not recognised, and allocation fell through to an ordinary disk name rather than refusing. Fleecing is the one that matters: it goes wrong during a backup. Also: the site lost its side padding on a narrow window. PVE 自己建構的四種磁碟區名稱中,有兩種不被認得 — efi-enroll 與 fleece-<n> — 而且不是拒絕,是落到「當成普通磁碟命名」。要緊的是 fleecing:它會在備份時出錯。另外:文件站在窄視窗下失去左右留白。
v0.8.5~beta1
2026-08-08
The three navigation entries added in 0.8.4 were missing the class the others carry and rendered as bare inline text. The navigation is now checked: every link styled, every link pointing somewhere, every section reachable. 0.8.4 新增的三個側欄項目少了其他項目都有的 class,變成沒有樣式的行內文字。現在導覽會被檢查:每個連結都有樣式、都指向存在的章節,每個章節都到得了。
v0.8.4~beta1
2026-08-08
This site now leads with which Proxmox VE operations work and where each has actually been driven, why the plugin has to be verified on hardware, and how to help. The test count in the text is checked against the run, because a number in prose goes stale silently. 本站改為先講:哪些 Proxmox VE 操作可用、每一項實際在哪裡跑過、為什麼這個外掛需要實機驗證,以及如何協助。文中的測試數量會與實際執行結果比對,因為寫在文句裡的數字會安靜地過期。
v0.8.3~beta1
2026-08-08
From reading the synology plugin's changelog defect by defect: an unbounded waitpid on the path where nothing went wrong, a multipath map that never reached the new size after a resize, and every other node keeping the old size — which hands a migrated guest a device smaller than its configuration claims. 逐條讀 synology 外掛的變更紀錄而來:一個在「什麼都沒出錯」路徑上沒有界限的 waitpid、擴充後始終沒達到新大小的 multipath map,以及其他節點仍停在舊大小 — 那會把一個比設定更小的裝置交給遷移過去的客體。
v0.8.2~beta1
2026-08-07
A host inside a host group is mapped through the group, which is the only target PowerStore offers once a host joins one. Attaching the member host left every other node in the group without the volume. 屬於 host group 的 host 改為透過 group 對應 — host 一旦加入 group,那就是 PowerStore 唯一提供的對應對象。接上成員 host 會讓 group 裡其他節點都拿不到該磁碟區。
v0.8.1~beta1
2026-08-07
A migrated VM could arrive on a node that could not see its disk: activate_volume mapped to the generated host name without first working out which host object the node actually is. New volumes were also mapped only to the node that created them — each node now publishes its resolved host for the others to pre-map to. 遷移過去的 VM 可能落在看不到自己磁碟的節點上:activate_volume 直接用產生的 host 名稱去對應,沒有先判定這台節點實際上是哪個 host 物件。新磁碟區也只會對應到建立它的那台 — 現在每台節點都會發布自己解析到的 host,供其他節點預先對應。
v0.8.0~beta1
2026-08-07
Every volume attach on PowerStore failed: the LUN id was sent as a string, because using it as a hash key stringifies the scalar in place and Perl's JSON encoder then writes the string. Every number in a request body is coerced where it goes in now. PowerStore 上每一次磁碟區對應都失敗:LUN id 以字串送出 — 把它當雜湊鍵會就地字串化該純量,Perl 的 JSON 編碼器接著就寫出字串。現在請求主體裡的每個數字都在放進去的當下強制轉為數值。
v0.7.99~beta1
2026-08-07
Documentation for the host-object behaviour added in 0.7.98 — first run, troubleshooting, naming, configuration and a section on this site, in both languages. 為 0.7.98 的 host 物件行為補上文件 — 首次執行、疑難排解、命名、設定,以及本站的一節,兩種語言都有。
v0.7.98~beta1
2026-08-07
The host object the array already has for this node is used instead of a second one being created — an initiator can belong to only one host object, so a pre-existing host is adopted, provided it holds this node's ports and no others. 改為使用儲存伺服器上原本就有的、屬於本節點的 host 物件,而不是再建一個 — 一個 initiator 只能屬於一個 host 物件,所以會採用既有的 host,前提是它只持有本節點的埠。
v0.7.97~beta1
2026-08-07
"The initiator is already registered" now names the host that holds it, and says how to resolve it — PowerStore's own refusal names neither. Initiators are also compared by identity rather than spelling, since the array, sysfs and the ME CLI each write a WWPN differently. 「initiator 已被註冊」現在會說出是哪個 host 佔用它,以及該怎麼解決 — PowerStore 自己的拒絕訊息兩者都沒有說。initiator 也改為以身分而非寫法比對,因為儲存伺服器、sysfs 與 ME CLI 各自寫法都不同。
v0.7.96~beta1
2026-08-07
First defect found on a PowerStore, and it stopped pvesm add: the FC WWPN was sent without colons, and the array quoted the host name back where the port name belongs. The three families need three different FC identifier formats and now send three. Unity's was missing the node WWN entirely. 第一個在 PowerStore 上找到的缺陷,而且它讓 pvesm add 直接失敗:FC 的 WWPN 送出時沒有冒號,而儲存伺服器在「port name」的位置回填了 host 名稱。三個系列需要三種不同的 FC 識別格式,現在也就送三種。Unity 那個更是整個少了節點 WWN。
v0.7.95~beta1
2026-08-07
sparseinit told PVE a new volume reads as zeroes, and PVE acts on that by not writing the zeroes — true of a thin volume, not of a thick one, so a clone onto a thick volume could leave the array's previous contents inside the guest's disk. Answered per family now. Also: Chinese text uses full-width punctuation throughout, enforced by a test. sparseinit 告訴 PVE 新磁碟區讀出來是零,而 PVE 據此乾脆不寫那些零 — 這對精簡磁碟區成立,對厚配置不成立,於是複製到厚配置磁碟區時,客體可能讀到儲存伺服器先前的內容。現在改為各家族分別回答。另外:中文全面改用全形標點,並由測試強制。
v0.7.94~beta1
2026-08-07
The test suite wrote over this node's own tracking files — the lifecycle tests use storage ids a real installation would also use, and the orphan reaper reads exactly those files. Also: a removed storage left its outage state behind, so a storage created again later inherited it. 測試套件會覆寫本節點自己的追蹤檔案 — 生命週期測試用的儲存 id 正是真實環境也會用的名字,而孤兒回收器讀的就是那些檔案。另修正:被移除的儲存會留下中斷狀態,之後同名的新儲存會繼承它。
v0.7.93~beta1
2026-08-07
The recovery tool had been left behind by two changes: it looked for the array password where it no longer is, and it ignored dell-host-mode — against a shared-mode storage it would have registered a second host and moved this node's initiator off the one every volume is mapped to. Now tested by driving the real script. 災難復原工具被兩項改動甩在後面:它到密碼已不在的地方去找,而且忽略了 dell-host-mode — 對 shared 模式的儲存,它會建立第二個 host,並把本節點的 initiator 從所有磁碟區對應的那一個上搬走。現在以驅動真正的腳本來測試。
v0.7.92~beta1
2026-08-06
IMPORTANT for dellpowerflex on 0.7.86–0.7.91: a storage whose password was still in storage.cfg died with "Can't locate object method" on every array call — the warning about the legacy location used a method PowerFlex does not inherit. The broken path was the upgrade-compatibility path itself. Also: three unthrottled warnings on PowerFlex's activation path. 使用 dellpowerflex 且版本在 0.7.86–0.7.91 者請注意:密碼仍在 storage.cfg 的儲存,每一次儲存伺服器呼叫都會以「Can't locate object method」失敗 — 那則關於舊位置的警告用了 PowerFlex 並未繼承的方法。壞掉的正是升級相容路徑本身。另修正:PowerFlex 啟用路徑上三則未節流的警告。
v0.7.91~beta1
2026-08-06
Two storages on one array shared an API client — and with it the storeid named in every message and the password read per storage. A rotated password on only one of them meant repeated failed logins with a stale credential. Also: get_identity called the same array two different things once dell-portal became a list. 同一台儲存伺服器上的兩個儲存共用了一個 API client — 連同每則訊息指名的 storeid 與逐儲存讀取的密碼。密碼只在其中一個輪換過,就會用過期憑證反覆登入。另修正:dell-portal 成為清單後,get_identity 會把同一台儲存伺服器說成兩台。
v0.7.90~beta1
2026-08-06
The ME4024 has run the six lifecycle items beyond the first-run test — guest boot, disk growth, backup and restore, container, reboot — and all six passed. Fixed: the import skipped runs of zeroes, which is only correct on a thin volume, and thin is an operator's choice here. ME4024 跑完首次執行測試之外的六項生命週期項目 — 客體開機、磁碟擴充、備份與還原、容器、重開機 — 六項全過。並修正:匯入會跳過連續的零,而那只有在精簡磁碟區上才正確,精簡在這裡是操作者的選擇。
v0.7.89~beta1
2026-08-06
Starting a VM stat'ed its disk without a time limit — PVE's base qemu_blockdev_options reaches the device through an unbounded stat, which on a dead multipath device hangs the worker unkillably. Overridden in all four families, plus a test that asks what LVM and RBD both found necessary. 啟動 VM 時對磁碟做了一次沒有上限的 stat — PVE 基底的 qemu_blockdev_options 透過無界限的 stat 取得裝置,而在失效的 multipath 裝置上那會讓 worker 卡死且殺不掉。四個家族都已覆寫,並新增一個測試,問 LVM 與 RBD 都認為必要的是什麼。
v0.7.88~beta1
2026-08-06
Moving a disk to another storage type, pvesm export/import and remote migration were advertised and then refused one call later: only the format was declared, not the transfer. Both are implemented now, and the device an import writes to must be confirmed by the kernel. 把磁碟移到其他類型的儲存、pvesm export/import 與跨叢集移轉,先被宣告可用、下一個呼叫就被拒絕:當初只宣告了格式,沒有實作傳輸。兩者現已實作,而且匯入要寫入的裝置必須經核心確認。
v0.7.87~beta1
2026-08-06
SECURITY: PowerVault's login puts sha256("user_password") in the URL, so a failed login wrote a crackable hash into the journal in full. Every message now passes a shape-based redactor — credentials cut to a correlatable prefix, WWIDs and volume names untouched. 安全性:PowerVault 的登入把 sha256(「帳號_密碼」) 放在 URL 裡,因此登入失敗會把一個可破解的雜湊完整寫進 journal。現在每則訊息都會經過依形狀判斷的遮蔽 —— 憑證截成可對照的前綴,WWID 與磁碟區名稱完好保留。
v0.7.86~beta1
2026-08-06
SECURITY: the array password was stored in clear text in /etc/pve/storage.cfg — group-readable by www-data, replicated to every node, and echoed back by the API. It now lives in /etc/pve/priv at mode 0600. Existing storages keep working; one pvesm set per storage completes the move. 安全性:儲存伺服器密碼原本以明文存放在 /etc/pve/storage.cfg —— www-data 群組讀得到、複製到每個節點、API 還會原樣回傳。現在改存於 /etc/pve/priv,權限 0600。既有儲存照常運作;每個儲存執行一次 pvesm set 即可完成搬移。
v0.7.85~beta1
2026-08-06
The 4.x-only NVMe mapping action no longer spells its boolean the 3.x way, the readback question only an array can answer is pre-registered with its symptom, and every family's multipath deviations from the kernel built-ins now carry their justification in code. 4.x 專屬的 NVMe 對應動作不再用 3.x 的方式拼布林,只有儲存伺服器能回答的讀回問題已連同症狀先行登記,各系列對核心內建 multipath 條目的偏離也都在程式碼中寫明理由。
v0.7.84~beta1
2026-08-06
Unity's multipath drop-in would have replaced the kernel's CLARiiON-family tuning with a generic ALUA guess — wrong checker, wrong prio, a hardware handler the built-in deliberately omits. It now follows the kernel's own DGC entry and adds only bounded-recovery settings. Unity 的 multipath drop-in 原本會把核心的 CLARiiON 家族調校換成通用的 ALUA 猜測 —— checker 錯、prio 錯、還強加了內建刻意不設的 hardware handler。現在它跟隨核心自己的 DGC 條目,只追加有界復原設定。
v0.7.83~beta1
2026-08-06
An NVMe host and an SDC are mapped by different actions, and PowerFlex's default protocol was using the wrong one — hostId sent to addMappedSdc. Dell's own client names addMappedHost/removeMappedHost; both directions now choose by what is being mapped. NVMe host 與 SDC 是用不同的動作對應的,而 PowerFlex 的預設協定用錯了 —— 把 hostId 送給 addMappedSdc。Dell 自己的客戶端寫著 addMappedHost/removeMappedHost;現在兩個方向都依對應對象選擇動作。
v0.7.82~beta1
2026-08-06
PowerFlex's most destructive call - the snapshot rollback - was resting on a 3.x form Dell's client never implemented. On 4.x it now uses the 'restore' action read from Dell's own gen2 client, chosen after the login has told us which generation the array speaks. PowerFlex 最具破壞性的呼叫 —— 快照倒回 —— 原本建立在一個 Dell 客戶端從未實作的 3.x 寫法上。在 4.x 上它現在改用讀自 Dell gen2 客戶端的 restore 動作,並在登入告訴我們儲存伺服器說哪一代語言之後才做選擇。
v0.7.81~beta1
2026-08-06
Every Unity refusal now carries the array's own errorCode, the way PowerVault's messages carry their return code — the numbers the ME4024's tester quoted in every report. Plus a signature-convention guard in the suite and a perlcritic gate audited down to zero. 每個 Unity 拒絕現在都帶著儲存伺服器自己的 errorCode,一如 PowerVault 訊息裡的 return code —— 那正是 ME4024 測試者每份回報都引用的數字。另外測試套件新增簽名慣例守衛,perlcritic 閘門逐類稽核至零。
v0.7.80~beta1
2026-08-06
One extra parameter in Unity's WWID lookup swallowed the volume name, so every lookup answered undef — device discovery dead on arrival. All 22 array-method signatures are now compared against BlockBase's actual call sites; this was the only mismatch. Unity 的 WWID 查詢多宣告了一個參數,磁碟區名稱被吞掉,每次查詢都回 undef —— 裝置探索一上機就陣亡。22 個 array 方法的簽名已全數與 BlockBase 實際呼叫點比對,只有這一個不匹配。
v0.7.79~beta1
2026-08-06
Running pvesm add end-to-end against the emulator found that a REFUSED add had already written the multipath drop-in and reconfigured every vendor's maps node-wide. The drop-in now waits until the protocol activation has actually succeeded. 把 pvesm add 對模擬器端到端跑了一次,發現被「拒絕」的 add 早已寫入 multipath drop-in 並做了全節點的重讀。drop-in 現在會等到協定啟用真正成功之後才寫入。
v0.7.78~beta1
2026-08-06
PowerFlex's two login generations have the same shape as PowerVault's two login methods, and the timeout cap added for one had not been applied to the other — lesson 40a in the transport dimension. A dead array is now declared dead after one cycle, whichever family is asking. PowerFlex 的兩個登入世代與 PowerVault 的兩種登入方式如出一轍,但為後者加上的逾時上限沒有套到前者 —— 教訓 40a 的傳輸層版本。現在無論哪個系列在問,死掉的儲存伺服器一輪之後就會被宣告死亡。
v0.7.77~beta1
2026-08-06
A Unity listing that claims 9999 rows and hands back none was read as an empty collection — which the orphan reaper reads as "everything was deleted". Contradictions and page-cap truncations are now loud errors. And the health ping stopped duplicating the capacity query. 一份自稱有 9999 筆卻一筆都不給的 Unity 列舉,原本被讀成空集合 —— 孤兒回收機制會把那讀成「全部都被刪了」。矛盾與頁數上限截斷現在都是大聲的錯誤。另外健康檢查的 ping 不再與容量查詢重複。
v0.7.76~beta1
2026-08-06
Real sockets caught what fake user agents could not: the failover rotated the portal and then sent the request to the address it had just abandoned, because the URL was built before the login that discovers the dead controller. The adverse suite now attacks Unity too. 真實 socket 抓到了假 UA 看不見的問題:容錯轉了位址,請求卻送回剛拋棄的那一個 —— 因為 URL 建在「發現控制器死掉」的登入之前。adverse 測試套件現在也攻擊 Unity。
v0.7.75~beta1
2026-08-06
dell-portal now takes both controllers' management addresses, comma-separated, and fails over between them — asked by the ME4024's tester, whose array has no floating management IP. The data path never needed help; management does, and now has it. dell-portal 現在可以逗號分隔填入兩個控制器的管理位址並自動容錯 —— 由 ME4024 的測試者提出,他們的儲存伺服器沒有浮動管理 IP。資料路徑從來不需要幫忙;管理路徑需要,現在有了。
v0.7.74~beta1
2026-08-06
The rollback backup snapshot carried two traps of its own: being the newest, it blocked every second rollback; and its name was one a user could type, putting their snapshot in the cleanup's path. Now hidden from PVE, named with a dot no user can type, and capped at one. 倒回的備份快照自己帶著兩個陷阱:它永遠最新,因此擋住每一次第二次倒回;而它的名字使用者打得出來,使用者的快照會落入清理範圍。現在它對 PVE 隱藏、改用使用者打不出來的帶點名稱,且永遠只保留一份。
v0.7.73~beta1
2026-08-06
"Absent" on a Unity delete now gets a listing's second opinion — a firmware without by-name lookups would otherwise have turned every delete into a reported success that deleted nothing. And linked clones map back to their template, so qm rescan does not duplicate them. Unity 刪除路徑上的「不存在」現在要經過列舉的第二意見 —— 否則不支援以名稱查詢的韌體,會把每一次刪除都變成「回報成功但什麼都沒刪」。另外連結複製會對應回它的範本,qm rescan 不會再把它加成兩份。
v0.7.72~beta1
2026-08-06
The pool key on a Unity create was a Go field name, not the JSON tag that goes on the wire. And a concurrent mapping change could silently unmap a node — both attach and detach now verify their write and retry, because a lost update is visible after the fact. Unity 建立 LUN 時的儲存池鍵用的是 Go 的欄位名稱,而不是真正上線路的 JSON 標籤。另外並行的對應變更可能靜靜地把某個節點解除對應 —— attach 與 detach 現在都會在寫後驗證並重試,因為遺失的更新事後是看得見的。
v0.7.71~beta1
2026-08-06
Unity creates a backup snapshot on every restore whether asked or not; unnamed, it made the volume undeletable days after the rollback that caused it. It now gets this plugin's own name. And an EFI disk (4 MiB) is rounded up past the array's minimum LUN size, so 'qm create' survives. Unity 在每次 restore 時都會自動建立備份快照;沒有命名的話,磁碟區會在倒回的幾天後變得刪不掉。現在它會拿到本外掛自己的名稱。另外 EFI disk(4 MiB)會被向上補足到儲存伺服器的最小 LUN 容量,讓 qm create 得以成功。
v0.7.70~beta1
2026-08-05
Reading Dell's Programmer's Guide corrected two things no amount of reading Dell's code could: on Unity a 302 is an authorization error rather than a redirect, and paging has a real total to work from instead of a guess about short pages. 讀 Dell 的 Programmer's Guide 修正了兩件「讀再多 Dell 程式碼也看不出來」的事:在 Unity 上 302 是授權錯誤而不是重新導向,以及分頁其實有真正的總數可用,不必靠「短頁即結束」的猜測。
v0.7.69~beta1
2026-08-05
Driving the Unity client against a REST API emulator found a create that returned undef in silence when the array answered with no body — the volume exists and nothing points at it, which is how a second one gets created on top. Every create now resolves itself by name or fails loudly. 把 Unity 客戶端接上一個 REST API 模擬器,找出了一個「儲存伺服器回應沒有內容時就靜靜回傳 undef」的建立動作 —— 磁碟區存在、卻沒有任何東西指向它,而那正是第二顆被建在第一顆之上的原因。現在每個建立動作都會以名稱自行確認,否則大聲失敗。
v0.7.68~beta1
2026-08-05
A fourth storage type: Unity XT. Written from Dell's own CSI client rather than documentation prose, which corrected the name limit before a single line depended on it. 120 tests, none needing an array. 第四個 storage type:Unity XT。是依 Dell 自己的 CSI 客戶端寫的,而不是文件敘述 —— 那也在任何一行程式依賴它之前,先修正了名稱長度上限。120 個測試,全部不需要儲存伺服器。
v0.7.67~beta1
2026-08-05
The newest release is now the one people find, instead of the green "Latest" badge sitting on a build three weeks behind. And every release carries a copy under a name that does not change, so the documented install URL is right forever. 別人現在會找到最新的那一版,而不是讓綠色的「Latest」標記掛在一個落後三個星期的建置上。另外每一版都會附一份檔名固定不變的副本,因此文件裡的安裝網址永遠正確。
v0.7.66~beta1
2026-08-05
Every successful delete printed a multipath failure that had not happened — the map was removed by name a moment earlier, so flushing it exits non-zero. And the project stopped claiming no hardware has ever run it, in the five places that still said so. 每次成功的刪除都會印出一則其實沒有發生的 multipath 失敗 —— map 在前一刻已經以名稱移除,再去 flush 它自然以非零狀態結束。另外,本專案不再宣稱「從未在硬體上執行過」,先前仍這樣寫的五個地方都已更正。
v0.7.65~beta1
2026-08-05
The first end-to-end run on real hardware. Three defects sat between a storage that came up and a disk that worked, each hidden by the one before it: a host addressed as an initiator, a mapping list that nested by volume, and a placeholder row for a default mapping that does not exist. All three fixed; the whole of FIRST_RUN then passed on a PowerVault ME4024 over Fibre Channel. 第一次在實體硬體上端到端跑完。從儲存能夠啟用、到真的有一顆可用的磁碟之間,卡著三個缺陷,而且一個被前一個擋著看不到:host 被當成 initiator 定址、對應清單依磁碟區巢狀、以及一列描述「不存在的 default mapping」的佔位資料。三者全部修正後,FIRST_RUN 的每一項都在一台走 Fibre Channel 的 PowerVault ME4024 上通過。
v0.7.64~beta1
2026-08-04
The ME4024 payloads behind the previous release are now on file and read by the test suite verbatim, confirming both fixes against what the array actually sends. A host belonging to no host group is now identified by the type the array gives it, not by the key it arrived under. 上一版兩項修正背後的 ME4024 實機回應已經歸檔,測試套件直接逐字讀取,確認兩項修正與儲存伺服器實際送出的內容相符。不屬於任何 host group 的 host,現在改以儲存伺服器自己標示的型別辨識,而不是靠它掛在哪個鍵底下。
v0.7.63~beta1
2026-08-04
Three defects reported from a PowerVault ME4024: the plugin could not find the host it had just created, so the storage went inactive; every pool read as 100% full, so PVE would refuse every allocation; and a healthy FC fabric was reported as unzoned on every poll. 一台 PowerVault ME4024 回報的三個缺陷:外掛找不到自己剛建立的 host,儲存因此進入 inactive;每個儲存池都讀成 100% 已用,PVE 於是拒絕所有配置;以及一組正常的 FC fabric,每次輪詢都被回報成沒有 zoning。
v0.7.62~beta1
2026-08-04
The first defect found on real hardware: a PowerVault ME4024 could not be added at all, because one non-ASCII character in its /show/system response met a JSON decoder being handed characters where it wanted bytes. 第一個在實體硬體上找到的缺陷:一台 PowerVault ME4024 完全無法建立儲存 —— 它 /show/system 回應裡的一個非 ASCII 字元,遇上了一個「被餵入字元、卻期待位元組」的 JSON 解析器。
v0.7.61~beta1
2026-08-04
SHA256SUMS named a file that does not exist after download, because GitHub rewrites "~" in an asset name. Found by following the install instructions rather than reading them. SHA256SUMS 記錄的檔名在下載後根本不存在,因為 GitHub 會改寫附件名稱中的「~」。這是靠實際照著安裝說明做一次才發現的,不是靠閱讀。
v0.7.60~beta1
2026-08-04
The release pipeline works again. Every release since v0.7.36 failed at the syntax check and published nothing — perl 5.38 words a missing base class differently from perl 5.40, and only one wording was tolerated. 發佈流程恢復正常。自 v0.7.36 起每一次發佈都在語法檢查失敗、什麼都沒發佈 —— perl 5.38 對「基底類別不存在」的措辭與 5.40 不同,而只有其中一種被容忍。
v0.7.59~beta1
2026-08-04
A failing syntax check is echoed as an annotation, which the public API exposes even though logs are not. 失敗的語法檢查會輸出成 annotation —— 即使記錄檔不公開,公開 API 仍讀得到它。
v0.7.58~beta1
2026-08-04
A CI job ran its checks without installing anything they depend on, and failed on every run for months. One check per step now, because a job's step list is public while its logs are not. 一個 CI job 在沒有安裝任何相依套件的情況下執行檢查,連續數個月每次都失敗。現在改為每項檢查一個步驟 —— 因為 job 的步驟清單是公開的,記錄檔不是。
v0.7.57~beta1
2026-08-04
The release workflow had been failing and publishing nothing since v0.7.36: a test that needs Proxmox VE did not skip on a runner that has none, so the suite was green here and red in CI. SHA256SUMS is a checksum file and does not affect installing the package. 自 v0.7.36 起 release workflow 一直失敗、什麼都沒發佈:一個需要 Proxmox VE 的測試在沒有 PVE 的 runner 上沒有 skip,於是本機是綠的、CI 是紅的。SHA256SUMS 只是雜湊驗證檔,不影響套件安裝。
v0.7.56~beta1
2026-07-27
The three family columns of the feature table are centred, headings and values together — the feature-name column stays left, because that is the one the eye reads down. 功能支援表的三個系列欄位改為置中,標題與值一起 —— 功能名稱欄維持靠左,因為那是眼睛由上往下讀的一欄。
v0.7.55~beta1
2026-07-27
The tables have column separators as well as row ones, so a value can be read against its heading rather than by counting across. 表格除了橫向分隔線之外也加上了直向的欄位分隔線,可以直接對著欄位標題讀值,不必橫著數過去。
v0.7.54~beta1
2026-07-27
In the feature table, a value that is the same for every family now spans the three columns and is centred. A merged row means "the same everywhere"; a split row means the families differ. 功能支援表中,三個系列相同的值改為跨欄置中。合併的列代表「三者相同」,分欄的列代表「有差異」。
v0.7.53~beta1
2026-07-27
Install from the release package; building from source is for working on the plugin. Checking the live release also showed the documented verification step could not be carried out — SHA256SUMS is on no release — and that a URL built from the version number 404s. 請安裝發行版套件;從原始碼建置是給要修改這個外掛的人用的。實際檢查線上 release 也發現文件寫的驗證步驟根本無法執行 —— 沒有任何 release 附上 SHA256SUMS —— 而且用版本號拼出來的網址會 404。
v0.7.52~beta1
2026-07-27
A snapshot named "before-s-after" — a name PVE accepts — belonged to a volume that does not exist, so it was invisible to the listing and to the purge that runs before a volume can be deleted. 名為「before-s-after」的快照 —— 一個 PVE 會接受的名字 —— 會被歸給一個不存在的 volume,因而對列表、以及刪除 volume 前必須執行的清除都隱形。
v0.7.51~beta1
2026-07-27
Storages named "dell-1" and "dell_1" on one array shared every volume name: each listed the other's disks, and deleting from one deleted from the other. The second storage is now refused when it is created. 同一台儲存伺服器上名為「dell-1」與「dell_1」的兩個儲存,會共用每一個 volume 名稱:彼此列出對方的磁碟,從其中一個刪除就等於從另一個刪除。第二個儲存現在會在建立時就被拒絕。
v0.7.50~beta1
2026-07-27
A PowerStore could be configured for a PowerFlex protocol, and the SAN families silently used iSCSI instead of saying so. Configuration is now checked when it is written, not when it is first used. PowerStore 可以被設定成 PowerFlex 的協定,而 SAN 系列不會說什麼,只是安靜地改用 iSCSI。設定現在在寫入當下就會被檢查,而不是等到第一次使用。
v0.7.49~beta1
2026-07-27
Two things PVE asks a storage plugin that this one never answered: container snapshots were taken without freezing the filesystem, and moving a disk to another storage type was refused before any code here ran. PVE 會向儲存外掛詢問、而本外掛從未回答的兩件事:容器快照未凍結檔案系統就擷取,以及把磁碟搬到另一種型別的儲存在任何程式碼執行前就被拒絕。
v0.7.48~beta1
2026-07-27
PowerFlex does not inherit the shared base class, and none of the safety guards the other two families have had reached it: a delete, a template and a rollback all ran without testing whether a guest was using the volume. PowerFlex 不繼承共用的基底類別,而另外兩個系列具備的安全守衛沒有任何一項套用到它:刪除、建立範本與還原,全都在未檢查「是否有 guest 正在使用」的情況下執行。
v0.7.47~beta1
2026-07-27
Two ways one name could have destroyed many volumes: a PowerVault name able to act as a shell wildcard in a delete, and a temporary-clone record whose only check was a prefix every VM disk shares. 兩種「一個名稱毀掉多個 volume」的途徑:PowerVault 的名稱在刪除指令中可以當成 shell 萬用字元,以及暫存複製紀錄唯一的檢查是一個每個 VM 磁碟都符合的前置字串。
v0.7.46~beta1
2026-07-27
Disabling a storage unmapped volumes whose in-use state could not be established, and a template could be captured mid-write. Both now refuse rather than assume, and a test stops the pattern coming back. 停用儲存時,會對「無法確認是否使用中」的 volume 解除對應;範本也可能在寫入進行中被擷取。兩者現在都改為拒絕而非假設,並有測試防止這個寫法再出現。
v0.7.45~beta1
2026-07-27
"Is anything using this device?" answered "no" every time it failed to find out — including when the one check that sees a running VM could not run. A delete and a rollback both trusted that answer. 「有東西正在用這個裝置嗎?」只要查不出來就一律回答「沒有」—— 包含那個唯一看得到執行中 VM 的檢查跑不起來的時候。刪除與還原兩條路徑都相信了那個答案。
v0.7.44~beta1
2026-07-27
A momentary outage would have made a delete report success, and PVE removes the disk from the VM configuration the moment it does — leaving the volume on the array with nothing pointing at it. "Not there" and "could not ask" are now different answers. 一次短暫的斷線會讓刪除回報成功,而 PVE 在那一刻就會把磁碟從 VM 設定中移除 —— volume 留在儲存伺服器上,卻再也沒有東西指向它。現在「不存在」與「問不到」是兩個不同的答案。
v0.7.43~beta1
2026-07-27
The ownership gate that guards every destructive path was defined, documented and tested — and called from nowhere. It is wired in now, and doing so immediately showed its own definition was incomplete. 守著每一條破壞性路徑的所有權閘門,有定義、有文件、也有測試 —— 但沒有任何地方呼叫它。現在已經接上,而接上的當下就暴露出它自己的定義並不完整。
v0.7.42~beta1
2026-07-27
A node-wide multipath reconfigure was being used to make one LUN appear — on a timer, and on every device wait. It reapplies configuration to every map on the node, other vendors' storage included. A new LUN is now claimed one named path at a time. 原本用一個「節點層級」的 multipath reconfigure 去讓單一 LUN 出現 —— 而且是依計時器執行、每次等待裝置也執行。它會把設定重新套用到節點上的每一個 map,包含其他廠牌的儲存。現在改為逐一指名路徑來認領新的 LUN。
v0.7.41~beta1
2026-07-27
A LUN with one path gets no multipath map on a node whose find_multipaths is strict — the Debian default, and exactly what a first hardware test looks like. The diagnostic now names it instead of leaving the operator to connect two facts. 在 find_multipaths 為 strict 的節點上,只有單一路徑的 LUN 不會產生 multipath map —— 那是 Debian 的預設值,也正是第一次實機測試的樣子。診斷訊息現在會直接指名它,而不是把兩件事的關聯留給操作者自己想通。
v0.7.40~beta1
2026-07-27
A PowerStore timestamp's zone offset was read and then thrown away. On a node in UTC+8 every snapshot would have been dated eight hours wrong — which looks like a bug in PVE and is not one. PowerStore 時間戳的時區位移被解析出來之後就丟掉了。在 UTC+8 的節點上,每一個快照的時間都會差八小時 —— 那看起來像是 PVE 的問題,但並不是。
v0.7.39~beta1
2026-07-27
Every PowerStore endpoint, request body and enum is now confirmed against Dell's own SDK and Ansible collection — all of them already matched. What remains unverified is what the array puts in a response. PowerStore 的每一個端點、請求內容與列舉值,都已對照 Dell 自己的 SDK 與 Ansible collection 確認 —— 原本就全部相符。仍未驗證的是儲存伺服器在回應裡放了什麼。
v0.7.38~beta1
2026-07-27
PowerStore could not have reported its capacity: the space metric was read as a REST collection when it is an entity name for the metrics service. The storage would have shown as inactive with nothing else wrong with it. PowerStore 根本無法回報自己的容量:容量指標被當成 REST 集合來讀,但它其實是指標服務的 entity 名稱。儲存會顯示為 inactive,而其他一切明明都正常。
v0.7.37~beta1
2026-07-27
PowerFlex NVMe/TCP could not have connected at all — the family's default data path. The host was sent to the SDS-facing port, and the subsystem NQN was read from an object that has no NQN field. Both settled by reading Dell's own Ansible module. PowerFlex 的 NVMe/TCP 根本連不上 —— 而那是這個系列的預設資料路徑。主機被送往了面向 SDS 的連接埠,而 subsystem NQN 讀的是一個根本沒有 NQN 欄位的物件。兩者都是靠閱讀 Dell 自己的 Ansible 模組才確認的。
v0.7.36~beta1
2026-07-27
Dell's REST reference and Dell's own SDK spell the PowerFlex volume-size parameter differently. Creating a volume is the first thing anyone does here, so both are tried — and only on a rejection, never on a server error that may already have created something. Dell 的 REST 參考文件與 Dell 自己的 SDK,對 PowerFlex 容量參數的拼法並不相同。建立 volume 是使用本外掛的第一件事,因此兩種都會嘗試 —— 而且只在「被拒絕」時,絕不會在「可能已經建立了東西」的伺服器錯誤之後重試。
v0.7.35~beta1
2026-07-27
Every command now runs in the C locale. On a zh_TW node — the kind this plugin is written for — a translated tool answers in Chinese and every parser expecting English silently matches nothing. 每一個指令現在都在 C 語系下執行。在以 zh_TW 執行的節點上 —— 也就是本外掛所設想的那種節點 —— 有翻譯的工具會用中文回答,而每一個預期英文的解析器都會靜靜地比對不到任何東西。
v0.7.34~beta1
2026-07-27
The same mistake as the release before it, pointed at the operating system instead of the array: a node with no iSCSI was recognised by matching an English error string, which is not what a node running in another language says. 與前一版同樣的錯誤,只是對象從儲存伺服器換成作業系統:判斷節點有沒有 iSCSI,靠的是比對一段英文錯誤訊息 —— 而以其他語言執行的節點並不會那樣說。
v0.7.33~beta1
2026-07-27
"Does this volume exist?" was answered by matching the words an array chose. An array saying "storage pool not found" would have been read as "the volume is gone" — and the next thing a caller does with that answer is create a second one. A test now fails on any new decision made that way. 「這個 volume 存在嗎?」原本是靠比對儲存伺服器所選的字句來回答。儲存伺服器若回「storage pool not found」,會被讀成「這個 volume 不見了」—— 而呼叫端拿到這個答案之後就會再建一個。現在只要出現新的這類判斷,就會有測試失敗。
v0.7.32~beta1
2026-07-27
Two things that would have done more than they were asked to: a feature check that could abort a whole operation, and a recovery tool that detached a volume it had not attached. 兩處做了超出被要求範圍的事:一個功能檢查可能讓整個操作中止,以及一支救援工具會去解除它並沒有掛上的對應。
v0.7.31~beta1
2026-07-27
No linked clone could have been snapshotted or renamed: a linked clone's name begins with "base-", and that was taken to mean it was a template. PVE would have refused with "the feature is not available on this storage". 任何連結複製都無法建立快照或重新命名:連結複製的名稱以「base-」開頭,而這被當成了「它是範本」。PVE 只會回一句「此儲存不支援該功能」就拒絕。
v0.7.30~beta1
2026-07-27
Moving a linked clone's disk to another type of storage would have asked the target for a volume named after a base image it has never heard of. The volume-name contract is now measured against PVE's own RBD plugin rather than against a value someone wrote down. 把連結複製的磁碟搬到另一種型別的儲存時,會要求目標端建立一個以「它從未聽過的範本映像」命名的 volume。volume 名稱的約定現在直接與 PVE 自己的 RBD 外掛比對,而不是比對某人當初寫下來的值。
v0.7.29~beta1
2026-07-27
A PowerStore host that belongs to a host group would have been handed a LUN id the group already held, because a group-level mapping names the group and not the host. Dell's own KB now backs why the LUN ceiling is 255. 屬於某個 host group 的 PowerStore host,會被配到群組已經佔用的 LUN ID —— 因為群組層級的對應指名的是群組而不是 host。LUN 上限為何是 255,現在有 Dell 自己的知識庫文章佐證。
v0.7.28~beta1
2026-07-27
A PowerFlex volume mapped to an NVMe host could have looked unmapped forever, because a mapping entry that names both an SDC id and a host id had one of them dropped. The fourth appearance of the same mistake in this project, so the audit checklist now names the shape. 對映到 NVMe host 的 PowerFlex volume 可能永遠看起來都未對映,因為同時帶有 SDC id 與 host id 的對應項目,其中一個被丟掉了。這是同一個錯誤在本專案第四次出現,因此稽核清單現在直接點名這個寫法。
v0.7.27~beta1
2026-07-27
A printed column heading is not a property name. The PowerVault basetype documentation settles which field names the JSON really carries, and the field order now follows it. 列印出來的欄位標題不等於屬性名稱。PowerVault 的 basetype 文件確定了 JSON 實際帶的欄位名稱,欄位順序現在依照它排列。
v0.7.26~beta1
2026-07-27
The second volume mapped to a PowerVault host would have been handed a LUN the first one already used, because the LUN search compared an initiator IQN against a host name. PowerVault size and used space now read the field names the CLI Reference documents. 對映到同一台 PowerVault host 的第二個 volume,會拿到第一個已經在用的 LUN —— 因為搜尋可用 LUN 時,拿 initiator 的 IQN 去比對 host 名稱。PowerVault 的大小與已用空間現在改讀 CLI Reference 記載的欄位名稱。
v0.7.25~beta1
2026-07-27
Two more PowerStore paths that rested on unverified request syntax: a volume deleted mid-listing would have failed the listing, and the iSCSI portal lookup would have found nothing at all if the array read one filter operator differently. Neither depends on the answer now. 另外兩處 PowerStore 路徑原本建立在未驗證的請求語法上:列舉期間有 volume 被刪除會讓整個列舉失敗,而儲存伺服器若對某個過濾運算子解讀不同,iSCSI portal 就會完全查不到。現在兩者都不再取決於那個答案。
v0.7.24~beta1
2026-07-27
PowerStore volumes would have been invisible to PVE: the name filter used the wrong ilike wildcard, and an empty listing looks exactly like a storage with no volumes. An empty prefix listing is now rechecked locally, so the question cannot lose volumes either way. PowerStore 上的 volume 會完全看不到:名稱過濾用錯了 ilike 萬用字元,而「空的列舉」看起來就跟「沒有任何 volume 的儲存」一模一樣。現在前置字串列舉若為空會在本地重新比對,因此不論答案是哪一種都不會弄丟 volume。
v0.7.23~beta1
2026-07-27
Every field name the API clients read is now listed with its verification state, so one pass over a real array response can settle all of them. A test keeps the list in step with the code. API 客戶端讀取的每一個欄位名稱都列出了它的查證狀態,因此比對一次真實回應就能一次確認全部。並有測試確保這份清單與程式同步。
v0.7.22~beta1
2026-07-27
Every PowerVault pool would have looked completely full: show pools reports Avail, and the code read a field named avail-size that does not exist. 每一個 PowerVault 儲存池看起來都會是滿的:show pools 回報的是 Avail,而程式讀的是一個不存在的 avail-size 欄位。
v0.7.21~beta1
2026-07-27
The "device is still in use" message could never name the process holding it: fuser -v prints its table to stderr, and only stdout was being read. 「裝置仍在使用中」的訊息永遠說不出是哪個行程佔著它:fuser -v 把表格印到 stderr,而程式只讀了 stdout。
v0.7.20~beta1
2026-07-27
The package did not depend on LWP's HTTPS driver, which is a separate package on Debian and was present only because pve-manager happens to pull it in. 套件沒有相依 LWP 的 HTTPS 驅動;那在 Debian 上是獨立套件,先前只是因為 pve-manager 剛好會把它帶進來才存在。
v0.7.19~beta1
2026-07-27
The release workflow installed only build tools, so every test that loads an API client would have died at compile time rather than testing anything. 發布用的 workflow 只安裝了建置工具,因此每一個會載入 API 客戶端的測試都會在編譯期就死掉,什麼也沒測到。
v0.7.18~beta1
2026-07-27
A first-run guide for real hardware, in both languages: the order to work through, what to check after each step, and what each failure most likely means. 新增雙語的實機首次執行指南:執行順序、每一步之後要看什麼,以及每種失敗最可能代表什麼。
v0.7.17~beta1
2026-07-27
PowerVault would have re-added an initiator on every host check, and the array's refusal fails activate_storage — so a working storage would have gone inactive. Ports the array calls unusable are no longer offered to the login loop. PowerVault 每次檢查 host 都會重新加入 initiator,而儲存伺服器的拒絕會讓 activate_storage 失敗 —— 原本正常的儲存因此會變成 inactive。儲存伺服器自己說不可用的連接埠,也不再送進登入迴圈。
v0.7.16~beta1
2026-07-27
PowerVault could not tell whether a volume was already mapped to this node: show maps has no host-name column, so the check always answered no and every activation would have remapped and taken another LUN. PowerVault 無法判斷 volume 是否已對應到本節點:show maps 根本沒有 host 名稱欄位,因此檢查永遠回答「否」,每次啟用都會再對應一次並再吃掉一個 LUN。
v0.7.15~beta1
2026-07-27
map volume is the one PowerVault command whose documented argument order differs between ME4 and ME5. The plugin sends the ME5 form and falls back to the ME4 one, so both families work. map volume 是唯一一個在 ME4 與 ME5 之間記載順序不同的 PowerVault 指令。外掛會先送 ME5 的形式,並在需要時退回 ME4 的形式,因此兩個系列都能運作。
v0.7.14~beta1
2026-07-27
PowerVault would not have come up at all: the two host commands used on a storage's first activation were inferred rather than read from Dell's CLI Reference Guide, and both were wrong. PowerVault 原本根本起不來:儲存第一次啟用時用到的兩個 host 指令是推測出來的,而不是查 Dell 的 CLI Reference Guide,而且兩個都錯。
v0.7.13~beta1
2026-07-27
Each of the three families now has a whole VM's life tested against a fake array that enforces that family's own rules, including the order of the four values status() returns. 三個系列現在各自都有一份「一台 VM 的完整生命週期」測試,跑在會強制執行該系列自身規則的假儲存伺服器上,其中也包含 status() 回傳四個值的順序。
v0.7.12~beta1
2026-07-27
Deleting a template could never succeed on PowerStore or PowerFlex: the decision was made by reading the array's refusal text, and on PowerStore the rule matched a hint this plugin had written itself. The array decides now. 在 PowerStore 與 PowerFlex 上刪除範本永遠不會成功:這個判斷是靠讀取儲存伺服器的拒絕訊息做的,而在 PowerStore 上,那條規則比對到的是本外掛自己寫的提示文字。現在改由儲存伺服器決定。
v0.7.11~beta1
2026-07-27
A whole VM's life is now tested against an array that refuses what a real one refuses. It found a delete failure that blamed the volume's snapshots when the real obstacle was a linked clone. 現在會讓一台 VM 的完整生命週期跑在「會像真實儲存伺服器一樣拒絕」的假儲存伺服器上。它找出了一個刪除失敗訊息:真正的阻礙是連結複製,卻怪到該 volume 的快照頭上。
v0.7.10~beta1
2026-07-27
PowerFlex ran an nvme connect per target on every pvestatd poll — six times a minute per node, each with a 30 second timeout on a degraded network. It now connects only what is missing, and forks nothing when everything is up. PowerFlex 先前在每次 pvestatd 輪詢時,都會對每個目標各執行一次 nvme connect —— 每個節點每分鐘六次,在網路劣化時每次都帶 30 秒逾時。現在只連缺少的那些,全部連上時完全不會 fork。
v0.7.9~beta1
2026-07-27
The recovery tool's --insecure flag did nothing, and a protection domain named in the configuration was only consulted when the pool name happened to be ambiguous. 災難復原工具的 --insecure 旗標完全沒有作用;而設定中指定的保護網域,先前只有在儲存池名稱剛好有歧義時才會被參考。
v0.7.8~beta1
2026-07-27
The PowerFlex options were undocumented, including the required one. Two new tests fail on documentation that has drifted from the code, and on a PVE upgrade that changes the contract underneath the plugin. PowerFlex 的選項完全沒有文件,包括必填的那一個。新增兩份測試,分別在「文件與程式碼脫節」以及「PVE 升級改動了外掛所依賴的約定」時失敗。
v0.7.7~beta1
2026-07-27
Missing, renamed and wrongly typed fields thrown at every parser in the plugin. Three defects fixed: names were not anchored exactly, a digit run too long to be a vmid decoded as a float, and a listing row that was not a hash killed the caller. 把缺少、改名、型別不對的欄位丟給外掛中的每一個解析器,修正三項缺陷:名稱錨定不夠精確、長到不可能是 vmid 的數字串會被解成浮點數,以及不是雜湊的資料列會讓呼叫端整個掛掉。
v0.7.6~beta1
2026-07-27
Every file test on a device path is bounded — a stat on a dead multipath device blocks the same way vgs does — and a resize waits for the array to report the new size before the host is refreshed. 所有對裝置路徑的檔案測試都加上時間上限 —— 對已失效的 multipath 裝置做 stat,會以與 vgs 相同的方式卡住 —— 而擴充容量時會先等儲存伺服器回報新容量,才去重新整理主機端。
v0.7.5~beta1
2026-07-27
Two test files that put the plugin under conditions an array is actually found in: a server that misbehaves on purpose, corrupt state files, hostile storage ids, and sixteen-way concurrent allocation — which found a real defect in the disk-id retry loop. 新增兩份測試,以儲存伺服器實際會出現的狀態來施壓:故意行為不良的伺服器、損毀的狀態檔、惡意的 storage id,以及 16 路並行配置 —— 後者找出了 disk id 重試迴圈中的一個真實缺陷。
v0.7.4~beta1
2026-07-27
The storage API version is negotiated rather than hardcoded, deleting a snapshot releases the clone that was reading it (the vzdump snapshot-mode path), the orphan reaper leaves alone any device that still has a working path, and rolling back past newer snapshots is refused. 儲存 API 版本改為協商而非寫死;刪除快照時會先釋放正在讀取它的暫時複製(即 vzdump 快照模式的流程);殘留裝置清理不再碰任何仍有可用路徑的裝置;並拒絕跨過較新快照的還原。
v0.7.3~beta1
2026-07-27
Cross-checked against the production incident records of the two related projects. Nine issues of the same classes were present here, including a refused delete that could be reported as success and an orphan reaper that made one array call per volume on every poll. 對照兩個相關專案的實際生產事故紀錄逐條檢查,其中九項同類問題本專案也有,包括「被拒絕的刪除可能被回報成成功」,以及殘留裝置清理在每次輪詢時對每個 volume 各發一次儲存伺服器查詢。
v0.7.2~beta1
2026-07-26
A review pass against the Proxmox VE 9.2.5 storage API source. Nine defects fixed, including PowerFlex applying PowerVault's name limit, deleting a volume leaving its snapshots behind, and a generated NVMe host NQN that was never persisted. 對照 Proxmox VE 9.2.5 儲存 API 原始碼的全面檢查,修正九項缺陷,包括 PowerFlex 套用了 PowerVault 的名稱長度上限、刪除 volume 沒有一併清除快照,以及自動產生的 NVMe host NQN 沒有被保存。
v0.7.1~beta1
2026-07-26
The VM config backup volume is no longer offered on PowerVault ME, whose volume ceiling is too low to spend one volume per snapshot. On PowerStore it stays on by default and can be turned off with the new dell-config-backup option. PowerVault ME 系列不再提供 VM 設定備份卷,因為它的 volume 上限太少,無法為每個快照再多花一個 volume。PowerStore 上維持預設開啟,並可用新增的 dell-config-backup 選項關閉。
v0.7.0~beta1
2026-07-26
PowerFlex support: NVMe/TCP by default, SDC optional. Both PowerFlex authentication generations are detected automatically. 新增 PowerFlex 支援:預設 NVMe/TCP,SDC 為選項。兩種 PowerFlex 認證世代皆自動偵測。
v0.6.0~beta1
2026-07-26
PowerVault ME4/ME5 support. HTTP 200 is not success on this family, expand takes a delta, and names are limited to 32 bytes without a dot. 新增 PowerVault ME4/ME5 支援。這個系列的 HTTP 200 不代表成功、expand 收的是增量、名稱上限 32 bytes 且不可含句點。
v0.5.0~beta1
2026-07-26
First beta: the dellpowerstore storage type, the abstract block base, the recovery tool and the full documentation set. 第一個 beta:dellpowerstore storage type、抽象 block 基底、災難復原工具與完整文件。

Full changelog: CHANGELOG.md. 完整變更紀錄:CHANGELOG_zh-TW.md。

Acknowledgments 致謝

The host-side layer — device discovery, multipath handling, the anti-hang rules and the orphan reaper — is carried over from two related projects, where those lessons were paid for in production: 主機端底層 —— 裝置探索、multipath 處理、防止卡死的規則與 orphan 清理 —— 承接自兩個相關專案,那些教訓是在正式環境付出代價換來的:

In the absence of hardware, this plugin was written against Dell's published documentation: the PowerStore REST guide, the PowerVault ME5 CLI Reference Guide, and the PowerFlex REST and SDC material. 在沒有實機的情況下,本外掛是依據 Dell 公開的文件撰寫的:PowerStore REST 指南、PowerVault ME5 CLI Reference Guide,以及 PowerFlex 的 REST 與 SDC 資料。