Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,10 @@
- name: Create a default Ubuntu2204 VM with automatic SSH authentication.
text: >
az vm create -n MyVm -g MyResourceGroup --image Ubuntu2204
- name: Create a Flow VM with a preferred size in a supported region.
text: >
az vm create -n MyVm -g MyResourceGroup --location eastus2 --image Ubuntu2204
--preferred-size Standard_D2s_v3 --generate-ssh-keys --nsg-rule NONE --public-ip-address ""
- name: Create a default RedHat VM with automatic SSH authentication using an image URN.
text: >
az vm create -n MyVm -g MyResourceGroup --image RedHat:RHEL:7-RAW:7.4.2018010506
Expand Down Expand Up @@ -2140,6 +2144,10 @@
text: az vm update -n name -g group --set tags.tagName=tagValue
- name: Remove a tag.
text: az vm update -n name -g group --remove tags.tagName
- name: Opt in to Flow VMs or change the preferred size.
text: az vm update -n MyVm -g MyResourceGroup --preferred-size Standard_D2s_v3
- name: Opt out of Flow VMs and pin a fixed size.
text: az vm update -n MyVm -g MyResourceGroup --size Standard_D2s_v3 --remove flexProfile
- name: Set the primary NIC of a VM.
text: az vm update -n name -g group --set networkProfile.networkInterfaces[1].primary=false networkProfile.networkInterfaces[0].primary=true
- name: Add a new non-primary NIC to a VM.
Expand Down
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 @@ -496,6 +496,7 @@ def load_arguments(self, _):

for scope in ['vm create', 'vm update']:
with self.argument_context(scope) as c:
c.argument('preferred_size', completer=get_vm_size_completion_list, is_preview=True, help='Preferred VM size for Flow VMs. Azure may deploy a compatible alternative size. Cannot be used with --size.')
c.argument('additional_scheduled_events', options_list=['--additional-scheduled-events', '--additional-events'], arg_type=get_three_state_flag(), help='The configuration parameter used while creating event grid and resource graph scheduled event setting.')
c.argument('enable_user_reboot_scheduled_events', options_list=['--enable-user-reboot-scheduled-events', '--enable-reboot'], arg_type=get_three_state_flag(), help='The configuration parameter used while publishing scheduled events additional publishing targets.')
c.argument('enable_user_redeploy_scheduled_events', options_list=['--enable-user-redeploy-scheduled-events', '--enable-redeploy'], arg_type=get_three_state_flag(), help='The configuration parameter used while creating user initiated redeploy scheduled event setting creation.')
Expand Down
11 changes: 9 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/_template_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ def build_vm_resource( # pylint: disable=too-many-locals, too-many-statements,
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, zone_movement=None,
os_disk_storage_fault_domain_alignment=None, data_disk_storage_fault_domain_alignment=None):
os_disk_storage_fault_domain_alignment=None, data_disk_storage_fault_domain_alignment=None,
preferred_size=None):

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

Expand Down Expand Up @@ -602,8 +603,12 @@ def _build_storage_profile():

return profile

