VMBackup: Fix Python 3.12+ compatibility for Azure Linux 4.0#2177
VMBackup: Fix Python 3.12+ compatibility for Azure Linux 4.0#2177jonathanbrenes wants to merge 1 commit into
Conversation
Evidence: Extension is broken on Azure Linux 4.0Production failureOn an unpatched Azure Linux 4.0 VM (Python 3.14.3), the VMSnapshot extension cannot start at all. Every enable attempt exits with code 1, causing Azure Backup jobs to fail with error Extension log ( Crash traceback — cascading The import chain All 4 removed APIs confirmed brokenAfter patching — extension worksUnit tests on AZL4 VM (8/8 pass): End-to-end backup — PASS:
Backward compatibility — 15 distros, all PASS
All patches are guarded by |
The VMSnapshot extension crashes on Azure Linux 4.0 (Python 3.14) due to
four Python APIs removed in recent versions. The extension fails at import
time, causing Azure Backup jobs to fail with error 400039 after hours of
retries.
Root cause — removed Python APIs used by VMBackup:
- distutils.version.LooseVersion (removed in 3.12)
- imp module (removed in 3.12)
- platform.dist() (removed in 3.8)
- platform.linux_distribution() (removed in 3.8)
Changes:
WaagentLib.py:
- Add try/except for LooseVersion import with a minimal shim class
that provides comparison operators (__lt__, __gt__, __eq__, __le__,
__ge__) using regex-based version parsing.
Note: Python never added a stdlib replacement for LooseVersion.
PEP 632 recommends the third-party `packaging` library, but it is
not suitable here: (1) it is not in the stdlib and may be absent on
minimal installs, (2) it enforces strict PEP 440 parsing and rejects
the loose version strings this codebase passes, and (3) adding a
dependency to a VM extension that must run on every Linux distro from
RHEL 7 (Python 2.7) to AZL4 (Python 3.14) is fragile. The inline
shim is zero-dependency and drop-in compatible.
WAAgentUtil.py:
- Add try/except around the `import imp` fallback so it does not crash
on Python 3.12+ when the primary importlib path fails
HandlerUtil.py:
- Replace platform.dist() in get_dist_info() with /etc/os-release
parsing (NAME + VERSION fields)
- Fix invalid escape sequence: replace('\/', '/') was a no-op
(invalid escape treated as literal char); changed to
replace('\\/', '/') which correctly replaces \/ with /
patch/__init__.py:
- Add /etc/os-release ID parsing to DistInfo() fallback
- Add 'azurelinux' mapping in GetMyPatching() -> AzureLinuxPatching
patch/AzureLinuxPatching.py (new):
- Dedicated patching class for Azure Linux 4.0
- All binary paths set to /usr/bin/ (AZL4 merged /usr)
- Uses dnf for package installation
Tested:
- End-to-end Azure Backup on AZL4 VM: PASS (26 min, all phases)
- Backward compat across 10 distros (Python 3.6-3.14): all PASS
RHEL 8/9, Oracle Linux 9, SLES 15/16, Debian 12,
Ubuntu 20.04/22.04/24.04, Azure Linux 4.0
986e482 to
037ab48
Compare
Problem
The VMSnapshot (VMBackup) extension crashes on Azure Linux 4.0 (Python 3.14) due to four Python APIs that were removed in recent Python versions. The extension fails at import time, causing Azure Backup jobs to fail with error 400039 after hours of retries.
Removed APIs used by VMBackup
distutils.version.LooseVersionimpmoduleplatform.dist()platform.linux_distribution()Changes
WaagentLib.pytry/exceptforLooseVersionimport with a minimal shim class providing comparison operators (__lt__,__gt__,__eq__,__le__,__ge__) via regex-based version parsing.WAAgentUtil.pytry/exceptaround theimport impfallback so it doesn't crash on Python 3.12+ when the primaryimportlib.utilpath fails.HandlerUtil.pyplatform.dist()inget_dist_info()with/etc/os-releaseparsing (NAME+VERSIONfields).replace('\/', '/')was a no-op (invalid escape treated as literal); changed toreplace('\\/', '/').patch/__init__.py/etc/os-releaseIDparsing toDistInfo()fallback for distros whereplatform.linux_distribution()is gone.'azurelinux'mapping inGetMyPatching()→AzureLinuxPatching.patch/AzureLinuxPatching.py(new)/usr/bin/(AZL4 uses merged/usr).dnffor package installation.Testing
End-to-end Azure Backup on AZL4
Full backup job completed successfully (26 min, all phases: pre-snapshot, snapshot, post-snapshot).
Backward compatibility
All patches are no-ops on older Python versions (guarded by
try/exceptwith fallback to original imports). Verified across 15 distros (Python 2.7.5 – 3.14.3), including end-to-end Azure Backup on all Python 2 VMs: