fix: override qemu_blockdev_options to emit lun as integer on PVE 9 (#266)

PVE::Storage::Plugin::qemu_blockdev_options builds the iscsi blockdev JSON
with lun => "$3" — a string capture from the URL regex. QEMU 9's strict
blockdev schema rejects a string where an integer is required, causing every
VM with TrueNAS storage to fail to start on PVE 9.

Override the method in TrueNAS.pm to return the blockdev hash directly from
_find_extent, with lun => int($ext->{lun_id}). This bypasses the base class
entirely and is correct on both PVE 8 and PVE 9.

Verified on pve01-hq (PVE 9.2.3 / QEMU 9 / kernel 7.0.6-2-pve):
VM 103 (TrueNAS-Scale01-Tank01, SCALE 24.10) starts successfully.

The upstream bug in PVE::Storage::Plugin is tracked separately — when
Proxmox fixes it, the override can be removed. See issue #266 for details.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kevin Adams 2026-05-31 23:04:30 -04:00
parent 5919910b3c
commit b1423a9d72
2 changed files with 55 additions and 7 deletions

View File

@ -7,27 +7,50 @@ This file captures release scope, business decisions, and deferred items. It is
## Current Release — v3.0.0 (TrueNAS Custom Plugin)
**Branch:** `release/3.x`
**Status:** Code complete — blocked on #266 (PVE 9 VM start failure) before tagging
**Target:** Ship before PVE 8 EOL (2026-08-31)
Full rewrite as a native `PVE::Storage::Custom` plugin. No patching of PVE files, no SSH, full TrueNAS REST API, bearer token auth only.
### Remaining open items
### Blocking — must fix before v3.0.0 tag
| # | Title | Type |
|---|-------|------|
| [#228](https://github.com/TheGrandWazoo/freenas-proxmox/issues/228) | Migration path v2.x→v3.x docs | docs |
| [#252](https://github.com/TheGrandWazoo/freenas-proxmox/issues/252) | Integration test 2.x→3.0 upgrade path docs | docs |
None. All blocking issues resolved.
### Pre-release housekeeping (non-blocking, do before tag)
| Task | Status |
|------|--------|
| Write ADR-009 superseding ADR-008 — PVE 9 support confirmed, fix approach, snapshot deferred | Pending |
| Close epic #219 | Pending |
| File issue for "older storage API" warning — api() version bump for PVE 9 | Pending |
### Lab upgrade plan (required to test #266)
| Node | Current | Target | Notes |
|------|---------|--------|-------|
| pve01-hq | PVE 8.4.19 | PVE 9.x | Blocked: Ceph Quincy → Reef first; systemd-boot pkg remove |
| pve02-hq | PVE 8.4.14 | PVE 9.x (possible) | TBD |
| pve03-hq | PVE 8.3.2 | Stay 8.4 | Regression baseline |
| pve04-hq | PVE 8.3.2 | Stay 8.4 | Regression baseline |
Ceph upgrade (Quincy → Reef) must complete across all 4 nodes before pve01 OS upgrade.
### Completed in v3.0.0
| # | Title | Commit |
|---|-------|--------|
| [#266](https://github.com/TheGrandWazoo/freenas-proxmox/issues/266) | PVE 9: VM fails to start — `lun` string vs integer in QEMU blockdev JSON | pending commit |
| [#269](https://github.com/TheGrandWazoo/freenas-proxmox/issues/269) | SCALE 25.10 strict Pydantic rejects volsize as string | `c7ce39d` |
| [#267](https://github.com/TheGrandWazoo/freenas-proxmox/issues/267) | free_image 422 on targetextent delete when VM is running | `359c2af` |
| [#265](https://github.com/TheGrandWazoo/freenas-proxmox/issues/265) | Loop over all targetextent rows in free_image | `0dea6bc` |
| [#264](https://github.com/TheGrandWazoo/freenas-proxmox/issues/264) | SCALE 25.04 compatibility: integer type coercion + alias uniqueness | `96957c0` |
| [#261](https://github.com/TheGrandWazoo/freenas-proxmox/issues/261) | API token keyfile (`/etc/pve/priv/truenas-<id>.key`) | `f30862f` |
| [#262](https://github.com/TheGrandWazoo/freenas-proxmox/issues/262) | Package rename: `freenas-proxmox``truenas-proxmox` (transitional package ships) | `9b2ecb8` |
| [#263](https://github.com/TheGrandWazoo/freenas-proxmox/issues/263) | Fix `truenas_target` full-IQN match | `3a8a5df` |
| [#260](https://github.com/TheGrandWazoo/freenas-proxmox/issues/260) | TPM state disk limitation callout in README | `0a8e7e7` |
| [#264](https://github.com/TheGrandWazoo/freenas-proxmox/issues/264) | SCALE 25.04 compatibility: integer type coercion + alias uniqueness | `96957c0` |
| [#250](https://github.com/TheGrandWazoo/freenas-proxmox/issues/250) | Rollback orphaned TrueNAS resources on `alloc_image` partial failure | `eab964c` |
| [#228](https://github.com/TheGrandWazoo/freenas-proxmox/issues/228) | Migration path v2.x→v3.x docs (beginner, advanced, troubleshooting) | `0a17a30` |
| [#252](https://github.com/TheGrandWazoo/freenas-proxmox/issues/252) | Integration test 2.x→3.0 upgrade path | closed |
---
@ -51,7 +74,7 @@ gh repo rename truenas-proxmox --repo TheGrandWazoo/freenas-proxmox
---
## Upcoming — v3.1.0 (PVE 9 + Snapshots)
## Upcoming — v3.1.0 (Snapshots + PVE 9 hardening)
**Target:** Before PVE 8 EOL — 2026-08-31

View File

@ -624,6 +624,31 @@ sub path {
return ($dev_path, $ds_vmid, $vtype);
}
# Override base-class qemu_blockdev_options to ensure lun is encoded as a JSON
# integer. PVE::Storage::Plugin does lun => "$3" (string capture from the
# iscsi:// URL regex) which QEMU 9's strict blockdev schema rejects. We build
# the hash directly from _find_extent so the value is always an IV. (#266)
sub qemu_blockdev_options {
my ($class, $scfg, $storeid, $volname, $machine_version, $options) = @_;
_resolve_token($storeid, $scfg);
my $ext = _find_extent($scfg, $volname);
die "Volume '$volname' has no iSCSI extent on $scfg->{truenas_host}.\n" unless $ext;
die "Volume '$volname' is not mapped to any iSCSI target.\n"
unless defined $ext->{target_id};
my $t = _api($scfg, 'GET', "/iscsi/target/id/$ext->{target_id}") // {};
my $iqn = _basename($scfg) . ":$t->{name}";
return {
driver => 'iscsi',
portal => _portal($scfg),
target => $iqn,
lun => int($ext->{lun_id}),
transport => 'tcp',
};
}
sub activate_storage {
my ($class, $storeid, $scfg, $cache) = @_;
_resolve_token($storeid, $scfg);