vm_properties = {'hardwareProfile': {'vmSize': size}, 'networkProfile': {'networkInterfaces': nics},
vm_properties = {'hardwareProfile': {}, 'networkProfile': {'networkInterfaces': nics},
'storageProfile': _build_storage_profile()}
if preferred_size is None:
vm_properties['hardwareProfile']['vmSize'] = size
else:
vm_properties['flexProfile'] = {'preferredVMSize': preferred_size}
if processor_mode is not None:
vm_properties['hardwareProfile']['processorMode'] = processor_mode

Expand Down Expand Up @@ -659,6 +664,8 @@ def _build_storage_profile():

if vm_size_properties:
vm_properties['hardwareProfile']['vmSizeProperties'] = vm_size_properties
if not vm_properties['hardwareProfile']:
del vm_properties['hardwareProfile']

if availability_set_id:
vm_properties['availabilitySet'] = {'id': availability_set_id}
Expand Down
25 changes: 22 additions & 3 deletions src/azure-cli/azure/cli/command_modules/vm/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ def _validate_vm_create_storage_profile(cmd, namespace, for_scale_set=False):

from ._vm_utils import normalize_disk_info
# attach_data_disks are not exposed yet for VMSS, so use 'getattr' to avoid crash
vm_size = (getattr(namespace, 'size', None) or getattr(namespace, 'vm_sku', None))
vm_size = (getattr(namespace, 'preferred_size', None) or
getattr(namespace, 'size', None) or getattr(namespace, 'vm_sku', None))

# pylint: disable=line-too-long
namespace.disk_info = normalize_disk_info(size=vm_size,
Expand Down Expand Up @@ -953,7 +954,8 @@ def _subnet_capacity_check(subnet_mask, vmss_instance_count, over_provision):

def _validate_vm_vmss_accelerated_networking(cli_ctx, namespace):
if namespace.accelerated_networking is None:
size = getattr(namespace, 'size', None) or getattr(namespace, 'vm_sku', None)
size = (getattr(namespace, 'preferred_size', None) or
getattr(namespace, 'size', None) or getattr(namespace, 'vm_sku', None))
size = size.lower()

# Use the following code to refresh the list
Expand Down Expand Up @@ -1654,9 +1656,25 @@ def _resolve_role_id(cli_ctx, role, scope):
return role_id


def _validate_vm_size_options(namespace):
from azure.cli.core.azclierror import InvalidArgumentValueError

preferred_size = getattr(namespace, 'preferred_size', None)
size = getattr(namespace, 'size', None)

if size is not None and preferred_size is not None:
raise MutuallyExclusiveArgumentError("Specify either --size or --preferred-size, not both.")
if preferred_size is not None and not preferred_size.strip():
raise InvalidArgumentValueError("--preferred-size must not be empty or whitespace.")


def process_vm_create_namespace(cmd, namespace):
_validate_vm_size_options(namespace)
preferred_size = getattr(namespace, 'preferred_size', None)
if namespace.size is None and preferred_size is None:
namespace.size = 'Standard_D2s_v5'
validate_tags(namespace)
_validate_location(cmd, namespace, namespace.zone, namespace.size)
_validate_location(cmd, namespace, namespace.zone, preferred_size or namespace.size)

# Currently, only `az vm create` supports this feature, so it is temporarily placed in process_vm_create_namespace()
from ._vm_utils import display_region_recommendation
Expand Down Expand Up @@ -1700,6 +1718,7 @@ def process_vm_create_namespace(cmd, namespace):


def process_vm_update_namespace(cmd, namespace):
_validate_vm_size_options(namespace)
_validate_vm_create_dedicated_host(cmd, namespace)
_validate_capacity_reservation_group(cmd, namespace)
_validate_vm_vmss_update_ephemeral_placement(cmd, namespace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ def _build_arguments_schema(cls, *args, **kwargs):
arg_group="Properties",
help="Specifies the time alloted for all extensions to start. The time duration should be between 15 minutes and 120 minutes (inclusive) and should be specified in ISO 8601 format. The default value is 90 minutes (PT1H30M). Minimum api-version: 2020-06-01.",
)
_args_schema.flex_profile = AAZObjectArg(
options=["--flex-profile"],
arg_group="Properties",
help="[Preview Feature] Specifies a FlexProfile for VM size. Azure may deploy a compatible alternative VM size based on capacity and placement considerations, and returns the deployed size in hardwareProfile.vmSize. A request that adds flexProfile must omit hardwareProfile.vmSize. For a virtual machine that uses FlexProfile, a hardwareProfile.vmSize equal to the deployed size is ignored, so a GET response can be sent back unchanged. A PATCH request that omits flexProfile keeps it. A PUT request that omits flexProfile and sets hardwareProfile.vmSize clears it. This property cannot exist along with a non-null properties.availabilitySet, properties.capacityReservation, properties.host, properties.hostGroup, properties.proximityPlacementGroup or properties.virtualMachineScaleSet.",
)
_args_schema.hardware_profile = AAZObjectArg(
options=["--hardware-profile"],
arg_group="Properties",
Expand Down Expand Up @@ -387,6 +392,13 @@ def _build_arguments_schema(cls, *args, **kwargs):
help="Uri of the storage account to use for placing the console output and screenshot. If storageUri is not specified while enabling boot diagnostics, managed storage will be used.",
)

flex_profile = cls._args_schema.flex_profile
flex_profile.preferred_vm_size = AAZStrArg(
options=["preferred-vm-size"],
help="Specifies the preferred VM size, for example Standard_D4s_v5. Azure may deploy a compatible alternative size based on capacity and placement considerations. Supported VM families for FlexProfile may vary by region. The recommended way to get the list of available sizes is using these APIs: [List all available virtual machine sizes in a region](https://docs.microsoft.com/rest/api/compute/resourceskus/list), [List all available virtual machine sizes for resizing](https://docs.microsoft.com/rest/api/compute/virtualmachines/listavailablesizes).",
required=True,
)

hardware_profile = cls._args_schema.hardware_profile
hardware_profile.processor_mode = AAZStrArg(
options=["processor-mode"],
Expand Down Expand Up @@ -1743,6 +1755,7 @@ def content(self):
properties.set_prop("diagnosticsProfile", AAZObjectType, ".diagnostics_profile")
properties.set_prop("evictionPolicy", AAZStrType, ".eviction_policy")
properties.set_prop("extensionsTimeBudget", AAZStrType, ".extensions_time_budget")
properties.set_prop("flexProfile", AAZObjectType, ".flex_profile")
properties.set_prop("hardwareProfile", AAZObjectType, ".hardware_profile")
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("host", AAZObjectType, ".host"))
_CreateHelper._build_schema_sub_resource_create(properties.set_prop("hostGroup", AAZObjectType, ".host_group"))
Expand Down Expand Up @@ -1802,6 +1815,10 @@ def content(self):
boot_diagnostics.set_prop("enabled", AAZBoolType, ".enabled")
boot_diagnostics.set_prop("storageUri", AAZStrType, ".storage_uri")

flex_profile = _builder.get(".properties.flexProfile")
if flex_profile is not None:
flex_profile.set_prop("preferredVMSize", AAZStrType, ".preferred_vm_size", typ_kwargs={"flags": {"required": True}})

hardware_profile = _builder.get(".properties.hardwareProfile")
if hardware_profile is not None:
hardware_profile.set_prop("processorMode", AAZStrType, ".processor_mode")
Expand Down Expand Up @@ -2373,6 +2390,9 @@ def _build_schema_on_200_201(cls):
properties.extensions_time_budget = AAZStrType(
serialized_name="extensionsTimeBudget",
)
properties.flex_profile = AAZObjectType(
serialized_name="flexProfile",
)
properties.hardware_profile = AAZObjectType(
serialized_name="hardwareProfile",
)
Expand Down Expand Up @@ -2502,6 +2522,12 @@ def _build_schema_on_200_201(cls):
serialized_name="storageUri",
)

flex_profile = cls._schema_on_200_201.properties.flex_profile
flex_profile.preferred_vm_size = AAZStrType(
serialized_name="preferredVMSize",
flags={"required": True},
)

hardware_profile = cls._schema_on_200_201.properties.hardware_profile
hardware_profile.processor_mode = AAZStrType(
serialized_name="processorMode",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ def _build_schema_on_200(cls):
properties.extensions_time_budget = AAZStrType(
serialized_name="extensionsTimeBudget",
)
properties.flex_profile = AAZObjectType(
serialized_name="flexProfile",
)
properties.hardware_profile = AAZObjectType(
serialized_name="hardwareProfile",
)
Expand Down Expand Up @@ -415,6 +418,12 @@ def _build_schema_on_200(cls):
serialized_name="storageUri",
)

flex_profile = cls._schema_on_200.value.Element.properties.flex_profile
flex_profile.preferred_vm_size = AAZStrType(
serialized_name="preferredVMSize",
flags={"required": True},
)

hardware_profile = cls._schema_on_200.value.Element.properties.hardware_profile
hardware_profile.processor_mode = AAZStrType(
serialized_name="processorMode",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ def _build_schema_on_200(cls):
properties.extensions_time_budget = AAZStrType(
serialized_name="extensionsTimeBudget",
)
properties.flex_profile = AAZObjectType(
serialized_name="flexProfile",
)
properties.hardware_profile = AAZObjectType(
serialized_name="hardwareProfile",
)
Expand Down Expand Up @@ -415,6 +418,12 @@ def _build_schema_on_200(cls):
serialized_name="storageUri",
)

flex_profile = cls._schema_on_200.value.Element.properties.flex_profile
flex_profile.preferred_vm_size = AAZStrType(
serialized_name="preferredVMSize",
flags={"required": True},
)

hardware_profile = cls._schema_on_200.value.Element.properties.hardware_profile
hardware_profile.processor_mode = AAZStrType(
serialized_name="processorMode",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ def _build_schema_on_200(cls):
properties.extensions_time_budget = AAZStrType(
serialized_name="extensionsTimeBudget",
)
properties.flex_profile = AAZObjectType(
serialized_name="flexProfile",
)
properties.hardware_profile = AAZObjectType(
serialized_name="hardwareProfile",
)
Expand Down Expand Up @@ -405,6 +408,12 @@ def _build_schema_on_200(cls):
serialized_name="storageUri",
)

flex_profile = cls._schema_on_200.properties.flex_profile
flex_profile.preferred_vm_size = AAZStrType(
serialized_name="preferredVMSize",
flags={"required": True},
)

hardware_profile = cls._schema_on_200.properties.hardware_profile
hardware_profile.processor_mode = AAZStrType(
serialized_name="processorMode",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ def _build_arguments_schema(cls, *args, **kwargs):
help="Specifies the time alloted for all extensions to start. The time duration should be between 15 minutes and 120 minutes (inclusive) and should be specified in ISO 8601 format. The default value is 90 minutes (PT1H30M). Minimum api-version: 2020-06-01.",
nullable=True,
)
_args_schema.flex_profile = AAZObjectArg(
options=["--flex-profile"],
arg_group="Properties",
help="[Preview Feature] Specifies a FlexProfile for VM size. Azure may deploy a compatible alternative VM size based on capacity and placement considerations, and returns the deployed size in hardwareProfile.vmSize. A request that adds flexProfile must omit hardwareProfile.vmSize. For a virtual machine that uses FlexProfile, a hardwareProfile.vmSize equal to the deployed size is ignored, so a GET response can be sent back unchanged. A PATCH request that omits flexProfile keeps it. A PUT request that omits flexProfile and sets hardwareProfile.vmSize clears it. This property cannot exist along with a non-null properties.availabilitySet, properties.capacityReservation, properties.host, properties.hostGroup, properties.proximityPlacementGroup or properties.virtualMachineScaleSet.",
nullable=True,
)
_args_schema.hardware_profile = AAZObjectArg(
options=["--hardware-profile"],
arg_group="Properties",
Expand Down Expand Up @@ -424,6 +430,12 @@ def _build_arguments_schema(cls, *args, **kwargs):
nullable=True,
)

flex_profile = cls._args_schema.flex_profile
flex_profile.preferred_vm_size = AAZStrArg(
options=["preferred-vm-size"],
help="Specifies the preferred VM size, for example Standard_D4s_v5. Azure may deploy a compatible alternative size based on capacity and placement considerations. Supported VM families for FlexProfile may vary by region. The recommended way to get the list of available sizes is using these APIs: [List all available virtual machine sizes in a region](https://docs.microsoft.com/rest/api/compute/resourceskus/list), [List all available virtual machine sizes for resizing](https://docs.microsoft.com/rest/api/compute/virtualmachines/listavailablesizes).",
)

hardware_profile = cls._args_schema.hardware_profile
hardware_profile.processor_mode = AAZStrArg(
options=["processor-mode"],
Expand Down Expand Up @@ -2118,6 +2130,7 @@ def _update_instance(self, instance):
properties.set_prop("diagnosticsProfile", AAZObjectType, ".diagnostics_profile")
properties.set_prop("evictionPolicy", AAZStrType, ".eviction_policy")
properties.set_prop("extensionsTimeBudget", AAZStrType, ".extensions_time_budget")
properties.set_prop("flexProfile", AAZObjectType, ".flex_profile")
properties.set_prop("hardwareProfile", AAZObjectType, ".hardware_profile")
_UpdateHelper._build_schema_sub_resource_update(properties.set_prop("host", AAZObjectType, ".host"))
_UpdateHelper._build_schema_sub_resource_update(properties.set_prop("hostGroup", AAZObjectType, ".host_group"))
Expand Down Expand Up @@ -2177,6 +2190,10 @@ def _update_instance(self, instance):
boot_diagnostics.set_prop("enabled", AAZBoolType, ".enabled")
boot_diagnostics.set_prop("storageUri", AAZStrType, ".storage_uri")

flex_profile = _builder.get(".properties.flexProfile")
if flex_profile is not None:
flex_profile.set_prop("preferredVMSize", AAZStrType, ".preferred_vm_size", typ_kwargs={"flags": {"required": True}})

hardware_profile = _builder.get(".properties.hardwareProfile")
if hardware_profile is not None:
hardware_profile.set_prop("processorMode", AAZStrType, ".processor_mode")
Expand Down Expand Up @@ -3222,6 +3239,9 @@ def _build_schema_virtual_machine_read(cls, _schema):
properties.extensions_time_budget = AAZStrType(
serialized_name="extensionsTimeBudget",
)
properties.flex_profile = AAZObjectType(
serialized_name="flexProfile",
)
properties.hardware_profile = AAZObjectType(
serialized_name="hardwareProfile",
)
Expand Down Expand Up @@ -3351,6 +3371,12 @@ def _build_schema_virtual_machine_read(cls, _schema):
serialized_name="storageUri",
)

flex_profile = _schema_virtual_machine_read.properties.flex_profile
flex_profile.preferred_vm_size = AAZStrType(
serialized_name="preferredVMSize",
flags={"required": True},
)

hardware_profile = _schema_virtual_machine_read.properties.hardware_profile
hardware_profile.processor_mode = AAZStrType(
serialized_name="processorMode",
Expand Down
Loading
Loading