Skip to content

New extension: nvme-conversion — Convert VM disk controllers between SCSI and NVMe#9858

Open
jonathanbrenes wants to merge 3 commits into
Azure:mainfrom
jonathanbrenes:feature/nvme-conversion
Open

New extension: nvme-conversion — Convert VM disk controllers between SCSI and NVMe#9858
jonathanbrenes wants to merge 3 commits into
Azure:mainfrom
jonathanbrenes:feature/nvme-conversion

Conversation

@jonathanbrenes
Copy link
Copy Markdown
Contributor

New extension: nvme-conversion — Convert VM disk controllers between SCSI and NVMe

Related command

az nvme-conversion check, az nvme-conversion convert

Description

Adds a new Azure CLI extension that converts Azure VM disk controllers between SCSI and NVMe. This is a preview release (1.0.0b1).

Key capabilities:

  • az nvme-conversion check — Pre-flight validation (SKU capabilities, OS readiness, VM generation, ADE, unmanaged-disk detection) without making changes
  • az nvme-conversion convert — End-to-end conversion: validates prerequisites, prepares the OS, resizes the VM to an NVMe-capable SKU, and restarts
  • OS preparation for Linux (initrd rebuild, fstab migration, io_timeout, udev rules) and Windows (stornvme driver verification via RunCommand)
  • Dry-run mode for Linux VMs (--dry-run)
  • Auto-detection of current controller type and target VM size (e.g. Standard_D2s_v5Standard_D2s_v6)
  • Rejects unmanaged (page-blob) OS disks with a clear error
  • RunCommand calls have a 600s timeout to prevent hangs
  • Custom confirmation prompt naming the VM and target controller

Testing:

  • 56 unit tests passed, 2 skipped
  • azdev style nvme-conversion (pylint + flake8): PASSED
  • Live end-to-end validation against 6 RHEL 9 LVM Gen2 VMs in westus3: all converted Standard_D2s_v5 (SCSI) → Standard_D2s_v6 (NVMe) and verified post-conversion
  • Unmanaged-disk guard validated live against an unmanaged-disk VM

General Guidelines

  • Have you run azdev style <YOUR_EXT> locally? (pip install azdev required)
  • Have you run python scripts/ci/test_index.py -q locally? (pip install wheel==0.30.0 required)
  • My extension version conforms to the Extension version schema

For new extensions:

About Extension Publish

There is a pipeline to automatically build, upload and publish extension wheels.
Once your pull request is merged into main branch, a new pull request will be created to update src/index.json automatically.
You only need to update the version information in file setup.py and historical information in file HISTORY.rst in your PR but do not modify src/index.json.

…SCSI and NVMe

Adds the nvme-conversion extension that orchestrates the full SCSI<->NVMe
conversion lifecycle for Azure VMs:
- Pre-flight validation (Gen2, ADE, SKU capabilities, OS readiness)
- OS preparation via RunCommand (Windows stornvme, Linux initramfs/grub/fstab)
- VM deallocate, OS disk capability update, VM resize + controller change
- Optional VM start with rollback instructions

Commands:
  az nvme-conversion check   - Validate VM readiness without changes
  az nvme-conversion convert - Full conversion with --fix-os, --dry-run, --no-wait

Tested on: Ubuntu 24.04, RHEL 8/9/10, SLES 15 SP6, Azure Linux 4,
Windows Server 2019/2022 — 20 VMs, 56 unit tests, azdev style/test/linter passed.
- custom.py: reject unmanaged (page-blob) OS disks in _validate_vm with a clear ValidationError.

- custom.py: add _get_vm_skus() helper; share resource_skus.list() result between _resolve_vm_size and _validate_sku to avoid duplicate API calls.

- custom.py: switch user-progress logger.warning calls to logger.info (Gen2 banner, controller arrows, SKU validating, VM updated, VM started, etc.); reserve warnings for actual problems.

- custom.py: collapse _check_os_readiness into a thin wrapper around _prepare_os(fix_os=False, dry_run=False) to remove duplicated logic.

- custom.py: validate SKU capabilities across all vm.zones, not just vm.zones[0].

- _linux_checks.py / _windows_checks.py: add timeout=600 to begin_run_command(...).result() calls so RunCommand cannot hang indefinitely.

- commands.py: replace confirmation=True with a custom yes/no prompt that names the VM and target controller for the convert command.

- setup.py: pin azure-mgmt-compute>=30.0.0.

Validated end-to-end against live Azure VMs in westus3:

