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 d64cdddd74d..1b856e84cf3 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 b8bd933d9c8..f150a9bd96b 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, @@ -590,6 +590,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: @@ -1068,7 +1070,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, @@ -1379,6 +1381,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 89a4162d392..131be9743ca 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, @@ -1147,7 +1147,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, @@ -1760,15 +1760,13 @@ 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, - wire_server_use_local_file_rules=None, imds_mode=None, - add_proxy_agent_extension=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, + 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, + wire_server_use_local_file_rules=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 @@ -2006,6 +2004,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 @@ -3736,7 +3739,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, @@ -4057,7 +4060,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, @@ -4605,6 +4609,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, @@ -4731,6 +4736,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 bde7d7c19fc..f83f66ae9d3 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 ce46b2dc7f7..41eff6beeca 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 046a162be2f..c92c5183480 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):