diff --git a/src/azure-cli/azure/cli/command_modules/vm/_params.py b/src/azure-cli/azure/cli/command_modules/vm/_params.py index 2f9d5f5e125..ff2e0442205 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_params.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_params.py @@ -74,6 +74,7 @@ def load_arguments(self, _): OSTypes = ['Windows', 'Linux'] PatchMode = ['AutomaticByOS', 'AutomaticByPlatform', 'Manual', 'ImageDefault'] Priority = ['Regular', 'Low', 'Spot'] + ProcessorMode = ['Deterministic', 'Opportunistic'] ProxyAgentMode = ['Audit', 'Enforce'] PublicIPAddressAllocationMethod = ['dynamic', 'static'] PublicNetworkAccess = ['Disabled', 'Enabled'] @@ -1422,6 +1423,10 @@ def load_arguments(self, _): help='The ID or name of the capacity reservation group that is used to allocate. Pass in "None" to disassociate the capacity reservation group. Please note that if you want to delete a VM/VMSS that has been associated with capacity reservation group, you need to disassociate the capacity reservation group first.') c.argument('v_cpus_available', type=int, help='Specify the number of vCPUs available') c.argument('v_cpus_per_core', type=int, help='Specify the ratio of vCPU to physical core. Setting this property to 1 also means that hyper-threading is disabled.') + c.argument('processor_mode', arg_type=get_enum_type(ProcessorMode), + help='Specifies the processor mode for the virtual machine or virtual machine scale set. ' + 'Optional; if omitted, the platform default applies (currently Deterministic). ' + 'This property can be updated on a running VM or VMSS without deallocation or reboot.') c.argument('disk_controller_type', disk_controller_type) c.argument('enable_proxy_agent', arg_type=get_three_state_flag(), help='Specify whether metadata security protoco (proxy agent) feature should be enabled on the virtual machine or virtual machine scale set.') c.argument('proxy_agent_mode', deprecate_info=c.deprecate(target='--proxy-agent-mode', redirect='--wire-server-mode'), arg_type=get_enum_type(ProxyAgentMode), help='Specify the mode that proxy agent will execute on if the feature is enabled.') diff --git a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py index 50f96cb3ee9..32d4eead1c3 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py +++ b/src/azure-cli/azure/cli/command_modules/vm/_template_builder.py @@ -306,7 +306,7 @@ def build_vm_resource( # pylint: disable=too-many-locals, too-many-statements, enable_hotpatching=None, platform_fault_domain=None, security_type=None, enable_secure_boot=None, enable_vtpm=None, count=None, edge_zone=None, os_disk_delete_option=None, user_data=None, capacity_reservation_group=None, disable_capacity_reservation_assignment=None, - enable_hibernation=None, v_cpus_available=None, v_cpus_per_core=None, + enable_hibernation=None, v_cpus_available=None, v_cpus_per_core=None, processor_mode=None, os_disk_security_encryption_type=None, os_disk_secure_vm_disk_encryption_set=None, disk_controller_type=None, enable_proxy_agent=None, proxy_agent_mode=None, additional_scheduled_events=None, enable_user_reboot_scheduled_events=None, enable_user_redeploy_scheduled_events=None, @@ -589,6 +589,8 @@ def _build_storage_profile(): vm_properties = {'hardwareProfile': {'vmSize': size}, 'networkProfile': {'networkInterfaces': nics}, 'storageProfile': _build_storage_profile()} + if processor_mode is not None: + vm_properties['hardwareProfile']['processorMode'] = processor_mode resiliency_profile = {} if zone_movement is not None: @@ -1064,7 +1066,7 @@ def build_vmss_resource(cmd, name, computer_name_prefix, location, tags, overpro disable_capacity_reservation_assignment=None, enable_auto_update=None, patch_mode=None, enable_agent=None, security_type=None, enable_secure_boot=None, enable_vtpm=None, automatic_repairs_action=None, v_cpus_available=None, - v_cpus_per_core=None, os_disk_security_encryption_type=None, + v_cpus_per_core=None, processor_mode=None, os_disk_security_encryption_type=None, os_disk_secure_vm_disk_encryption_set=None, os_disk_delete_option=None, regular_priority_count=None, regular_priority_percentage=None, disk_controller_type=None, enable_osimage_notification=None, max_surge=None, enable_hibernation=None, @@ -1375,6 +1377,9 @@ def build_vmss_resource(cmd, name, computer_name_prefix, location, tags, overpro virtual_machine_profile['storageProfile'] = storage_properties hardware_profile = {} + if processor_mode is not None: + hardware_profile['processorMode'] = processor_mode + vm_size_properties = {} if v_cpus_available is not None: vm_size_properties['vCPUsAvailable'] = v_cpus_available diff --git a/src/azure-cli/azure/cli/command_modules/vm/custom.py b/src/azure-cli/azure/cli/command_modules/vm/custom.py index bb93685fe51..c43c1c25bda 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/custom.py +++ b/src/azure-cli/azure/cli/command_modules/vm/custom.py @@ -913,7 +913,7 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_D2s_ enable_hotpatching=None, platform_fault_domain=None, security_type=None, enable_secure_boot=None, enable_vtpm=None, count=None, edge_zone=None, nic_delete_option=None, os_disk_delete_option=None, data_disk_delete_option=None, user_data=None, capacity_reservation_group=None, - disable_capacity_reservation_assignment=None, enable_hibernation=None, + disable_capacity_reservation_assignment=None, enable_hibernation=None, processor_mode=None, v_cpus_available=None, v_cpus_per_core=None, accept_term=None, disable_integrity_monitoring=None, # Unused enable_integrity_monitoring=False, @@ -1146,7 +1146,7 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_D2s_ user_data=user_data, capacity_reservation_group=capacity_reservation_group, disable_capacity_reservation_assignment=disable_capacity_reservation_assignment, enable_hibernation=enable_hibernation, v_cpus_available=v_cpus_available, v_cpus_per_core=v_cpus_per_core, - os_disk_security_encryption_type=os_disk_security_encryption_type, + processor_mode=processor_mode, os_disk_security_encryption_type=os_disk_security_encryption_type, os_disk_secure_vm_disk_encryption_set=os_disk_secure_vm_disk_encryption_set, disk_controller_type=disk_controller_type, enable_proxy_agent=enable_proxy_agent, proxy_agent_mode=proxy_agent_mode, additional_scheduled_events=additional_scheduled_events, @@ -1758,16 +1758,15 @@ def update_vm(cmd, resource_group_name, vm_name, os_disk=None, disk_caching=None write_accelerator=None, license_type=None, no_wait=False, ultra_ssd_enabled=None, priority=None, max_price=None, proximity_placement_group=None, workspace=None, enable_secure_boot=None, enable_vtpm=None, user_data=None, capacity_reservation_group=None, - disable_capacity_reservation_assignment=None, - dedicated_host=None, dedicated_host_group=None, size=None, ephemeral_os_disk_placement=None, - enable_hibernation=None, v_cpus_available=None, v_cpus_per_core=None, disk_controller_type=None, - security_type=None, enable_proxy_agent=None, proxy_agent_mode=None, additional_scheduled_events=None, - enable_user_reboot_scheduled_events=None, enable_user_redeploy_scheduled_events=None, - scheduled_events_api_version=None, enable_all_instance_down=None, - align_regional_disks_to_vm_zone=None, wire_server_mode=None, imds_mode=None, - add_proxy_agent_extension=None, - wire_server_access_control_profile_reference_id=None, imds_access_control_profile_reference_id=None, - key_incarnation_id=None, zone_movement=None, zone=None, **kwargs): + disable_capacity_reservation_assignment=None, dedicated_host=None, dedicated_host_group=None, size=None, + ephemeral_os_disk_placement=None, enable_hibernation=None, v_cpus_available=None, v_cpus_per_core=None, + processor_mode=None, disk_controller_type=None, security_type=None, enable_proxy_agent=None, + proxy_agent_mode=None, additional_scheduled_events=None, enable_user_reboot_scheduled_events=None, + enable_user_redeploy_scheduled_events=None, scheduled_events_api_version=None, + enable_all_instance_down=None, align_regional_disks_to_vm_zone=None, wire_server_mode=None, + imds_mode=None, add_proxy_agent_extension=None, wire_server_access_control_profile_reference_id=None, + imds_access_control_profile_reference_id=None, key_incarnation_id=None, zone_movement=None, zone=None, + **kwargs): from azure.mgmt.core.tools import parse_resource_id, resource_id, is_valid_resource_id from ._vm_utils import update_write_accelerator_settings, update_disk_caching_by_aaz from .operations.vm import convert_show_result_to_snake_case as vm_convert_show_result_to_snake_case @@ -1998,6 +1997,11 @@ def _output(self, *args, **kwargs): vm["hardware_profile"]["vm_size_properties"] = {} vm["hardware_profile"]["vm_size_properties"]["v_cp_us_per_core"] = v_cpus_per_core + if processor_mode is not None: + if vm.get("hardware_profile", None) is None: + vm["hardware_profile"] = {} + vm["hardware_profile"]["processor_mode"] = processor_mode + if ephemeral_os_disk_placement is not None: if vm.get("storage_profile", {}).get("os_disk", {}).get("diff_disk_settings", None) is not None: vm["storage_profile"]["os_disk"]["diff_disk_settings"]["placement"] = ephemeral_os_disk_placement @@ -3728,7 +3732,7 @@ def create_vmss(cmd, vmss_name, resource_group_name, image=None, capacity_reservation_group=None, disable_capacity_reservation_assignment=None, enable_auto_update=None, patch_mode=None, enable_agent=None, security_type=None, enable_secure_boot=None, enable_vtpm=None, automatic_repairs_action=None, - v_cpus_available=None, v_cpus_per_core=None, accept_term=None, + v_cpus_available=None, v_cpus_per_core=None, processor_mode=None, accept_term=None, disable_integrity_monitoring=None, # Unused enable_integrity_monitoring=False, enable_auto_os_upgrade=None, os_disk_security_encryption_type=None, os_disk_secure_vm_disk_encryption_set=None, @@ -4048,7 +4052,8 @@ def _get_public_ip_address_allocation(value, sku): patch_mode=patch_mode, enable_agent=enable_agent, security_type=security_type, enable_secure_boot=enable_secure_boot, enable_vtpm=enable_vtpm, automatic_repairs_action=automatic_repairs_action, v_cpus_available=v_cpus_available, - v_cpus_per_core=v_cpus_per_core, os_disk_security_encryption_type=os_disk_security_encryption_type, + v_cpus_per_core=v_cpus_per_core, processor_mode=processor_mode, + os_disk_security_encryption_type=os_disk_security_encryption_type, os_disk_secure_vm_disk_encryption_set=os_disk_secure_vm_disk_encryption_set, os_disk_delete_option=os_disk_delete_option, regular_priority_count=regular_priority_count, regular_priority_percentage=regular_priority_percentage, disk_controller_type=disk_controller_type, @@ -4595,6 +4600,7 @@ def update_vmss(cmd, resource_group_name, name, license_type=None, no_wait=False disable_capacity_reservation_assignment=None, vm_sku=None, ephemeral_os_disk_placement=None, force_deletion=None, enable_secure_boot=None, enable_vtpm=None, automatic_repairs_action=None, v_cpus_available=None, v_cpus_per_core=None, + processor_mode=None, regular_priority_count=None, regular_priority_percentage=None, disk_controller_type=None, enable_osimage_notification=None, custom_data=None, enable_hibernation=None, security_type=None, enable_proxy_agent=None, proxy_agent_mode=None, @@ -4720,6 +4726,13 @@ def _output(self, *args, **kwargs): if v_cpus_per_core is not None: vmss["virtual_machine_profile"]["hardware_profile"]["vm_size_properties"]["v_cp_us_per_core"] = v_cpus_per_core # pylint: disable=line-too-long + if processor_mode is not None: + if vmss.get("virtual_machine_profile", None) is None: + vmss["virtual_machine_profile"] = {} + if vmss["virtual_machine_profile"].get("hardware_profile", None) is None: + vmss["virtual_machine_profile"]["hardware_profile"] = {} + vmss["virtual_machine_profile"]["hardware_profile"]["processor_mode"] = processor_mode + if capacity_reservation_group is not None: if vmss.get("virtual_machine_profile", None) is None: vmss["virtual_machine_profile"] = {} diff --git a/src/azure-cli/azure/cli/command_modules/vm/operations/vm.py b/src/azure-cli/azure/cli/command_modules/vm/operations/vm.py index 95b7d7777a2..adfb3348317 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/operations/vm.py +++ b/src/azure-cli/azure/cli/command_modules/vm/operations/vm.py @@ -418,6 +418,9 @@ def convert_show_result_to_snake_case(result): boot_diagnostics.pop("storageUri") hardware_profile = new_result.get("hardware_profile", {}) or {} + if "processorMode" in hardware_profile: + hardware_profile["processor_mode"] = hardware_profile["processorMode"] + hardware_profile.pop("processorMode") if "vmSize" in hardware_profile: hardware_profile["vm_size"] = hardware_profile["vmSize"] hardware_profile.pop("vmSize") diff --git a/src/azure-cli/azure/cli/command_modules/vm/operations/vmss.py b/src/azure-cli/azure/cli/command_modules/vm/operations/vmss.py index a1d8733d97e..f770a572bf8 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/operations/vmss.py +++ b/src/azure-cli/azure/cli/command_modules/vm/operations/vmss.py @@ -593,6 +593,9 @@ def convert_show_result_to_snake_case(result): protected_settings_from_key_vault.pop("sourceVault") hardware_profile = virtual_machine_profile.get("hardware_profile", {}) or {} + if "processorMode" in hardware_profile: + hardware_profile["processor_mode"] = hardware_profile["processorMode"] + hardware_profile.pop("processorMode") if "vmSizeProperties" in hardware_profile: hardware_profile["vm_size_properties"] = hardware_profile["vmSizeProperties"] hardware_profile.pop("vmSizeProperties") diff --git a/src/azure-cli/azure/cli/command_modules/vm/tests/latest/test_vm_commands.py b/src/azure-cli/azure/cli/command_modules/vm/tests/latest/test_vm_commands.py index 6e104e99619..6f1aae6a8e0 100644 --- a/src/azure-cli/azure/cli/command_modules/vm/tests/latest/test_vm_commands.py +++ b/src/azure-cli/azure/cli/command_modules/vm/tests/latest/test_vm_commands.py @@ -2027,6 +2027,51 @@ def test_vm_size_properties(self, resource_group): self.check('virtualMachineProfile.hardwareProfile.vmSizeProperties.vCpusPerCore', 2) ]) + @live_only() + @AllowLargeResponse(size_kb=99999) + @ResourceGroupPreparer(name_prefix='cli_test_vm_processor_mode_', location='westus') + def test_vm_processor_mode(self, resource_group): + self.kwargs.update({ + 'vm': self.create_random_name('vm-', 10), + 'vmss': self.create_random_name('vmss-', 12), + 'image': 'MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest', + 'size': 'Standard_D2als_v7' + }) + + self.cmd( + 'vm create -g {rg} -n {vm} --image {image} --size {size} ' + '--admin-username azureuser --admin-password TestPassword0! ' + '--processor-mode Deterministic --public-ip-address "" --nsg-rule NONE', + checks=[ + self.check('hardwareProfile.processorMode', 'Deterministic') + ]) + self.cmd('vm show -g {rg} -n {vm}', checks=[ + self.check('hardwareProfile.processorMode', 'Deterministic') + ]) + self.cmd('vm update -g {rg} -n {vm} --processor-mode Opportunistic', checks=[ + self.check('hardwareProfile.processorMode', 'Opportunistic') + ]) + self.cmd('vm show -g {rg} -n {vm}', checks=[ + self.check('hardwareProfile.processorMode', 'Opportunistic') + ]) + + self.cmd( + 'vmss create -g {rg} -n {vmss} --image {image} --vm-sku {size} ' + '--admin-username azureuser --admin-password TestPassword0! ' + '--processor-mode Deterministic --instance-count 0 --lb-sku Standard', + checks=[ + self.check('virtualMachineProfile.hardwareProfile.processorMode', 'Deterministic') + ]) + self.cmd('vmss show -g {rg} -n {vmss}', checks=[ + self.check('virtualMachineProfile.hardwareProfile.processorMode', 'Deterministic') + ]) + self.cmd('vmss update -g {rg} -n {vmss} --processor-mode Opportunistic', checks=[ + self.check('virtualMachineProfile.hardwareProfile.processorMode', 'Opportunistic') + ]) + self.cmd('vmss show -g {rg} -n {vmss}', checks=[ + self.check('virtualMachineProfile.hardwareProfile.processorMode', 'Opportunistic') + ]) + class VMSimulateEvictionScenarioTest(ScenarioTest):