Fix ICM 51000001082652: VMBackup extension fails to import on Python 3.13+ - #2196
Open
vupadhyay-ms wants to merge 3 commits into
Open
Fix ICM 51000001082652: VMBackup extension fails to import on Python 3.13+#2196vupadhyay-ms wants to merge 3 commits into
vupadhyay-ms wants to merge 3 commits into
Conversation
… 51000001082652)
Ubuntu 26.04 / Py 3.14 removed the stdlib modules 'crypt' (Py 3.13),
'distutils' (Py 3.12), and 'imp' (Py 3.12). VMBackup imports all three
unconditionally, so handle.py -enable crashes at file-load time before
any snapshot logic runs -> CRP reports VMExtensionProvisioningTimeout ->
customer backup fails.
Changes (2 files):
* VMBackup/main/WaagentLib.py
- Add PEP 263 encoding declaration (defense-in-depth vs future Unicode)
- Wrap 'import crypt' in try/except; crypt = None fallback
- Replace 'from distutils.version import LooseVersion' with 3-tier ladder:
packaging.version -> distutils.version -> ASCII-only hand-written class
- Guard gen_password_hash() with 'if crypt is None: raise NotImplementedError'
* VMBackup/main/Utils/WAAgentUtil.py
- Replace 'except ImportError' fallback with hasattr(importlib.util,
'module_from_spec') capability check (Py 2.7 raised AttributeError,
not ImportError - this was one of the PR Azure#2124 regressions)
- Drop outer 'except Exception: raise Exception(Cant load waagent)'
wrapper that was hiding the real traceback in ICM logs
This is a corrected re-landing of PR Azure#2124 (reverted by PR Azure#2163 due to
ICM 783505554). Defenses vs those regressions:
- Pure ASCII in modified files (byte-scan verified: 0 non-ASCII bytes)
- PEP 263 encoding declaration future-proofs against Unicode leaks
- hasattr() capability check is exception-type-independent
- Tier 3 LooseVersion class inherits from 'object' (new-style, correct
Py 2.7 rich-comparison dispatch)
Tested on Py 2.7 (Docker), 3.10, 3.12, 3.13, 3.14: 18/18 PASS.
End-to-end portal-triggered backup on Py 3.14 with branch code in
/var/lib/waagent/... completed with extension status: success and
snapshot URIs written to blob storage.
Fixes: ICM 51000001082652
Re-lands: PR Azure#2124 (reverted in PR Azure#2163)
Regression-tests: ICM 783505554
Related: Azure#2172
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Encoding declaration retained; only the 4-line comment block above it removed per review feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Author
|
@microsoft-github-policy-service agree company="Microsoft" |
Combine the strengths of both fallback shims discussed in review: - Keep pre-release precedence (alpha < beta < rc < release) via negative sentinels and the [.\-_] separator split (broader than a digits-only tokenizer for kernel-style strings). - Add explicit str() coercion when tuple positions have mismatched types so Py 3 does not raise TypeError comparing int vs str (e.g. '1.0.5' vs '1.0.foo'). This matches the safe pattern from PR Azure#2177. - Add __ne__ so Py 2.7 does not fall back to identity comparison; Py 3 auto-derives it but Py 2.7 does not. - Add __repr__ for cleaner logs and debugging. - Fold six near-identical rich-comparison methods into a single _cmp() helper and one-line delegates, halving the surface area. No behavior change for the 4 in-tree call sites (all pass numeric plugin version strings such as '1.0.9231.0'); shim now degrades safely on arbitrary inputs instead of raising. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5519adfb-3554-4ee6-84ff-61ec7bab7e1a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Issue
Customer VM (Ubuntu 26.04 / Py 3.14) fails backup. Extension log shows:
The 3 stdlibs
cryptWaagentLib.py:26(bareimport crypt)distutilsWaagentLib.py:59(from distutils.version import LooseVersion)impWAAgentUtil.py:69(import impfallback)Python removed these modules. Our code imports them unconditionally → extension crashes at file-load time →
VMExtensionProvisioningTimeout→ customer backup fails.History (why previous fix was reverted)
→in fallback class docstring → Py 2SyntaxErrorat parse timeexcept ImportErrorfailed to catchAttributeErrorfromimportlib.util.module_from_specon Py 2.7This PR re-lands the fix with those 2 bugs corrected.
The Fix — 5 edits, 2 files
VMBackup/main/WaagentLib.pyEdit 1 — Add PEP 263 encoding declaration
# -*- coding: utf-8 -*-Prevents future Unicode-in-source regressions (prevents ICM 783505554 class of bug).
Edit 2 — Wrap
import cryptcryptis dead code (VMBackup never callsgen_password_hash). Wrapping stops the crash.Edit 3 — Replace
distutils.LooseVersionwith 3-tier ladderGuarantees
LooseVersionresolves on every Python 2.7 → 3.14. Tier 3 class is identical to PR #2124's, with 2 corrections: (a) inherits fromobjectfor Py 2.7 rich-comparison correctness, (b) ASCII->instead of Unicode→.Edit 4 — Defensive guard in
gen_password_hash()Never hit today; fails loudly if some future caller reaches this on Py 3.13+.
VMBackup/main/Utils/WAAgentUtil.pyEdit 5 — Replace exception-based fallback with capability check
Testing —
Test Setup: Azure Ubuntu 24.04 VM +
python3.10 / 3.12 / 3.13 / 3.14(via deadsnakes PPA) + Dockerpython:2.7for regression coverage.py_compileon both fileshandle.py -enableexit 0