Skip to content

Commit c1092cd

Browse files
Sync dev to main (#114)
* Add tests for orchestrator, support, and tui modules Introduces new test files for encryption, prompts, restore workflow, selective menu, support, and abort context functionalities. Refactors orchestrator/encryption.go to allow mocking terminal checks, and support.go to allow mocking email notifier creation for improved testability. Adds a stopHook to tui.App for controlled stopping in tests. * Enforce root check only for real root filesystem restores Updated restore privilege checks to require root only when restoring to the real system root (osFS), not for virtual or test filesystems. Added isRealRestoreFS helper to distinguish filesystem types. * Expand storage tests and improve FilesystemDetector hooks Added extensive test coverage for local and secondary storage, including error handling, edge cases, and permission scenarios. Refactored FilesystemDetector to support injectable test hooks for mount point and filesystem type lookups, and improved octal unescaping logic. These changes enhance testability and reliability of storage operations. * Improve email and webhook notifier test coverage Adds extensive unit tests for email and webhook notifiers, covering error branches, authentication methods, payload formats, and edge cases. Refactors email notifier to allow overriding Postfix config path for hermetic tests and fixes logger level checks for debug output. * Add comprehensive tests for MAC, directory, and security logic Added extensive unit tests to identity_test.go for MAC address handling, interface ranking, system data generation, and edge cases. Expanded directory_recreation_test.go with tests for storage/datastore config parsing, directory creation, error propagation, and ZFS detection. Added security_test.go tests for ownership/permission checks, config-driven logic, and error handling. These tests improve coverage and robustness for identity, orchestrator, and security modules. * Add comprehensive coverage tests for decryption workflow This commit adds extensive unit tests to internal/orchestrator/decrypt_test.go, covering error handling and edge cases for decryption workflows, rclone integration, bundle extraction, manifest inspection, and user prompt logic. The tests improve code reliability by simulating various failure scenarios, file system errors, and user interactions. * Add network safe apply with rollback and diagnostics Implements network configuration safe apply with a transactional rollback timer, health checks, NIC name repair, and diagnostics capture. Adds network inventory collection, network health/preflight validation, and CLI workflow for applying/restoring network config with rollback. Updates backup safety logic to support network-only rollback archives and integrates new reporting in system collector and restore guide documentation. * Add cluster shadowing guard and NIC naming override detection Introduces cluster shadowing guard to prevent direct restoration of /etc/pve paths during cluster recovery, with sanitization logic and tests. Adds detection and reporting of persistent NIC naming override rules (udev/systemd) to network_apply and TUI workflows, including user prompts and detailed logging. Enhances safe cluster apply to handle node mismatches, prompt for source node selection, and improves logging and test coverage for restore scenarios. * feat: improve network staging, datastore handling, and restore workflows - Add staged network file installation with automatic rollback on preflight validation failures in network_apply.go - Implement node hostname mismatch detection when applying VM/CT configs in SAFE cluster restore mode (RESTORE_GUIDE) - Add deferred datastore definition handling to prevent broken entries on unmounted disk locations (RESTORE_GUIDE) - Implement NIC repair staged install workflow and persistent naming rule detection (network_apply.go and docs) - Enhance directory_recreation.go with ZFS mount detection and datastore permission validation logic - Add automatic /etc/resolv.conf repair documentation and failing PBS job config removal on live restores (RESTORE_GUIDE) - Introduce promptYesNo CLI utility function for interactive confirmation prompts (prompts_cli.go) - Add file deduplication optimization pass and additional test coverage in optimizations.go - Expand restore workflow state management with additional safety checks and node handling (restore.go) - Add staged installation documentation covering /tmp/proxsave/restore-stage-* workflow and rollback timer mechanics * refactor: add filesystem category and smart fstab merge - Add filesystem category (ID: "filesystem", path: "./etc/fstab") to restore workflow covering mount points and configurations - Integrate filesystem category into storage, base, and full restore modes in GetStorageModeCategories and GetBaseModeCategories - Implement skipFn parameter in extractArchiveNative and extractPlainArchive to skip /etc/fstab during initial extraction - Add Smart Merge workflow for /etc/fstab via SmartMergeFstab function with user prompts on live restores to root (/) - Intercept filesystem category during normal extraction pipeline in RunRestoreWorkflow to prevent blind overwrite - Update extractArchiveNative to accept optional skipFn callback that filters entries before extraction with SKIPPED logging - Add safeFstabMerge flag in runFullRestore when destRoot == "/" to defer /etc/fstab processing until after extraction - Extend extractSelectiveArchive signature to pass skipFn parameter through the extraction chain - Update TestGetStorageModeCategories and TestGetBaseModeCategories assertions to verify filesystem inclusion (+1 count) - Refactor indentation in maybeInstallNetworkConfigFromStage and maybeApplyNetworkConfigCLI call chains for readability * feat: enhance network apply diagnostics and error handling • Increase network rollback timer from 90s to 180s (defaultNetworkRollbackTimeout constant) • Add NetworkApplyNotCommittedError type to report rollback path and restored IP on timeout • Refactor network validator order: prioritize ifup -n -a over ifquery --check -a for preflight validation • Introduce runNetworkIfqueryDiagnostic function for non-blocking diagnostic checks of network state • Capture baseline health report before apply with writeNetworkHealthReportFileNamed helper • Generate network plan report and capture pre/post-apply ifquery diagnostics automatically • Execute rollback immediately on timer expiration and capture after-rollback snapshots and ifquery output • Enhance error messages with validation command names (preflight.CommandLine()) and rollback paths - Add runCommandWithTimeoutCountdown function with visual progress feedback during service stop operations • Update restore summary to report "warnings" when network apply incomplete, with restored IP information * Add default wait delay to command runner Introduces a default 3-second wait delay for commands executed via osCommandRunner. Handles exec.ErrWaitDelay by returning output without error, improving robustness of command execution. * deps(deps): bump github.com/gdamore/tcell/v2 from 2.13.6 to 2.13.7 in the security-patches group (#112) deps(deps): bump github.com/gdamore/tcell/v2 Bumps the security-patches group with 1 update: [github.com/gdamore/tcell/v2](https://github.com/gdamore/tcell). Updates `github.com/gdamore/tcell/v2` from 2.13.6 to 2.13.7 - [Release notes](https://github.com/gdamore/tcell/releases) - [Changelog](https://github.com/gdamore/tcell/blob/main/CHANGESv3.md) - [Commits](gdamore/tcell@v2.13.6...v2.13.7) --- updated-dependencies: - dependency-name: github.com/gdamore/tcell/v2 dependency-version: 2.13.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: security-patches ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * deps(deps): bump golang.org/x/crypto from 0.46.0 to 0.47.0 (#113) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.46.0 to 0.47.0. - [Commits](golang/crypto@v0.46.0...v0.47.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.47.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix octal unescaping to use ParseUint instead of ParseInt Replaces strconv.ParseInt with strconv.ParseUint in unescapeOctal to correctly handle unsigned octal values. This prevents potential issues when parsing octal escape sequences as bytes. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent c87b63c commit c1092cd

80 files changed

Lines changed: 18286 additions & 257 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@ Thank you so much!
7777

7878
## Repo Activity
7979

80-
![Alt](https://repobeats.axiom.co/api/embed/53ea60503d80f77590f52ac0e983b2b8af47e20a.svg "Repobeats analytics image")
80+
![Alt](https://repobeats.axiom.co/api/embed/d9565d6d1ed8222a5da5fedf25c18a9c8beab382.svg "Repobeats analytics image")

cmd/proxsave/helpers_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func TestFormatDuration(t *testing.T) {
193193
{30 * time.Second, "30.0s"},
194194
{59 * time.Second, "59.0s"},
195195
{60 * time.Second, "1.0m"},
196-
{90 * time.Second, "1.5m"},
196+
{time.Minute + 30*time.Second, "1.5m"},
197197
{60 * time.Minute, "1.0h"},
198198
{90 * time.Minute, "1.5h"},
199199
}

docs/RESTORE_GUIDE.md

Lines changed: 165 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ Phase 13: pvesh SAFE Apply (Cluster SAFE Mode Only)
323323
└─ Offer to apply datacenter.cfg via pvesh
324324
325325
Phase 14: Post-Restore Tasks
326+
├─ Optional: Apply restored network config with rollback timer (requires COMMIT)
326327
├─ Recreate storage/datastore directories
327328
├─ Check ZFS pool status (PBS only)
328329
├─ Restart PVE/PBS services (if stopped)
@@ -709,7 +710,8 @@ Cluster backup detected. Choose how to restore the cluster database:
709710

710711
**Post-restore actions (SAFE mode)**:
711712
After export, the workflow offers interactive options to apply configurations via `pvesh`:
712-
1. **VM/CT configs**: Scans exported configs and applies them via `pvesh set /nodes/<node>/qemu/<vmid>/config`
713+
1. **VM/CT configs**: Scans exported configs (under `/etc/pve/nodes/<node>/...`) and applies them via `pvesh set /nodes/<node>/qemu/<vmid>/config`
714+
- If the target node hostname differs from the hostname stored in the backup (common after hardware migration / reinstall), ProxSave detects the mismatch and prompts you to select the exported node directory to import from (instead of silently reporting “No VM/CT configs found”).
713715
2. **Storage configuration**: Applies `storage.cfg` entries via `pvesh set /cluster/storage/<id>`
714716
3. **Datacenter configuration**: Applies `datacenter.cfg` via `pvesh set /cluster/config`
715717

@@ -722,6 +724,7 @@ Each action prompts for confirmation before execution.
722724
- Unmounts `/etc/pve` FUSE filesystem
723725
- Writes directly to `/var/lib/pve-cluster/config.db`
724726
- Restarts services with restored configuration
727+
- Avoids restoring files under `/etc/pve/*` while pmxcfs is stopped/unmounted (to prevent "shadowed" writes on the underlying disk). Those files are expected to come from the restored `config.db`.
725728

726729
**When to use**:
727730
- Complete disaster recovery
@@ -1348,6 +1351,21 @@ These configurations are included in every backup and can be restored using **th
13481351
Apply all VM/CT configs via pvesh? (y/N): y
13491352
```
13501353

1354+
**If the node name changed** (example: backup from `pve-old`, restore on `pve-new`), ProxSave prompts for the exported source node:
1355+
```
1356+
SAFE cluster restore: applying configs via pvesh (node=pve-new)
1357+
1358+
WARNING: VM/CT configs in this backup are stored under different node names.
1359+
Current node: pve-new
1360+
Select which exported node to import VM/CT configs from (they will be applied to the current node):
1361+
[1] pve-old (qemu=12, lxc=3)
1362+
[0] Skip VM/CT apply
1363+
Choice: 1
1364+
1365+
Found 15 VM/CT configs for exported node pve-old (will apply to current node pve-new)
1366+
Apply all VM/CT configs via pvesh? (y/N): y
1367+
```
1368+
13511369
6. **Confirm and watch progress**:
13521370
```
13531371
Applied VM/CT config 100 (webserver)
@@ -1639,6 +1657,53 @@ Backup source: Proxmox Virtual Environment (PVE)
16391657
Type "yes" to continue anyway or "no" to abort: _
16401658
```
16411659

1660+
### 4. Network Safe Apply (Optional)
1661+
1662+
If the **network** category is restored, ProxSave can optionally apply the
1663+
new network configuration immediately using a **transactional rollback timer**.
1664+
1665+
**Important (console recommended)**:
1666+
- Run the live network apply/commit step from the **local console** (physical console, IPMI/iDRAC/iLO, Proxmox console, or hypervisor console), not from SSH.
1667+
- If the restored network config changes the management IP or routes, your SSH session will drop and you may be unable to type `COMMIT`.
1668+
- In that case, ProxSave will treat the lack of `COMMIT` as “not confirmed” and will restore the previous network settings (rollback).
1669+
1670+
**How it works**:
1671+
- On live restores (writing to `/`), ProxSave **stages** network files first under `/tmp/proxsave/restore-stage-*` and does **not** overwrite `/etc/network/*` during archive extraction.
1672+
- After extraction, ProxSave performs a prevention-first **staged install**: it writes the staged files to disk (no reload), runs safe NIC repair + preflight validation, and **rolls back automatically** if validation fails (leaving the staged copy for review).
1673+
- If rollback backup creation fails (or ProxSave is not running as root), ProxSave keeps network files staged and avoids writing to `/etc`.
1674+
- When you choose to apply live, ProxSave (re)validates and reloads networking inside the rollback timer window.
1675+
- ProxSave arms a local rollback job **before** applying changes
1676+
- Rollback restores **only network-related files** using a dedicated archive under `/tmp/proxsave/network_rollback_backup_*` (so it won’t undo other restored categories)
1677+
- Rollback also prunes network config files that were **created after** the backup (e.g. extra files under `/etc/network/interfaces.d/`), so rollback returns to the exact pre-restore state
1678+
- The user has **180 seconds** to type `COMMIT`
1679+
- If `COMMIT` is not received, ProxSave triggers the rollback and restores the pre-restore network configuration
1680+
- If the network-only rollback archive is not available, ProxSave prompts before falling back to the full safety backup (or skipping live apply)
1681+
1682+
This protects SSH/GUI access during network changes.
1683+
1684+
**Health checks**:
1685+
- After applying changes, ProxSave runs local checks (SSH route if available, default route, link state, IP addresses, gateway ping, DNS config/resolve, local web UI port)
1686+
- On PVE systems, additional checks are included for cluster networking: `/etc/pve` (pmxcfs) mount status, `pve-cluster` / `corosync` service state, and `pvecm status` quorum
1687+
- The result is shown to help decide whether to type `COMMIT`
1688+
- Diagnostics are saved under `/tmp/proxsave/network_apply_*` (snapshots `before.txt` / `after.txt` / `after_rollback.txt` when relevant, `health_before.txt` / `health_after.txt`, `preflight.txt`, `plan.txt`, and `ifquery_*`)
1689+
1690+
**NIC name repair**:
1691+
- If physical NIC names changed after reinstall (e.g. `eno1``enp3s0`), ProxSave attempts an automatic mapping using backup network inventory (permanent MAC / MAC / PCI path / udev IDs like `ID_PATH`, `ID_NET_NAME_PATH`, `ID_NET_NAME_SLOT`, `ID_SERIAL`)
1692+
- When a safe mapping is found, `/etc/network/interfaces` and `/etc/network/interfaces.d/*` are rewritten before applying the network config
1693+
- If you skip live network apply, ProxSave may still install the staged config to disk (no reload) after safe NIC repair + preflight; if validation fails, it rolls back and keeps the staged copy.
1694+
- If a mapping would overwrite an interface name that already exists on the current system, ProxSave prompts before applying it (conflict-safe)
1695+
- If persistent NIC naming rules are detected (custom udev `NAME=` rules or systemd `.link` files), ProxSave warns and prompts before applying NIC repair to avoid conflicts with user-intended naming
1696+
- A backup of the pre-repair files is stored under `/tmp/proxsave/nic_repair_*`
1697+
1698+
**Preflight validation**:
1699+
- After NIC repair, ProxSave runs a **gate** validation of the ifupdown configuration before reloading networking (e.g. `ifup -n -a` / `ifup --no-act -a` / `ifreload --syntax-check -a`)
1700+
- If validation fails, live apply is aborted and the validator output is saved under `/tmp/proxsave/network_apply_*/preflight.txt`
1701+
- Additionally (diagnostics-only), ProxSave can run `ifquery --check -a` **before and after apply** to show how the runtime state matches the target config. Its output is saved under `/tmp/proxsave/network_apply_*/ifquery_*`. Note that `ifquery --check` can show `[fail]` **before apply** even when the config is valid (because the running state still reflects the old config).
1702+
- On staged installs/applies, a failed preflight triggers an **automatic rollback of network files** (no prompt), returning to the pre-restore state and keeping the staged copy for review.
1703+
1704+
**Result reporting**:
1705+
- If you do not type `COMMIT`, ProxSave completes the restore with warnings and reports that the original network settings were restored (including the current IP, when detectable), plus the rollback log path.
1706+
16421707
### 4. Hard Guards
16431708

16441709
**Path Traversal Prevention**:
@@ -2002,9 +2067,105 @@ zfs list
20022067
# If ZFS, import pool
20032068
zpool import <pool-name>
20042069

2005-
# If directory, create it
2006-
mkdir -p /mnt/datastore/{.chunks,.lock}
2007-
chown backup:backup /mnt/datastore -R
2070+
# If directory-based datastore (non-ZFS), verify permissions for backup user
2071+
# NOTE:
2072+
# - On live restores, ProxSave stages PBS datastore/job configuration first under `/tmp/proxsave/restore-stage-*`
2073+
# and applies it safely after checking the current system state.
2074+
# - If a datastore path looks like a mountpoint location (e.g. under `/mnt`) but resolves to the root filesystem,
2075+
# ProxSave will **defer** that datastore definition (it will NOT be written to `datastore.cfg`), to avoid ending up
2076+
# with a broken datastore entry that blocks re-creation on a new/empty disk. Deferred entries are saved under
2077+
# `/tmp/proxsave/datastore.cfg.deferred.*` for manual review.
2078+
# - ProxSave may create missing datastore directories and fix `.lock`/ownership, but it will NOT format disks.
2079+
# - To avoid accidental writes to the wrong disk, ProxSave will skip datastore directory initialization if the
2080+
# datastore path looks like a mountpoint location (e.g. under /mnt) but resolves to the root filesystem.
2081+
# In that case, mount/import the datastore disk/pool first, then restart PBS (or re-run restore).
2082+
# - If the datastore path is not empty and contains unexpected files/directories, ProxSave will not touch it.
2083+
ls -ld /mnt/datastore /mnt/datastore/<DatastoreName> 2>/dev/null
2084+
namei -l /mnt/datastore/<DatastoreName> 2>/dev/null || true
2085+
2086+
# Common fix (adjust to your datastore path)
2087+
chown backup:backup /mnt/datastore && chmod 750 /mnt/datastore
2088+
chown -R backup:backup /mnt/datastore/<DatastoreName> && chmod 750 /mnt/datastore/<DatastoreName>
2089+
```
2090+
2091+
---
2092+
2093+
**Issue: "Bad Request (400) unable to read /etc/resolv.conf (No such file or directory)"**
2094+
2095+
**Cause**: `/etc/resolv.conf` is missing or a broken symlink. This can happen after a restore if a previous backup contained an invalid symlink (e.g. pointing to `../commands/resolv_conf.txt`), or if the target system uses `systemd-resolved` and the expected `/run/systemd/resolve/*` files are not present.
2096+
2097+
**Solution**:
2098+
```bash
2099+
ls -la /etc/resolv.conf
2100+
readlink /etc/resolv.conf 2>/dev/null || true
2101+
2102+
# If the link is broken or points to commands/resolv_conf.txt, replace it:
2103+
rm -f /etc/resolv.conf
2104+
2105+
if [ -e /run/systemd/resolve/resolv.conf ]; then
2106+
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
2107+
elif [ -e /run/systemd/resolve/stub-resolv.conf ]; then
2108+
ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
2109+
else
2110+
# Fallback: static DNS (adjust to your environment)
2111+
printf "nameserver 1.1.1.1\nnameserver 8.8.8.8\noptions timeout:2 attempts:2\n" > /etc/resolv.conf
2112+
chmod 644 /etc/resolv.conf
2113+
fi
2114+
```
2115+
2116+
Note: newer ProxSave versions attempt to auto-repair `/etc/resolv.conf` during restore when the `network` category is selected.
2117+
2118+
---
2119+
2120+
**Issue: "Bad Request (400) parsing /etc/proxmox-backup/datastore.cfg (expected section properties)"**
2121+
2122+
**Cause**: In PBS, properties inside a `datastore:` section must be indented. A malformed file (often from manual edits or very old configs) will prevent PBS from loading datastore config.
2123+
2124+
**Solution**:
2125+
```bash
2126+
# ProxSave will attempt to auto-normalize datastore.cfg during restore and store a backup under /tmp/proxsave/,
2127+
# but you can also fix it manually:
2128+
cp -a /etc/proxmox-backup/datastore.cfg /root/datastore.cfg.bak.$(date +%F_%H%M%S)
2129+
2130+
# Example of correct indentation:
2131+
# datastore: Data1
2132+
# gc-schedule 0/2:00
2133+
# path /mnt/datastore/Data1
2134+
2135+
editor /etc/proxmox-backup/datastore.cfg
2136+
systemctl restart proxmox-backup proxmox-backup-proxy
2137+
```
2138+
2139+
---
2140+
2141+
**Issue: "unable to read prune/verification job config ... syntax error (expected header)"**
2142+
2143+
**Cause**: PBS job config files (`/etc/proxmox-backup/prune.cfg`, `/etc/proxmox-backup/verification.cfg`) are empty or malformed. PBS expects a section header at the first non-comment line; an empty file can trigger parse errors.
2144+
2145+
**Restore behavior**:
2146+
- On live restores, ProxSave stages PBS job config files and will **remove** empty staged job configs instead of writing a 0-byte file (to avoid breaking PBS parsing).
2147+
2148+
**Manual fix**:
2149+
```bash
2150+
rm -f /etc/proxmox-backup/prune.cfg /etc/proxmox-backup/verification.cfg
2151+
systemctl restart proxmox-backup proxmox-backup-proxy
2152+
```
2153+
2154+
---
2155+
2156+
**Issue: "Datastore error: Is a directory (os error 21)"**
2157+
2158+
**Cause**: PBS expects a lock file at `<datastore-path>/.lock`. If `.lock` is a directory (common after manual fixes or incorrect initialization), PBS will fail to open it and the datastore becomes unavailable.
2159+
2160+
**Solution**:
2161+
```bash
2162+
P=/mnt/datastore/<DatastoreName>
2163+
ls -ld "$P/.lock"
2164+
2165+
# If .lock is a directory, replace it with a file:
2166+
rm -rf "$P/.lock" && touch "$P/.lock" && chown backup:backup "$P/.lock"
2167+
2168+
systemctl restart proxmox-backup proxmox-backup-proxy
20082169
```
20092170

20102171
---

docs/RESTORE_TECHNICAL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ func extractSelectiveArchive(
860860
mode,
861861
logFile,
862862
logPath,
863+
nil, // skipFn (optional)
863864
)
864865

865866
return logPath, err
@@ -1247,6 +1248,7 @@ func extractArchiveNative(
12471248
mode RestoreMode,
12481249
logFile *os.File,
12491250
logFilePath string,
1251+
skipFn func(entryName string) bool,
12501252
) error {
12511253
// 1. Open archive with decompression
12521254
file, _ := os.Open(archivePath)

docs/TROUBLESHOOTING.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Complete troubleshooting guide for Proxsave with common issues, solutions, and d
1212
- [Encryption Issues](#4-encryption-issues)
1313
- [Disk Space Issues](#5-disk-space-issues)
1414
- [Email Notification Issues](#6-email-notification-issues)
15+
- [Restore Issues](#7-restore-issues)
1516
- [Debug Procedures](#debug-procedures)
1617
- [Getting Help](#getting-help)
1718
- [Related Documentation](#related-documentation)
@@ -549,6 +550,24 @@ MIN_DISK_SPACE_PRIMARY_GB=5 # Lower threshold
549550
# Add more storage or clean unnecessary files
550551
```
551552

553+
---
554+
### 7. Restore Issues
555+
556+
#### Error during network preflight: `addr_add_dry_run() got an unexpected keyword argument 'nodad'`
557+
558+
**Symptoms**:
559+
- Restore networking preflight fails when running `ifup -n -a`
560+
- Log contains: `NetlinkListenerWithCache.addr_add_dry_run() got an unexpected keyword argument 'nodad'`
561+
562+
**Cause**:
563+
- A Proxmox-packaged `ifupdown2` version may ship a Python signature mismatch between `addr_add()` and `addr_add_dry_run()` (dry-run path), which crashes `ifup -n` when `nodad` is used.
564+
565+
**What ProxSave does**:
566+
- During restore, ProxSave can apply a guarded hotfix (only when needed) by patching `/usr/share/ifupdown2/lib/nlcache.py` and writing a timestamped `.bak.*` backup first.
567+
568+
**Recovery / rollback**:
569+
- To revert the hotfix, restore the `.bak.*` copy back onto `nlcache.py`, or upgrade `ifupdown2` when Proxmox publishes a fixed build.
570+
552571
---
553572

554573
## Debug Procedures

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ toolchain go1.25.5
66

77
require (
88
filippo.io/age v1.3.1
9-
github.com/gdamore/tcell/v2 v2.13.6
9+
github.com/gdamore/tcell/v2 v2.13.7
1010
github.com/rivo/tview v0.42.0
11-
golang.org/x/crypto v0.46.0
11+
golang.org/x/crypto v0.47.0
1212
golang.org/x/term v0.39.0
1313
golang.org/x/text v0.33.0
1414
)

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ filippo.io/hpke v0.4.0 h1:p575VVQ6ted4pL+it6M00V/f2qTZITO0zgmdKCkd5+A=
88
filippo.io/hpke v0.4.0/go.mod h1:EmAN849/P3qdeK+PCMkDpDm83vRHM5cDipBJ8xbQLVY=
99
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
1010
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
11-
github.com/gdamore/tcell/v2 v2.13.6 h1:ZAKaC+z7EHtDlELEVw5qxvO560cCXOtn0Su4YqMahJM=
12-
github.com/gdamore/tcell/v2 v2.13.6/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo=
11+
github.com/gdamore/tcell/v2 v2.13.7 h1:yfHdeC7ODIYCc6dgRos8L1VujQtXHmUpU6UZotzD6os=
12+
github.com/gdamore/tcell/v2 v2.13.7/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo=
1313
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
1414
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
1515
github.com/rivo/tview v0.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c=
@@ -19,8 +19,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
1919
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
2020
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2121
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
22-
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
23-
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
22+
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
23+
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
2424
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
2525
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
2626
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=

internal/backup/archiver_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ func TestFormatDuration(t *testing.T) {
401401
want string
402402
}{
403403
{30 * time.Second, "30.0s"},
404-
{90 * time.Second, "1.5m"},
404+
{time.Minute + 30*time.Second, "1.5m"},
405405
{2 * time.Hour, "2.0h"},
406406
}
407407

0 commit comments

Comments
 (0)