- 6/6 RHEL 9 LVM Gen2 VMs converted Standard_D2s_v5 (SCSI) -> Standard_D2s_v6 (NVMe) and verified post-conversion.

- Unmanaged-disk guard verified live: az nvme-conversion check on an unmanaged-disk VM fails with the new clear error message.

- pytest: 56 passed, 2 skipped. azdev style (pylint + flake8): PASSED.
Copilot AI review requested due to automatic review settings May 11, 2026 21:36
@azure-client-tools-bot-prd
Copy link
Copy Markdown

Validation for Breaking Change Starting...

Thanks for your contribution!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new Azure CLI extension (nvme-conversion) to pre-flight check and convert Azure VM disk controllers between SCSI and NVMe, including OS readiness checks/fixes and user-facing help/output.

Changes:

  • Introduces az nvme-conversion check and az nvme-conversion convert commands with SKU/ADE/Gen2/power-state validation and conversion orchestration.
  • Adds OS preparation implementations for Linux (embedded RunCommand bash script) and Windows (stornvme checks/fix via RunCommand).
  • Adds unit + mocked end-to-end tests plus extension packaging metadata and docs.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/nvme-conversion/setup.py Extension packaging metadata and dependencies
src/nvme-conversion/setup.cfg Placeholder config file
src/nvme-conversion/azext_nvme_conversion/custom.py Primary check/convert orchestration and internal helpers
src/nvme-conversion/azext_nvme_conversion/commands.py CLI command registration + confirmation/table formatting wiring
src/nvme-conversion/azext_nvme_conversion/_params.py CLI parameters and validators wiring
src/nvme-conversion/azext_nvme_conversion/_validators.py Input validation for --vm-size and --sleep-seconds
src/nvme-conversion/azext_nvme_conversion/_windows_checks.py Windows RunCommand checks/fix + version validation
src/nvme-conversion/azext_nvme_conversion/_linux_checks.py Linux RunCommand wrapper and error parsing
src/nvme-conversion/azext_nvme_conversion/_linux_script.py Embedded bash script for Linux NVMe readiness + fixes
src/nvme-conversion/azext_nvme_conversion/_format.py Table output transformers for -o table
src/nvme-conversion/azext_nvme_conversion/_help.py Help text and examples
src/nvme-conversion/azext_nvme_conversion/_client_factory.py Compute client factory
src/nvme-conversion/azext_nvme_conversion/azext_metadata.json Extension metadata (preview + min CLI core)
src/nvme-conversion/azext_nvme_conversion/tests/latest/test_nvme_conversion.py Unit + mocked end-to-end tests
src/nvme-conversion/README.md User-facing overview and usage
src/nvme-conversion/HISTORY.rst Initial release notes
src/nvme-conversion/DEVELOPMENT.md Development guide and architecture notes
src/nvme-conversion/ROADMAP.md Implementation roadmap and design notes
src/nvme-conversion/TESTING.md Live test tracker

Comment thread src/nvme-conversion/azext_nvme_conversion/_windows_checks.py Outdated
Comment on lines +64 to +67
# Resolve VM size: use current if not specified and current supports the target controller
_status('[2/8] Resolving VM size...')
vm_size = _resolve_vm_size(compute_client, vm, vm_size, new_controller_type,
ignore_sku_check, vm_skus=vm_skus)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b9e5df3. Updated HISTORY.rst and PR description to accurately describe behavior: auto-detects controller type; reuses current VM size if compatible, otherwise requires --vm-size.

Comment thread src/nvme-conversion/azext_nvme_conversion/commands.py Outdated
Comment thread src/nvme-conversion/azext_nvme_conversion/custom.py Outdated
Comment on lines +245 to +247
# Windows version
if os_type == 'Windows' and not ignore_windows_version_check:
_status('[5/7] Checking Windows version...')
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in b9e5df3. Renumbered to [5/7] for Windows version check and [6/7] for SKU validation.

Comment thread src/nvme-conversion/azext_nvme_conversion/_linux_script.py
Comment thread src/nvme-conversion/azext_nvme_conversion/_linux_script.py
Comment thread src/nvme-conversion/setup.py Outdated
Comment thread src/nvme-conversion/setup.py Outdated
Comment thread src/nvme-conversion/TESTING.md Outdated
@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented May 11, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown
Contributor

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

@github-actions
Copy link
Copy Markdown
Contributor

@yonzhan yonzhan requested a review from yanzhudd May 11, 2026 22:56
@yonzhan yonzhan requested a review from necusjz May 11, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants