Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
62773ed
Add test case for vm zone movement
william051200 Apr 21, 2026
d1aa52a
Generate new aaz code for vm command
william051200 Apr 21, 2026
45415da
Add zone_movement argument in vm create and update
william051200 Apr 21, 2026
d72166c
Updated converter
william051200 Apr 22, 2026
95dc8aa
Generate aaz code for vm deallocate
william051200 Apr 22, 2026
75c99a7
Add test case for vm switching zone
william051200 Apr 22, 2026
703115e
Handle zone changing in vm update
william051200 Apr 22, 2026
509b969
Hide force deallocate argument for vm deallocate command
william051200 Apr 22, 2026
e854dbc
Update logging message
william051200 Apr 22, 2026
92f7910
Update code style
william051200 Apr 22, 2026
fa180cc
Update network test case recording
william051200 Apr 23, 2026
9162539
Update vm test case recording
william051200 Apr 23, 2026
524bae2
Update backup test case recording
william051200 Apr 23, 2026
df7c5b9
Update monitor test case recording
william051200 Apr 23, 2026
5348560
Update resource test case recording
william051200 Apr 23, 2026
8a0b329
Update sqlvm test case recording
william051200 Apr 23, 2026
c08f066
Revert changes
william051200 Apr 23, 2026
e98f567
Update vm test case recording
william051200 Apr 23, 2026
7d4c16d
Update vm test case recording
william051200 Apr 23, 2026
ff4b09a
Update code
william051200 Apr 23, 2026
1b569b8
Update recording
william051200 Apr 24, 2026
5baf6be
Update vm deallocate aaz code
william051200 Apr 24, 2026
ab49263
Update test case and recordings
william051200 Apr 24, 2026
42f11cf
Update test case and recordings
william051200 Apr 24, 2026
c7de1d7
Update test case
william051200 Apr 27, 2026
c23abc5
Update test case and re-record test case
william051200 Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ def load_arguments(self, _):
c.argument('align_regional_disks_to_vm_zone', options_list=['--align-regional-disks-to-vm-zone', '--align-regional-disks'], arg_type=get_three_state_flag(), min_api='2024-11-01', help='Specify whether the regional disks should be aligned/moved to the VM zone. This is applicable only for VMs with placement property set. Please note that this change is irreversible.')
c.argument('key_incarnation_id', type=int, min_api='2024-11-01', help='Increase the value of this property allows user to reset the key used for securing communication channel between guest and host.')
c.argument('security_type', arg_type=get_enum_type(["TrustedLaunch", "Standard", "ConfidentialVM"], default=None), help='Specify the security type of the virtual machine. The value Standard can be used if subscription has feature flag UseStandardSecurityType registered under Microsoft.Compute namespace. Refer to https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/preview-features for steps to enable required feature.')
c.argument('zone_movement', arg_type=get_three_state_flag(), help='Indicates if zone movement is enabled. By default isEnabled is set to false i.e VM can\'t be moved from one zone to another.')
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

--zone-movement is a service/API-version gated feature (per issue metadata). Without a min_api guard here, the argument will appear in profiles/clouds where the property isn’t supported and will fail at runtime. Add an appropriate min_api (and/or a validator check) to gate the argument.

Suggested change
c.argument('zone_movement', arg_type=get_three_state_flag(), help='Indicates if zone movement is enabled. By default isEnabled is set to false i.e VM can\'t be moved from one zone to another.')
c.argument('zone_movement', arg_type=get_three_state_flag(), min_api='2024-11-01', help='Indicates if zone movement is enabled. By default isEnabled is set to false i.e VM can\'t be moved from one zone to another.')

Copilot uses AI. Check for mistakes.

with self.argument_context('vm create', arg_group='Storage') as c:
c.argument('attach_os_disk', help='Attach an existing OS disk to the VM. Can use the name or ID of a managed disk or the URI to an unmanaged disk VHD.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def build_vm_resource( # pylint: disable=too-many-locals, too-many-statements,
zone_placement_policy=None, include_zones=None, exclude_zones=None, align_regional_disks_to_vm_zone=None,
wire_server_mode=None, imds_mode=None, wire_server_access_control_profile_reference_id=None,
imds_access_control_profile_reference_id=None, key_incarnation_id=None, add_proxy_agent_extension=None,
disk_iops_read_write=None, disk_mbps_read_write=None):
disk_iops_read_write=None, disk_mbps_read_write=None, zone_movement=None):

os_caching = disk_info['os'].get('caching')

Expand Down Expand Up @@ -588,6 +588,16 @@ def _build_storage_profile():
vm_properties = {'hardwareProfile': {'vmSize': size}, 'networkProfile': {'networkInterfaces': nics},
'storageProfile': _build_storage_profile()}

