def _Create()

in perfkitbenchmarker/providers/azure/azure_virtual_machine.py [0:0]


  def _Create(self):
    """See base class."""
    assert self.network is not None

    os_disk_args = self.create_os_disk_strategy.GetCreationCommand()[
        'create-disk'
    ]
    enable_secure_boot = azure_flags.AZURE_SECURE_BOOT.value
    if (
        self.trusted_launch_unsupported_type
        and enable_secure_boot is not None
    ):
      raise errors.Benchmarks.UnsupportedConfigError(
          "Please don't set --azure_secure_boot for"
          f' {self.machine_type} machine_type. Attemping to update secure boot'
          ' flag on a VM with standard security type fails with error "Use of'
          ' UEFI settings is not supported...".',
      )
    security_args = []
    secure_boot_args = []
    # if machine is confidential or trusted launch, we can update secure boot
    if self.machine_type_is_confidential:
      security_args = [
          '--enable-vtpm',
          'true',
          '--security-type',
          'ConfidentialVM',
          '--os-disk-security-encryption-type',
          'VMGuestStateOnly',
      ]
      if enable_secure_boot is None:
        secure_boot_args = [
            '--enable-secure-boot',
            'true',
        ]
    if enable_secure_boot is not None:
      secure_boot_args = [
          '--enable-secure-boot',
          str(enable_secure_boot).lower(),
      ]

    tags = {}
    tags.update(self.vm_metadata)
    tags.update(util.GetResourceTags(self.resource_group.timeout_minutes))
    # Signal (along with timeout_utc) that VM is short lived.
    tags['vm_nature'] = 'ephemeral'
    tag_args = ['--tags'] + util.FormatTags(tags)

    create_cmd = (
        [
            azure.AZURE_PATH,
            'vm',
            'create',
            '--location',
            self.region,
            '--image',
            self.image,
            '--size',
            self.machine_type,
            '--admin-username',
            self.user_name,
            '--name',
            self.name,
        ]
        + os_disk_args
        + security_args
        + secure_boot_args
        + self.resource_group.args
        + self.nic.args
        + tag_args
    )
    if self.hypervisor_generation > 1:
      # Always specify disk controller type if supported (gen 2 hypervisor).
      # If a machine supports both NVMe and SCSI, it will use NVMe, but PKB will
      # assume it defaults to SCSI and fail to find the disk.
      # Note this does mean PKB will downgrade machines that support both to
      # SCSI unless they are explicitly specified as NVMe.
      # TODO(pclay): Detect whether SKUs support NVMe.
      if self.SupportsNVMe():
        create_cmd.extend(['--disk-controller-type', 'NVMe'])
      else:
        create_cmd.extend(['--disk-controller-type', 'SCSI'])
    if self.trusted_launch_unsupported_type:
      create_cmd.extend(['--security-type', 'Standard'])
    if self.boot_startup_script:
      create_cmd.extend(['--custom-data', self.boot_startup_script])

    if self._RequiresUltraDisk():
      self.ultra_ssd_enabled = True
      create_cmd.extend(['--ultra-ssd-enabled'])

    if self.availability_zone:
      create_cmd.extend(['--zone', self.availability_zone])

    # Resources in Availability Set are not allowed to be
    # deployed to particular hosts.
    if self.use_dedicated_host:
      create_cmd.extend(
          ['--host-group', self.host.host_group, '--host', self.host.name]
      )
      num_hosts = len(self.host_list)

    if self.network.placement_group:
      create_cmd.extend(self.network.placement_group.AddVmArgs())

    if self.low_priority:
      create_cmd.extend(['--priority', 'Spot'])

    if self.password:
      create_cmd.extend(['--admin-password', self.password])
    else:
      create_cmd.extend(['--ssh-key-value', self.ssh_public_key])

    # Uses a custom default because create has a very long tail.
    azure_vm_create_timeout = 1800
    _, stderr, retcode = vm_util.IssueCommand(
        create_cmd, timeout=azure_vm_create_timeout, raise_on_failure=False
    )
    if retcode:
      if 'quota' in stderr.lower():
        raise errors.Benchmarks.QuotaFailure(
            virtual_machine.QUOTA_EXCEEDED_MESSAGE + stderr
        )
      elif self.low_priority and (
          re.search(r'requested VM size \S+ is not available', stderr)
          or re.search(r'not available in location .+ for subscription', stderr)
          or re.search(
              r'Following SKUs have failed for Capacity Restrictions', stderr
          )
      ):
        raise errors.Benchmarks.InsufficientCapacityCloudFailure(stderr)
      elif re.search(
          r'requested VM size \S+ is not available', stderr
      ) or re.search(r'not available in location .+ for subscription', stderr):
        raise errors.Benchmarks.UnsupportedConfigError(stderr)
      elif self.low_priority and 'OverconstrainedAllocationRequest' in stderr:
        raise errors.Benchmarks.InsufficientCapacityCloudFailure(stderr)
      elif _OS_PROVISIONING_TIMED_OUT in stderr:
        raise errors.Resource.ProvisionTimeoutError(stderr)
      elif "Virtual Machine Scale Set with '<NULL>' security type." in stderr:
        raise errors.Resource.CreationError(
            f'Failed to create VM: {self.machine_type} is likely a confidential'
            ' machine, which PKB does not support at this time.\n\n'
            f' Full error: {stderr} return code: {retcode}'
        )
      elif "cannot boot Hypervisor Generation '1'" in stderr:
        raise errors.Resource.CreationError(
            f'Failed to create VM: {self.machine_type} is unable to support V1 '
            'Hypervision. Please update _MACHINE_TYPES_ONLY_SUPPORT_GEN1_IMAGES'
            ' in azure_virtual_machine.py.\n\n'
            f' Full error: {stderr} return code: {retcode}'
        )
      elif self.use_dedicated_host and 'AllocationFailed' in stderr:
        if self.num_vms_per_host:
          raise errors.Resource.CreationError(
              'Failed to create host: %d vms of type %s per host exceeds '
              'memory capacity limits of the host'
              % (self.num_vms_per_host, self.machine_type)
          )
        else:
          logging.warning(
              'Creation failed due to insufficient host capacity. A new host '
              'will be created and instance creation will be retried.'
          )
          with self._lock:
            if num_hosts == len(self.host_list):
              new_host = AzureDedicatedHost(
                  self.name,
                  self.region,
                  self.resource_group,
                  self.host_series_sku,
                  self.availability_zone,
              )
              self.host_list.append(new_host)
              new_host.Create()
            self.host = self.host_list[-1]
          raise errors.Resource.RetryableCreationError()
      elif not self.use_dedicated_host and 'AllocationFailed' in stderr:
        raise errors.Benchmarks.InsufficientCapacityCloudFailure(stderr)
      elif (
          not self.use_dedicated_host
          and 'OverconstrainedZonalAllocationRequest' in stderr
      ):
        raise errors.Benchmarks.UnsupportedConfigError(stderr)
      elif _SKU_NOT_AVAILABLE in stderr:
        raise errors.Benchmarks.UnsupportedConfigError(stderr)
      else:
        raise errors.Resource.CreationError(stderr)