in src/azure-cli/azure/cli/command_modules/vm/custom.py [0:0]
def create_vmss(cmd, vmss_name, resource_group_name, image=None,
disable_overprovision=None, instance_count=2,
location=None, tags=None, upgrade_policy_mode='manual', validate=False,
admin_username=None, admin_password=None, authentication_type=None,
vm_sku=None, no_wait=False,
ssh_dest_key_path=None, ssh_key_value=None, generate_ssh_keys=False, ssh_key_type=None,
load_balancer=None, load_balancer_sku=None, application_gateway=None,
app_gateway_subnet_address_prefix=None,
app_gateway_sku='Standard_Large', app_gateway_capacity=10,
backend_pool_name=None, nat_pool_name=None, backend_port=None, health_probe=None,
public_ip_address=None, public_ip_address_allocation=None,
public_ip_address_dns_name=None, accelerated_networking=None,
public_ip_per_vm=False, vm_domain_name=None, dns_servers=None, nsg=None,
os_caching=None, data_caching=None,
storage_container_name='vhds', storage_sku=None,
os_type=None, os_disk_name=None,
use_unmanaged_disk=False, data_disk_sizes_gb=None, disk_info=None,
vnet_name=None, vnet_address_prefix='10.0.0.0/16',
subnet=None, subnet_address_prefix=None,
os_offer=None, os_publisher=None, os_sku=None, os_version=None,
load_balancer_type=None, app_gateway_type=None, vnet_type=None,
public_ip_address_type=None, storage_profile=None,
single_placement_group=None, custom_data=None, secrets=None, platform_fault_domain_count=None,
plan_name=None, plan_product=None, plan_publisher=None, plan_promotion_code=None, license_type=None,
assign_identity=None, identity_scope=None, identity_role=None, encryption_identity=None,
identity_role_id=None, zones=None, priority=None, eviction_policy=None,
application_security_groups=None, ultra_ssd_enabled=None,
ephemeral_os_disk=None, ephemeral_os_disk_placement=None,
proximity_placement_group=None, aux_subscriptions=None, terminate_notification_time=None,
max_price=None, computer_name_prefix=None, orchestration_mode=None, scale_in_policy=None,
os_disk_encryption_set=None, data_disk_encryption_sets=None, data_disk_iops=None, data_disk_mbps=None,
automatic_repairs_grace_period=None, specialized=None, os_disk_size_gb=None, encryption_at_host=None,
host_group=None, max_batch_instance_percent=None, max_unhealthy_instance_percent=None,
max_unhealthy_upgraded_instance_percent=None, pause_time_between_batches=None,
enable_cross_zone_upgrade=None, prioritize_unhealthy_instances=None, edge_zone=None,
user_data=None, network_api_version=None, enable_spot_restore=None, spot_restore_timeout=None,
capacity_reservation_group=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,
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,
os_disk_delete_option=None, data_disk_delete_option=None, regular_priority_count=None,
regular_priority_percentage=None, disk_controller_type=None, nat_rule_name=None,
enable_osimage_notification=None, max_surge=None, disable_integrity_monitoring_autoupgrade=False,
enable_hibernation=None, enable_proxy_agent=None, proxy_agent_mode=None,
security_posture_reference_id=None, security_posture_reference_exclude_extensions=None,
enable_resilient_creation=None, enable_resilient_deletion=None,
additional_scheduled_events=None, enable_user_reboot_scheduled_events=None,
enable_user_redeploy_scheduled_events=None, skuprofile_vmsizes=None, skuprofile_allostrat=None,
security_posture_reference_is_overridable=None, zone_balance=None, wire_server_mode=None,
imds_mode=None, wire_server_access_control_profile_reference_id=None,
imds_access_control_profile_reference_id=None, enable_automatic_zone_balancing=None,
automatic_zone_balancing_strategy=None, automatic_zone_balancing_behavior=None):
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.util import random_string, hash_string
from azure.cli.core.commands.arm import ArmTemplateBuilder
from azure.cli.command_modules.vm._template_builder import (StorageProfile, build_vmss_resource,
build_vnet_resource, build_public_ip_resource,
build_load_balancer_resource,
build_vmss_storage_account_pool_resource,
build_application_gateway_resource,
build_msi_role_assignment, build_nsg_resource,
build_nat_rule_v2)
# The default load balancer will be expected to be changed from Basic to Standard, and Basic will be removed.
# In order to avoid breaking change which has a big impact to users,
# we use the hint to guide users to use Standard load balancer to create VMSS in the first stage.
if load_balancer_sku == 'Basic':
logger.warning(remove_basic_option_msg, "--lb-sku Standard")
# Build up the ARM template
master_template = ArmTemplateBuilder()
uniform_str = 'Uniform'
flexible_str = 'Flexible'
if orchestration_mode:
from azure.mgmt.core.tools import resource_id, is_valid_resource_id
if disk_info:
storage_sku = disk_info['os'].get('storageAccountType')
subscription_id = get_subscription_id(cmd.cli_ctx)
if os_disk_encryption_set is not None and not is_valid_resource_id(os_disk_encryption_set):
os_disk_encryption_set = resource_id(
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Compute', type='diskEncryptionSets', name=os_disk_encryption_set)
if os_disk_secure_vm_disk_encryption_set is not None and\
not is_valid_resource_id(os_disk_secure_vm_disk_encryption_set):
os_disk_secure_vm_disk_encryption_set = resource_id(
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Compute', type='diskEncryptionSets', name=os_disk_secure_vm_disk_encryption_set)
if data_disk_encryption_sets is None:
data_disk_encryption_sets = []
for i, des in enumerate(data_disk_encryption_sets):
if des is not None and not is_valid_resource_id(des):
data_disk_encryption_sets[i] = resource_id(
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Compute', type='diskEncryptionSets', name=des)
network_id_template = resource_id(
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Network')
vmss_id = resource_id(
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Compute', type='virtualMachineScaleSets', name=vmss_name)
scrubbed_name = vmss_name.replace('-', '').lower()[:5]
naming_prefix = '{}{}'.format(scrubbed_name,
hash_string(vmss_id,
length=(9 - len(scrubbed_name)),
force_lower=True))
# determine final defaults and calculated values
tags = tags or {}
os_disk_name = os_disk_name or ('osdisk_{}'.format(hash_string(vmss_id, length=10))
if use_unmanaged_disk else None)
load_balancer = load_balancer or '{}LB'.format(vmss_name)
app_gateway = application_gateway or '{}AG'.format(vmss_name)
backend_pool_name = backend_pool_name or '{}BEPool'.format(load_balancer or application_gateway)
vmss_dependencies = []
# VNET will always be a dependency
if vnet_type == 'new':
vnet_name = vnet_name or '{}VNET'.format(vmss_name)
subnet = subnet or '{}Subnet'.format(vmss_name)
vmss_dependencies.append('Microsoft.Network/virtualNetworks/{}'.format(vnet_name))
vnet = build_vnet_resource(
cmd, vnet_name, location, tags, vnet_address_prefix, subnet, subnet_address_prefix, edge_zone=edge_zone)
if app_gateway_type:
vnet['properties']['subnets'].append({
'name': 'appGwSubnet',
'properties': {
'addressPrefix': app_gateway_subnet_address_prefix
}
})
master_template.add_resource(vnet)
if subnet:
subnet_id = subnet if is_valid_resource_id(subnet) else \
'{}/virtualNetworks/{}/subnets/{}'.format(network_id_template, vnet_name, subnet)
else:
subnet_id = None
if vnet_name:
gateway_subnet_id = ('{}/virtualNetworks/{}/subnets/appGwSubnet'.format(network_id_template, vnet_name)
if app_gateway_type == 'new' else None)
else:
gateway_subnet_id = None
# public IP is used by either load balancer/application gateway
public_ip_address_id = None
if public_ip_address:
public_ip_address_id = (public_ip_address if is_valid_resource_id(public_ip_address)
else '{}/publicIPAddresses/{}'.format(network_id_template,
public_ip_address))
def _get_public_ip_address_allocation(value, sku):
if not value:
value = 'Static' if (sku and sku.lower() == 'standard') else 'Dynamic'
return value
# Handle load balancer creation
if load_balancer_type == 'new':
vmss_dependencies.append('Microsoft.Network/loadBalancers/{}'.format(load_balancer))
lb_dependencies = []
if vnet_type == 'new':
lb_dependencies.append('Microsoft.Network/virtualNetworks/{}'.format(vnet_name))
if public_ip_address_type == 'new':
public_ip_address = public_ip_address or '{}PublicIP'.format(load_balancer)
lb_dependencies.append(
'Microsoft.Network/publicIpAddresses/{}'.format(public_ip_address))
master_template.add_resource(build_public_ip_resource(
cmd, public_ip_address, location, tags,
_get_public_ip_address_allocation(public_ip_address_allocation, load_balancer_sku),
public_ip_address_dns_name, load_balancer_sku, zones, edge_zone=edge_zone))
public_ip_address_id = '{}/publicIPAddresses/{}'.format(network_id_template,
public_ip_address)
if nat_rule_name and nat_pool_name:
from azure.cli.core.azclierror import MutuallyExclusiveArgumentError
raise MutuallyExclusiveArgumentError(
'Please do not pass in both "--nat-pool-name" and "--nat-rule-name" parameters at the same time.'
'"--nat-rule-name" parameter is recommended')
is_basic_lb_sku = not load_balancer_sku or load_balancer_sku.lower() != 'standard'
# calculate default names if not provided
if orchestration_mode.lower() == flexible_str.lower():
# inbound nat pools are not supported on VMSS Flex
nat_pool_name = None
elif nat_pool_name or (not nat_rule_name and is_basic_lb_sku):
nat_pool_name = nat_pool_name or '{}NatPool'.format(load_balancer)
if not backend_port:
backend_port = 3389 if os_type == 'windows' else 22
frontend_ip_name = 'loadBalancerFrontEnd'
lb_resource = build_load_balancer_resource(
cmd, load_balancer, location, tags, backend_pool_name, nat_pool_name, backend_port,
frontend_ip_name, public_ip_address_id, subnet_id, private_ip_address='',
private_ip_allocation='Dynamic', sku=load_balancer_sku, instance_count=instance_count,
disable_overprovision=disable_overprovision, edge_zone=edge_zone)
lb_resource['dependsOn'] = lb_dependencies
master_template.add_resource(lb_resource)
# Per https://learn.microsoft.com/azure/load-balancer/load-balancer-standard-overview#nsg
if load_balancer_sku and load_balancer_sku.lower() == 'standard' and nsg is None and os_type:
nsg_name = '{}NSG'.format(vmss_name)
master_template.add_resource(build_nsg_resource(
None, nsg_name, location, tags, 'rdp' if os_type.lower() == 'windows' else 'ssh'))
nsg = "[resourceId('Microsoft.Network/networkSecurityGroups', '{}')]".format(nsg_name)
vmss_dependencies.append('Microsoft.Network/networkSecurityGroups/{}'.format(nsg_name))
# Since NAT rule V2 can work for both Uniform and Flex VMSS, but basic LB SKU cannot fully support it
# So when users use Standard LB SKU, CLI uses NAT rule V2 by default
if not nat_pool_name:
if nat_rule_name and is_basic_lb_sku:
logger.warning(
'Since the basic SKU of load balancer cannot fully support NAT rule V2, '
'it is recommended to specify "--lb-sku Standard" to use standard SKU instead.')
nat_rule_name = nat_rule_name or 'NatRule'
# The nested resource must follow the pattern parent_resource_name/nested_res_name
nat_rule_name = '{}/{}'.format(load_balancer, nat_rule_name)
nat_rule = build_nat_rule_v2(cmd, nat_rule_name, location, load_balancer, frontend_ip_name,
backend_pool_name, backend_port, instance_count, disable_overprovision)
master_template.add_resource(nat_rule)
# Or handle application gateway creation
if app_gateway_type == 'new':
vmss_dependencies.append('Microsoft.Network/applicationGateways/{}'.format(app_gateway))
ag_dependencies = []
if vnet_type == 'new':
ag_dependencies.append('Microsoft.Network/virtualNetworks/{}'.format(vnet_name))
if public_ip_address_type == 'new':
public_ip_address = public_ip_address or '{}PublicIP'.format(app_gateway)
ag_dependencies.append(
'Microsoft.Network/publicIpAddresses/{}'.format(public_ip_address))
master_template.add_resource(build_public_ip_resource(
cmd, public_ip_address, location, tags,
_get_public_ip_address_allocation(public_ip_address_allocation, None), public_ip_address_dns_name,
None, zones))
public_ip_address_id = '{}/publicIPAddresses/{}'.format(network_id_template,
public_ip_address)
# calculate default names if not provided
backend_port = backend_port or 80
ag_resource = build_application_gateway_resource(
cmd, app_gateway, location, tags, backend_pool_name, backend_port, 'appGwFrontendIP',
public_ip_address_id, subnet_id, gateway_subnet_id, private_ip_address='',
private_ip_allocation='Dynamic', sku=app_gateway_sku, capacity=app_gateway_capacity)
ag_resource['dependsOn'] = ag_dependencies
master_template.add_variable(
'appGwID',
"[resourceId('Microsoft.Network/applicationGateways', '{}')]".format(app_gateway))
master_template.add_resource(ag_resource)
# create storage accounts if needed for unmanaged disk storage
if storage_profile == StorageProfile.SAPirImage:
master_template.add_resource(build_vmss_storage_account_pool_resource(
cmd, 'storageLoop', location, tags, storage_sku, edge_zone))
master_template.add_variable('storageAccountNames', [
'{}{}'.format(naming_prefix, x) for x in range(5)
])
master_template.add_variable('vhdContainers', [
"[concat('https://', variables('storageAccountNames')[{}], '.blob.{}/{}')]".format(
x, cmd.cli_ctx.cloud.suffixes.storage_endpoint, storage_container_name) for x in range(5)
])
vmss_dependencies.append('storageLoop')
backend_address_pool_id = None
inbound_nat_pool_id = None
if load_balancer_type or app_gateway_type:
network_balancer = load_balancer if load_balancer_type else app_gateway
balancer_type = 'loadBalancers' if load_balancer_type else 'applicationGateways'
if is_valid_resource_id(network_balancer):
# backend address pool needed by load balancer or app gateway
backend_address_pool_id = '{}/backendAddressPools/{}'.format(network_balancer, backend_pool_name)
if nat_pool_name:
inbound_nat_pool_id = '{}/inboundNatPools/{}'.format(network_balancer, nat_pool_name)
else:
# backend address pool needed by load balancer or app gateway
backend_address_pool_id = '{}/{}/{}/backendAddressPools/{}'.format(
network_id_template, balancer_type, network_balancer, backend_pool_name)
if nat_pool_name:
inbound_nat_pool_id = '{}/{}/{}/inboundNatPools/{}'.format(
network_id_template, balancer_type, network_balancer, nat_pool_name)
if health_probe and not is_valid_resource_id(health_probe):
health_probe = '{}/loadBalancers/{}/probes/{}'.format(network_id_template, load_balancer, health_probe)
ip_config_name = '{}IPConfig'.format(naming_prefix)
nic_name = '{}Nic'.format(naming_prefix)
if custom_data:
custom_data = read_content_if_is_file(custom_data)
if user_data:
user_data = read_content_if_is_file(user_data)
if secrets:
secrets = _merge_secrets([validate_file_or_dict(secret) for secret in secrets])
if computer_name_prefix is not None and isinstance(computer_name_prefix, str):
naming_prefix = computer_name_prefix
if orchestration_mode.lower() == uniform_str.lower():
computer_name_prefix = naming_prefix
if os_version and os_version != 'latest':
logger.warning('You are deploying VMSS pinned to a specific image version from Azure Marketplace. '
'Consider using "latest" as the image version.')
vmss_resource = build_vmss_resource(
cmd=cmd, name=vmss_name, computer_name_prefix=computer_name_prefix, location=location, tags=tags,
overprovision=not disable_overprovision if orchestration_mode.lower() == uniform_str.lower() else None,
upgrade_policy_mode=upgrade_policy_mode, vm_sku=vm_sku,
instance_count=instance_count, ip_config_name=ip_config_name, nic_name=nic_name, subnet_id=subnet_id,
public_ip_per_vm=public_ip_per_vm, vm_domain_name=vm_domain_name, dns_servers=dns_servers, nsg=nsg,
accelerated_networking=accelerated_networking, admin_username=admin_username,
authentication_type=authentication_type, storage_profile=storage_profile, os_disk_name=os_disk_name,
disk_info=disk_info, os_type=os_type, image=image, admin_password=admin_password,
ssh_key_values=ssh_key_value, ssh_key_path=ssh_dest_key_path, os_publisher=os_publisher, os_offer=os_offer,
os_sku=os_sku, os_version=os_version, backend_address_pool_id=backend_address_pool_id,
inbound_nat_pool_id=inbound_nat_pool_id, health_probe=health_probe,
single_placement_group=single_placement_group, platform_fault_domain_count=platform_fault_domain_count,
custom_data=custom_data, secrets=secrets, license_type=license_type, zones=zones, priority=priority,
eviction_policy=eviction_policy, application_security_groups=application_security_groups,
ultra_ssd_enabled=ultra_ssd_enabled, proximity_placement_group=proximity_placement_group,
terminate_notification_time=terminate_notification_time, max_price=max_price,
scale_in_policy=scale_in_policy, os_disk_encryption_set=os_disk_encryption_set,
data_disk_encryption_sets=data_disk_encryption_sets, data_disk_iops=data_disk_iops,
data_disk_mbps=data_disk_mbps, automatic_repairs_grace_period=automatic_repairs_grace_period,
specialized=specialized, os_disk_size_gb=os_disk_size_gb, encryption_at_host=encryption_at_host,
host_group=host_group, max_batch_instance_percent=max_batch_instance_percent,
max_unhealthy_instance_percent=max_unhealthy_instance_percent,
max_unhealthy_upgraded_instance_percent=max_unhealthy_upgraded_instance_percent,
pause_time_between_batches=pause_time_between_batches, enable_cross_zone_upgrade=enable_cross_zone_upgrade,
prioritize_unhealthy_instances=prioritize_unhealthy_instances, edge_zone=edge_zone, user_data=user_data,
orchestration_mode=orchestration_mode, network_api_version=network_api_version,
enable_spot_restore=enable_spot_restore, spot_restore_timeout=spot_restore_timeout,
capacity_reservation_group=capacity_reservation_group, enable_auto_update=enable_auto_update,
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,
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,
enable_osimage_notification=enable_osimage_notification, max_surge=max_surge,
enable_hibernation=enable_hibernation, enable_auto_os_upgrade=enable_auto_os_upgrade,
enable_proxy_agent=enable_proxy_agent, proxy_agent_mode=proxy_agent_mode,
security_posture_reference_id=security_posture_reference_id,
security_posture_reference_exclude_extensions=security_posture_reference_exclude_extensions,
enable_resilient_vm_creation=enable_resilient_creation,
enable_resilient_vm_deletion=enable_resilient_deletion,
additional_scheduled_events=additional_scheduled_events,
enable_user_reboot_scheduled_events=enable_user_reboot_scheduled_events,
enable_user_redeploy_scheduled_events=enable_user_redeploy_scheduled_events,
skuprofile_vmsizes=skuprofile_vmsizes, skuprofile_allostrat=skuprofile_allostrat,
security_posture_reference_is_overridable=security_posture_reference_is_overridable,
zone_balance=zone_balance, wire_server_mode=wire_server_mode, imds_mode=imds_mode,
wire_server_access_control_profile_reference_id=wire_server_access_control_profile_reference_id,
imds_access_control_profile_reference_id=imds_access_control_profile_reference_id,
enable_automatic_zone_balancing=enable_automatic_zone_balancing,
automatic_zone_balancing_strategy=automatic_zone_balancing_strategy,
automatic_zone_balancing_behavior=automatic_zone_balancing_behavior)
vmss_resource['dependsOn'] = vmss_dependencies
if plan_name:
vmss_resource['plan'] = {
'name': plan_name,
'publisher': plan_publisher,
'product': plan_product,
'promotionCode': plan_promotion_code
}
enable_local_identity = None
if assign_identity is not None:
vmss_resource['identity'], _, _, enable_local_identity = _build_identities_info(
assign_identity)
if identity_scope:
role_assignment_guid = str(_gen_guid())
master_template.add_resource(build_msi_role_assignment(vmss_name, vmss_id, identity_role_id,
role_assignment_guid, identity_scope, False))
if encryption_identity:
if 'identity' in vmss_resource and 'userAssignedIdentities' in vmss_resource['identity'] \
and encryption_identity.lower() in \
(k.lower() for k in vmss_resource['identity']['userAssignedIdentities'].keys()):
if 'virtualMachineProfile' not in vmss_resource['properties']:
vmss_resource['properties']['virtualMachineProfile'] = {}
if 'securityProfile' not in vmss_resource['properties']['virtualMachineProfile']:
vmss_resource['properties']['virtualMachineProfile']['securityProfile'] = {}
if 'encryptionIdentity' not in vmss_resource['properties']['virtualMachineProfile']['securityProfile']:
vmss_resource['properties']['virtualMachineProfile']['securityProfile']['encryptionIdentity'] = {}
vmss_securityProfile_EncryptionIdentity \
= vmss_resource['properties']['virtualMachineProfile']['securityProfile']['encryptionIdentity']
if 'userAssignedIdentityResourceId' not in vmss_securityProfile_EncryptionIdentity or \
vmss_securityProfile_EncryptionIdentity['userAssignedIdentityResourceId'] \
!= encryption_identity:
vmss_securityProfile_EncryptionIdentity['userAssignedIdentityResourceId'] = encryption_identity
vmss_resource['properties']['virtualMachineProfile']['securityProfile']['encryptionIdentity'] \
= vmss_securityProfile_EncryptionIdentity
else:
raise ArgumentUsageError("Encryption Identity should be an ARM Resource ID of one of the "
"user assigned identities associated to the resource")
else:
raise CLIError('usage error: --orchestration-mode (Uniform | Flexible)')
master_template.add_resource(vmss_resource)
master_template.add_output('VMSS', vmss_name, 'Microsoft.Compute', 'virtualMachineScaleSets',
output_type='object')
if admin_password:
master_template.add_secure_parameter('adminPassword', admin_password)
template = master_template.build()
parameters = master_template.build_parameters()
# deploy ARM template
deployment_name = 'vmss_deploy_' + random_string(32)
client = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_RESOURCE_RESOURCES,
aux_subscriptions=aux_subscriptions).deployments
DeploymentProperties = cmd.get_models('DeploymentProperties', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES)
properties = DeploymentProperties(template=template, parameters=parameters, mode='incremental')
if validate:
from azure.cli.command_modules.vm._vm_utils import log_pprint_template
log_pprint_template(template)
log_pprint_template(parameters)
Deployment = cmd.get_models('Deployment', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES)
deployment = Deployment(properties=properties)
if validate:
if cmd.supported_api_version(min_api='2019-10-01', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES):
validation_poller = client.begin_validate(resource_group_name, deployment_name, deployment)
return LongRunningOperation(cmd.cli_ctx)(validation_poller)
return client.validate(resource_group_name, deployment_name, deployment)
# creates the VMSS deployment
deployment_result = DeploymentOutputLongRunningOperation(cmd.cli_ctx)(
sdk_no_wait(no_wait, client.begin_create_or_update, resource_group_name, deployment_name, deployment))
if orchestration_mode.lower() == uniform_str.lower() and assign_identity is not None:
vmss_info = get_vmss(cmd, resource_group_name, vmss_name)
if enable_local_identity and not identity_scope:
_show_missing_access_warning(resource_group_name, vmss_name, 'vmss')
deployment_result['vmss']['identity'] = _construct_identity_info(identity_scope, identity_role,
vmss_info.identity.principal_id,
vmss_info.identity.user_assigned_identities)
# Guest Attestation Extension and enable System Assigned MSI by default
is_trusted_launch = security_type and security_type.lower() == 'trustedlaunch' and\
enable_vtpm and enable_secure_boot
is_confidential_vm = security_type and security_type.lower() == 'confidentialvm'
if (is_trusted_launch or is_confidential_vm) and enable_integrity_monitoring:
client = _compute_client_factory(cmd.cli_ctx)
vmss = client.virtual_machine_scale_sets.get(resource_group_name, vmss_name)
vmss.virtual_machine_profile.storage_profile.image_reference = None
VirtualMachineScaleSetExtension, VirtualMachineScaleSetExtensionProfile = cmd.get_models(
'VirtualMachineScaleSetExtension', 'VirtualMachineScaleSetExtensionProfile')
if vmss.virtual_machine_profile.storage_profile.os_disk.os_type == 'Linux':
publisher = 'Microsoft.Azure.Security.LinuxAttestation'
if vmss.virtual_machine_profile.storage_profile.os_disk.os_type == 'Windows':
publisher = 'Microsoft.Azure.Security.WindowsAttestation'
version = _normalize_extension_version(cmd.cli_ctx, publisher, 'GuestAttestation', None, vmss.location)
ext = VirtualMachineScaleSetExtension(name='GuestAttestation',
publisher=publisher,
type_properties_type='GuestAttestation',
protected_settings=None,
type_handler_version=version,
settings=None,
auto_upgrade_minor_version=True,
provision_after_extensions=None,
enable_automatic_upgrade=not disable_integrity_monitoring_autoupgrade)
if not vmss.virtual_machine_profile.extension_profile:
vmss.virtual_machine_profile.extension_profile = VirtualMachineScaleSetExtensionProfile(extensions=[])
vmss.virtual_machine_profile.extension_profile.extensions.append(ext)
try:
LongRunningOperation(cmd.cli_ctx)(client.virtual_machine_scale_sets.begin_create_or_update(
resource_group_name, vmss_name, vmss))
logger.info('Guest Attestation Extension has been successfully installed by default'
'when Trusted Launch configuration is met')
VirtualMachineScaleSetVMInstanceRequiredIDs = cmd.get_models('VirtualMachineScaleSetVMInstanceRequiredIDs')
instance_ids = VirtualMachineScaleSetVMInstanceRequiredIDs(instance_ids=['*'])
LongRunningOperation(cmd.cli_ctx)(client.virtual_machine_scale_sets.begin_update_instances(
resource_group_name, vmss_name, instance_ids))
except Exception as e:
error_type = "Trusted Launch" if is_trusted_launch else "Confidential VM"
logger.error('Failed to install Guest Attestation Extension for %s. %s', error_type, e)
return deployment_result