resiliency_profile = {}
if zone_movement is not None:
resiliency_profile.update({
'zoneMovement': {
'isEnabled': zone_movement
}
})
if resiliency_profile:
vm_properties['resiliencyProfile'] = resiliency_profile

scheduled_events_policy = {}
if additional_scheduled_events is not None:
scheduled_events_policy.update({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
from ._assign import *
from ._remove import *
from ._show import *
from ._wait import *
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class Create(AAZCommand):
"""

_aaz_info = {
"version": "2025-04-01",
"version": "2025-11-01",
"resources": [
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.compute/virtualmachines/{}", "2025-04-01"],
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.compute/virtualmachines/{}", "2025-11-01"],
]
Comment on lines 18 to 22
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

PR metadata/linked issue indicates a minimum Compute API version of 2025-04-01, but these vm create/update/show operations are pinned to 2025-11-01. Please confirm the minimum required version for zone movement and either keep the API version at the minimum needed (to maximize cloud/profile compatibility) or update the PR description accordingly.

Copilot uses AI. Check for mistakes.
}

Expand Down Expand Up @@ -262,6 +262,11 @@ def _build_arguments_schema(cls, *args, **kwargs):
help="Specifies information about the proximity placement group that the virtual machine should be assigned to. Minimum api-version: 2018-04-01.",
)
cls._build_args_sub_resource_create(_args_schema.proximity_placement_group)
_args_schema.resiliency_profile = AAZObjectArg(
options=["--resiliency-profile"],
arg_group="Properties",
help="Resiliency profile for the virtual machine.",
)
_args_schema.scheduled_events_policy = AAZObjectArg(
options=["--scheduled-events-policy"],
arg_group="Properties",
Expand Down Expand Up @@ -881,6 +886,18 @@ def _build_arguments_schema(cls, *args, **kwargs):
enum={"Http": "Http", "Https": "Https"},
)

resiliency_profile = cls._args_schema.resiliency_profile
resiliency_profile.zone_movement = AAZObjectArg(
options=["zone-movement"],
help="Zone movement configuration.",
)

zone_movement = cls._args_schema.resiliency_profile.zone_movement
zone_movement.is_enabled = AAZBoolArg(
options=["is-enabled"],
help="Indicates if zone movement is enabled. By default isEnabled is set to false i.e VM can't be moved from one zone to another.",
)

scheduled_events_policy = cls._args_schema.scheduled_events_policy
scheduled_events_policy.all_instances_down = AAZObjectArg(
options=["all-instances-down"],
Expand Down Expand Up @@ -979,7 +996,7 @@ def _build_arguments_schema(cls, *args, **kwargs):
security_profile.security_type = AAZStrArg(
options=["security-type"],
help="Specifies the SecurityType of the virtual machine. It has to be set to any specified value to enable UefiSettings. The default behavior is: UefiSettings will not be enabled unless this property is set.",
enum={"ConfidentialVM": "ConfidentialVM", "TrustedLaunch": "TrustedLaunch"},
enum={"ConfidentialVM": "ConfidentialVM", "Standard": "Standard", "TrustedLaunch": "TrustedLaunch"},
)
security_profile.uefi_settings = AAZObjectArg(
options=["uefi-settings"],
Expand Down Expand Up @@ -1114,6 +1131,11 @@ def _build_arguments_schema(cls, *args, **kwargs):
options=["source-resource"],
help="The source resource identifier. It can be a snapshot, or disk restore point from which to create a disk.",
)
_element.storage_fault_domain_alignment = AAZStrArg(
options=["storage-fault-domain-alignment"],
help="Specifies the storage fault domain alignment type for the disk.",
enum={"Aligned": "Aligned", "BestEffortAligned": "BestEffortAligned"},
)
_element.to_be_detached = AAZBoolArg(
options=["to-be-detached"],
help="Specifies whether the data disk is in process of detachment from the VirtualMachine/VirtualMachineScaleset",
Expand Down Expand Up @@ -1212,6 +1234,11 @@ def _build_arguments_schema(cls, *args, **kwargs):
help="This property allows you to specify the type of the OS that is included in the disk if creating a VM from user-image or a specialized VHD. Possible values are: **Windows,** **Linux.**",
enum={"Linux": "Linux", "Windows": "Windows"},
)
os_disk.storage_fault_domain_alignment = AAZStrArg(
options=["storage-fault-domain-alignment"],
help="Specifies the storage fault domain alignment type for the disk.",
enum={"Aligned": "Aligned", "BestEffortAligned": "BestEffortAligned"},
)
os_disk.vhd = AAZObjectArg(
options=["vhd"],
help="The virtual hard disk.",
Expand All @@ -1223,6 +1250,10 @@ def _build_arguments_schema(cls, *args, **kwargs):
)

diff_disk_settings = cls._args_schema.storage_profile.os_disk.diff_disk_settings
diff_disk_settings.enable_full_caching = AAZBoolArg(
options=["enable-full-caching"],
help="Specifies whether or not to enable full caching for this VM which will cache the OS disk locally on the host and make this VM more resilient to storage outages",
)
diff_disk_settings.option = AAZStrArg(
options=["option"],
help="Specifies the ephemeral disk settings for operating system disk.",
Expand Down Expand Up @@ -1485,7 +1516,7 @@ def url_parameters(self):
def query_parameters(self):
parameters = {
**self.serialize_query_param(
"api-version", "2025-04-01",
"api-version", "2025-11-01",
required=True,
),
}
Expand Down Expand Up @@ -1579,6 +1610,7 @@ def content(self):
properties.set_prop("platformFaultDomain", AAZIntType, ".platform_fault_domain")
properties.set_prop("priority", AAZStrType, ".priority")
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("proximityPlacementGroup", AAZObjectType, ".proximity_placement_group"))
properties.set_prop("resiliencyProfile", AAZObjectType, ".resiliency_profile")
properties.set_prop("scheduledEventsPolicy", AAZObjectType, ".scheduled_events_policy")
properties.set_prop("scheduledEventsProfile", AAZObjectType, ".scheduled_events_profile")
properties.set_prop("securityProfile", AAZObjectType, ".security_profile")
Expand Down Expand Up @@ -1871,6 +1903,14 @@ def content(self):
_elements.set_prop("certificateUrl", AAZStrType, ".certificate_url")
_elements.set_prop("protocol", AAZStrType, ".protocol")

resiliency_profile = _builder.get(".properties.resiliencyProfile")
if resiliency_profile is not None:
resiliency_profile.set_prop("zoneMovement", AAZObjectType, ".zone_movement")

zone_movement = _builder.get(".properties.resiliencyProfile.zoneMovement")
if zone_movement is not None:
zone_movement.set_prop("isEnabled", AAZBoolType, ".is_enabled")

scheduled_events_policy = _builder.get(".properties.scheduledEventsPolicy")
if scheduled_events_policy is not None:
scheduled_events_policy.set_prop("allInstancesDown", AAZObjectType, ".all_instances_down")
Expand Down Expand Up @@ -1966,6 +2006,7 @@ def content(self):
_CreateHelper._build_schema_managed_disk_parameters_create(_elements.set_prop("managedDisk", AAZObjectType, ".managed_disk"))
_elements.set_prop("name", AAZStrType, ".name")
_elements.set_prop("sourceResource", AAZObjectType, ".source_resource")
_elements.set_prop("storageFaultDomainAlignment", AAZStrType, ".storage_fault_domain_alignment")
_elements.set_prop("toBeDetached", AAZBoolType, ".to_be_detached")
_CreateHelper._build_schema_virtual_hard_disk_create(_elements.set_prop("vhd", AAZObjectType, ".vhd"))
_elements.set_prop("writeAcceleratorEnabled", AAZBoolType, ".write_accelerator_enabled")
Expand Down Expand Up @@ -1996,11 +2037,13 @@ def content(self):
_CreateHelper._build_schema_managed_disk_parameters_create(os_disk.set_prop("managedDisk", AAZObjectType, ".managed_disk"))
os_disk.set_prop("name", AAZStrType, ".name")
os_disk.set_prop("osType", AAZStrType, ".os_type")
os_disk.set_prop("storageFaultDomainAlignment", AAZStrType, ".storage_fault_domain_alignment")
_CreateHelper._build_schema_virtual_hard_disk_create(os_disk.set_prop("vhd", AAZObjectType, ".vhd"))
os_disk.set_prop("writeAcceleratorEnabled", AAZBoolType, ".write_accelerator_enabled")

diff_disk_settings = _builder.get(".properties.storageProfile.osDisk.diffDiskSettings")
if diff_disk_settings is not None:
diff_disk_settings.set_prop("enableFullCaching", AAZBoolType, ".enable_full_caching")
diff_disk_settings.set_prop("option", AAZStrType, ".option")
diff_disk_settings.set_prop("placement", AAZStrType, ".placement")

Expand Down Expand Up @@ -2203,6 +2246,9 @@ def _build_schema_on_200_201(cls):
serialized_name="proximityPlacementGroup",
)
_CreateHelper._build_schema_sub_resource_read(properties.proximity_placement_group)
properties.resiliency_profile = AAZObjectType(
serialized_name="resiliencyProfile",
)
properties.scheduled_events_policy = AAZObjectType(
serialized_name="scheduledEventsPolicy",
)
Expand Down Expand Up @@ -2378,6 +2424,9 @@ def _build_schema_on_200_201(cls):
)
_element.name = AAZStrType()
_element.statuses = AAZListType()
_element.storage_alignment_status = AAZStrType(
serialized_name="storageAlignmentStatus",
)

encryption_settings = cls._schema_on_200_201.properties.instance_view.disks.Element.encryption_settings
encryption_settings.Element = AAZObjectType()
Expand Down Expand Up @@ -2904,6 +2953,16 @@ def _build_schema_on_200_201(cls):
)
_element.protocol = AAZStrType()

resiliency_profile = cls._schema_on_200_201.properties.resiliency_profile
resiliency_profile.zone_movement = AAZObjectType(
serialized_name="zoneMovement",
)

zone_movement = cls._schema_on_200_201.properties.resiliency_profile.zone_movement
zone_movement.is_enabled = AAZBoolType(
serialized_name="isEnabled",
)

scheduled_events_policy = cls._schema_on_200_201.properties.scheduled_events_policy
scheduled_events_policy.all_instances_down = AAZObjectType(
serialized_name="allInstancesDown",
Expand Down Expand Up @@ -3064,6 +3123,9 @@ def _build_schema_on_200_201(cls):
_element.source_resource = AAZObjectType(
serialized_name="sourceResource",
)
_element.storage_fault_domain_alignment = AAZStrType(
serialized_name="storageFaultDomainAlignment",
)
_element.to_be_detached = AAZBoolType(
serialized_name="toBeDetached",
)
Expand Down Expand Up @@ -3122,13 +3184,19 @@ def _build_schema_on_200_201(cls):
os_disk.os_type = AAZStrType(
serialized_name="osType",
)
os_disk.storage_fault_domain_alignment = AAZStrType(
serialized_name="storageFaultDomainAlignment",
)
os_disk.vhd = AAZObjectType()
_CreateHelper._build_schema_virtual_hard_disk_read(os_disk.vhd)
os_disk.write_accelerator_enabled = AAZBoolType(
serialized_name="writeAcceleratorEnabled",
)

diff_disk_settings = cls._schema_on_200_201.properties.storage_profile.os_disk.diff_disk_settings
diff_disk_settings.enable_full_caching = AAZBoolType(
serialized_name="enableFullCaching",
)
diff_disk_settings.option = AAZStrType()
diff_disk_settings.placement = AAZStrType()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class Deallocate(AAZCommand):
"""

_aaz_info = {
"version": "2022-11-01",
"version": "2025-11-01",
"resources": [
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.compute/virtualmachines/{}/deallocate", "2022-11-01"],
["mgmt-plane", "/subscriptions/{}/resourcegroups/{}/providers/microsoft.compute/virtualmachines/{}/deallocate", "2025-11-01"],
]
}

Expand Down Expand Up @@ -67,6 +67,10 @@ def _build_arguments_schema(cls, *args, **kwargs):
id_part="name",
configured_default="vm",
)
_args_schema.force_deallocate = AAZBoolArg(
options=["--force-deallocate"],
help="Optional parameter to force deallocate a virtual machine. Default is false.",
)
_args_schema.hibernate = AAZBoolArg(
options=["--hibernate"],
help="Optional parameter to hibernate a virtual machine. (Feature in Preview)",
Expand Down Expand Up @@ -98,7 +102,7 @@ def __call__(self, *args, **kwargs):
session,
self.on_200,
self.on_error,
lro_options={"final-state-via": "azure-async-operation"},
lro_options={"final-state-via": "location"},
path_format_arguments=self.url_parameters,
)
if session.http_response.status_code in [200]:
Expand All @@ -107,7 +111,7 @@ def __call__(self, *args, **kwargs):
session,
self.on_200,
self.on_error,
lro_options={"final-state-via": "azure-async-operation"},
lro_options={"final-state-via": "location"},
path_format_arguments=self.url_parameters,
)

Expand Down Expand Up @@ -149,11 +153,14 @@ def url_parameters(self):
@property
def query_parameters(self):
parameters = {
**self.serialize_query_param(
"forceDeallocate", self.ctx.args.force_deallocate,
),
**self.serialize_query_param(
"hibernate", self.ctx.args.hibernate,
),
**self.serialize_query_param(
"api-version", "2022-11-01",
"api-version", "2025-11-01",
required=True,
),
}
Expand Down
Loading
Loading