예제 #1
0
  def _CreateRequests(self, args, instance_refs,
                      compute_client, resource_parser):
    # gcloud creates default values for some fields in Instance resource
    # when no value was specified on command line.
    # When --source-instance-template was specified, defaults are taken from
    # Instance Template and gcloud flags are used to override them - by default
    # fields should not be initialized.
    source_instance_template = self.GetSourceInstanceTemplate(
        args, resource_parser)
    skip_defaults = source_instance_template is not None

    # This feature is only exposed in alpha/beta
    allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                                  base.ReleaseTrack.BETA]
    self.csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)

    if (skip_defaults and not args.IsSpecified('maintenance_policy') and
        not args.IsSpecified('preemptible') and
        not args.IsSpecified('restart_on_failure')):
      scheduling = None
    else:
      scheduling = instance_utils.CreateSchedulingMessage(
          messages=compute_client.messages,
          maintenance_policy=args.maintenance_policy,
          preemptible=args.preemptible,
          restart_on_failure=args.restart_on_failure)

    if args.tags:
      tags = compute_client.messages.Tags(items=args.tags)
    else:
      tags = None

    labels = None
    args_labels = getattr(args, 'labels', None)
    if args_labels:
      labels = compute_client.messages.Instance.LabelsValue(
          additionalProperties=[
              compute_client.messages.Instance.LabelsValue.AdditionalProperty(
                  key=key, value=value)
              for key, value in sorted(args.labels.iteritems())])

    if (skip_defaults and not args.IsSpecified('metadata') and
        not args.IsSpecified('metadata_from_file')):
      metadata = None
    else:
      metadata = metadata_utils.ConstructMetadataMessage(
          compute_client.messages,
          metadata=args.metadata,
          metadata_from_file=args.metadata_from_file)

    # If the user already provided an initial Windows password and
    # username through metadata, then there is no need to check
    # whether the image or the boot disk is Windows.

    boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
    utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

    # Check if the zone is deprecated or has maintenance coming.
    zone_resource_fetcher = zone_utils.ZoneResourceFetcher(compute_client)
    zone_resource_fetcher.WarnForZonalCreation(instance_refs)

    network_interface_arg = getattr(args, 'network_interface', None)
    if network_interface_arg:
      network_interfaces = instance_utils.CreateNetworkInterfaceMessages(
          resources=resource_parser,
          compute_client=compute_client,
          network_interface_arg=network_interface_arg,
          instance_refs=instance_refs,
          support_network_tier=self._support_network_tier)
    else:
      if self._support_public_dns is True:
        instances_flags.ValidatePublicDnsFlags(args)
      if self._support_public_ptr is True:
        instances_flags.ValidatePublicPtrFlags(args)

      if (skip_defaults and not args.IsSpecified('network') and
          not args.IsSpecified('subnet') and
          not args.IsSpecified('private_network_ip') and
          not args.IsSpecified('no_address') and
          not args.IsSpecified('address') and
          not args.IsSpecified('network_tier') and
          not args.IsSpecified('no_public_dns') and
          not args.IsSpecified('public_dns') and
          not args.IsSpecified('no_public_ptr') and
          not args.IsSpecified('public_ptr') and
          not args.IsSpecified('no_public_ptr_domain') and
          not args.IsSpecified('public_ptr_domain')):
        network_interfaces = []
      else:
        network_tier = getattr(args, 'network_tier', None)

        network_interfaces = [
            instance_utils.CreateNetworkInterfaceMessage(
                resources=resource_parser,
                compute_client=compute_client,
                network=args.network,
                subnet=args.subnet,
                private_network_ip=args.private_network_ip,
                no_address=args.no_address,
                address=args.address,
                instance_refs=instance_refs,
                network_tier=network_tier,
                no_public_dns=getattr(args, 'no_public_dns', None),
                public_dns=getattr(args, 'public_dns', None),
                no_public_ptr=getattr(args, 'no_public_ptr', None),
                public_ptr=getattr(args, 'public_ptr', None),
                no_public_ptr_domain=getattr(args, 'no_public_ptr_domain',
                                             None),
                public_ptr_domain=getattr(args, 'public_ptr_domain', None))
        ]

    if (skip_defaults and not args.IsSpecified('machine_type') and
        not args.IsSpecified('custom_cpu') and
        not args.IsSpecified('custom_memory')):
      machine_type_uris = [None for _ in instance_refs]
    else:
      machine_type_uris = instance_utils.CreateMachineTypeUris(
          resources=resource_parser,
          compute_client=compute_client,
          machine_type=args.machine_type,
          custom_cpu=args.custom_cpu,
          custom_memory=args.custom_memory,
          ext=getattr(args, 'custom_extensions', None),
          instance_refs=instance_refs)

    create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or [])
    if create_boot_disk:
      image_expander = image_utils.ImageExpander(compute_client,
                                                 resource_parser)
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=instance_refs[0].project,
          image=args.image,
          image_family=args.image_family,
          image_project=args.image_project,
          return_image_resource=False)
    else:
      image_uri = None

    # A list of lists where the element at index i contains a list of
    # disk messages that should be set for the instance at index i.
    disks_messages = []

    # A mapping of zone to boot disk references for all existing boot
    # disks that are being attached.
    # TODO(b/36050875): Simplify since resources.Resource is now hashable.
    existing_boot_disks = {}

    if (skip_defaults and not args.IsSpecified('disk') and
        not args.IsSpecified('create_disk') and
        not args.IsSpecified('local_ssd') and
        not args.IsSpecified('boot_disk_type') and
        not args.IsSpecified('boot_disk_device_name') and
        not args.IsSpecified('boot_disk_auto_delete') and
        not args.IsSpecified('boot_disk_kms_key') and
        not args.IsSpecified('boot_disk_kms_project') and
        not args.IsSpecified('boot_disk_kms_location') and
        not args.IsSpecified('boot_disk_kms_keyring') and
        not args.IsSpecified('require_csek_key_create')):
      disks_messages = [[] for _ in instance_refs]
    else:
      for instance_ref in instance_refs:
        persistent_disks, boot_disk_ref = (
            instance_utils.CreatePersistentAttachedDiskMessages(
                resource_parser, compute_client, self.csek_keys,
                args.disk or [], instance_ref))
        persistent_create_disks = (
            instance_utils.CreatePersistentCreateDiskMessages(
                compute_client,
                resource_parser,
                self.csek_keys,
                getattr(args, 'create_disk', []),
                instance_ref))
        local_ssds = []
        for x in args.local_ssd or []:
          local_ssds.append(
              instance_utils.CreateLocalSsdMessage(
                  resource_parser,
                  compute_client.messages,
                  x.get('device-name'),
                  x.get('interface'),
                  x.get('size'),
                  instance_ref.zone,
                  instance_ref.project)
          )

        if create_boot_disk:
          boot_disk = instance_utils.CreateDefaultBootAttachedDiskMessage(
              compute_client, resource_parser,
              disk_type=args.boot_disk_type,
              disk_device_name=args.boot_disk_device_name,
              disk_auto_delete=args.boot_disk_auto_delete,
              disk_size_gb=boot_disk_size_gb,
              require_csek_key_create=(
                  args.require_csek_key_create if self.csek_keys else None),
              image_uri=image_uri,
              instance_ref=instance_ref,
              csek_keys=self.csek_keys,
              kms_args=args)
          persistent_disks = [boot_disk] + persistent_disks
        else:
          existing_boot_disks[boot_disk_ref.zone] = boot_disk_ref
        disks_messages.append(persistent_disks + persistent_create_disks +
                              local_ssds)

    accelerator_args = getattr(args, 'accelerator', None)

    project_to_sa = {}
    requests = []
    for instance_ref, machine_type_uri, disks in zip(
        instance_refs, machine_type_uris, disks_messages):
      if instance_ref.project not in project_to_sa:
        scopes = None
        if not args.no_scopes and not args.scopes:
          # User didn't provide any input on scopes. If project has no default
          # service account then we want to create a VM with no scopes
          request = (compute_client.apitools_client.projects,
                     'Get',
                     compute_client.messages.ComputeProjectsGetRequest(
                         project=instance_ref.project))
          errors = []
          result = compute_client.MakeRequests([request], errors)
          if not errors:
            if not result[0].defaultServiceAccount:
              scopes = []
              log.status.Print(
                  'There is no default service account for project {}. '
                  'Instance {} will not have scopes.'.format(
                      instance_ref.project, instance_ref.Name))
        if scopes is None:
          scopes = [] if args.no_scopes else args.scopes

        if args.no_service_account:
          service_account = None
        else:
          service_account = args.service_account
        if (skip_defaults and not args.IsSpecified('scopes') and
            not args.IsSpecified('no_scopes') and
            not args.IsSpecified('service_account') and
            not args.IsSpecified('no_service_account')):
          service_accounts = []
        else:
          service_accounts = instance_utils.CreateServiceAccountMessages(
              messages=compute_client.messages,
              scopes=scopes,
              service_account=service_account)
        project_to_sa[instance_ref.project] = service_accounts

      if skip_defaults and not args.IsSpecified('can_ip_forward'):
        can_ip_forward = None
      else:
        can_ip_forward = args.can_ip_forward

      instance = compute_client.messages.Instance(
          canIpForward=can_ip_forward,
          disks=disks,
          description=args.description,
          machineType=machine_type_uri,
          metadata=metadata,
          minCpuPlatform=args.min_cpu_platform,
          name=instance_ref.Name(),
          networkInterfaces=network_interfaces,
          serviceAccounts=project_to_sa[instance_ref.project],
          scheduling=scheduling,
          tags=tags)
      if getattr(args, 'deletion_protection', None) is not None:
        instance.deletionProtection = args.deletion_protection
      if labels:
        instance.labels = labels
      if accelerator_args:
        accelerator_type_name = accelerator_args['type']
        accelerator_type_ref = resource_parser.Parse(
            accelerator_type_name,
            collection='compute.acceleratorTypes',
            params={'project': instance_ref.project,
                    'zone': instance_ref.zone})
        # Accelerator count is default to 1.
        accelerator_count = int(accelerator_args.get('count', 1))
        accelerators = instance_utils.CreateAcceleratorConfigMessages(
            compute_client.messages, accelerator_type_ref,
            accelerator_count)
        instance.guestAccelerators = accelerators

      request = compute_client.messages.ComputeInstancesInsertRequest(
          instance=instance,
          project=instance_ref.project,
          zone=instance_ref.zone)

      if source_instance_template:
        request.sourceInstanceTemplate = source_instance_template

      sole_tenancy_host_arg = getattr(args, 'sole_tenancy_host', None)
      if sole_tenancy_host_arg:
        sole_tenancy_host_ref = resource_parser.Parse(
            sole_tenancy_host_arg, collection='compute.hosts',
            params={
                'project': instance_ref.project,
                'zone': instance_ref.zone
            })
        request.instance.host = sole_tenancy_host_ref.SelfLink()
      requests.append(
          (compute_client.apitools_client.instances, 'Insert', request))
    return requests
예제 #2
0
    def _Run(self, args):
        """Returns a list of requests necessary for adding images."""
        holder = self._GetApiHolder()
        client = holder.client
        messages = client.messages
        resource_parser = holder.resources

        image_ref = Create.DISK_IMAGE_ARG.ResolveAsResource(
            args, holder.resources)
        image = messages.Image(
            name=image_ref.image,
            description=args.description,
            sourceType=messages.Image.SourceTypeValueValuesEnum.RAW,
            family=args.family)

        csek_keys = csek_utils.CsekKeyStore.FromArgs(
            args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS)
        if csek_keys:
            image.imageEncryptionKey = csek_utils.MaybeToMessage(
                csek_keys.LookupKey(
                    image_ref, raise_if_missing=args.require_csek_key_create),
                client.apitools_client)
        image.imageEncryptionKey = kms_utils.MaybeGetKmsKey(
            args, messages, image.imageEncryptionKey)

        # Validate parameters.
        if args.source_disk_zone and not args.source_disk:
            raise exceptions.ToolException(
                'You cannot specify [--source-disk-zone] unless you are specifying '
                '[--source-disk].')

        source_image_project = args.source_image_project
        source_image = args.source_image
        source_image_family = args.source_image_family

        if source_image_project and not (source_image or source_image_family):
            raise exceptions.ToolException(
                'You cannot specify [--source-image-project] unless you are '
                'specifying [--source-image] or [--source-image-family].')

        if source_image or source_image_family:
            image_expander = image_utils.ImageExpander(client, resource_parser)
            _, source_image_ref = image_expander.ExpandImageFlag(
                user_project=image_ref.project,
                image=source_image,
                image_family=source_image_family,
                image_project=source_image_project,
                return_image_resource=True)
            image.sourceImage = source_image_ref.selfLink
            image.sourceImageEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_image_ref, client.apitools_client)

        if args.source_uri:
            source_uri = six.text_type(
                resources.REGISTRY.Parse(args.source_uri))
            image.rawDisk = messages.Image.RawDiskValue(source=source_uri)
        elif args.source_disk:
            source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceDisk = source_disk_ref.SelfLink()
            image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_disk_ref, client.apitools_client)
        elif hasattr(args, 'source_snapshot') and args.source_snapshot:
            source_snapshot_ref = flags.SOURCE_SNAPSHOT_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceSnapshot = source_snapshot_ref.SelfLink()
            image.sourceSnapshotEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_snapshot_ref, client.apitools_client)

        if args.licenses:
            image.licenses = args.licenses

        guest_os_features = getattr(args, 'guest_os_features', [])
        if guest_os_features:
            guest_os_feature_messages = []
            for feature in guest_os_features:
                gf_type = messages.GuestOsFeature.TypeValueValuesEnum(feature)
                guest_os_feature = messages.GuestOsFeature()
                guest_os_feature.type = gf_type
                guest_os_feature_messages.append(guest_os_feature)
            image.guestOsFeatures = guest_os_feature_messages

        initial_state, has_set =\
            image_utils.CreateInitialStateConfig(args, messages)
        if has_set:
            image.shieldedInstanceInitialState = initial_state

        if args.IsSpecified('storage_location'):
            image.storageLocations = [args.storage_location]

        request = messages.ComputeImagesInsertRequest(
            image=image, project=image_ref.project)

        args_labels = getattr(args, 'labels', None)
        if args_labels:
            labels = messages.Image.LabelsValue(additionalProperties=[
                messages.Image.LabelsValue.AdditionalProperty(key=key,
                                                              value=value)
                for key, value in sorted(six.iteritems(args_labels))
            ])
            request.image.labels = labels

        # --force is in GA, --force-create is in beta and deprecated.
        if args.force or getattr(args, 'force_create', None):
            request.forceCreate = True

        return client.MakeRequests(
            [(client.apitools_client.images, 'Insert', request)],
            timeout=POLL_TIMEOUT)
예제 #3
0
    def Run(self, args):
        """Creates and runs an InstanceTemplates.Insert request.

    Args:
      args: argparse.Namespace, An object that contains the values for the
          arguments specified in the .Args() method.

    Returns:
      A resource object dispatched by display.Displayer().
    """
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client

        self.ValidateDiskFlags(args)
        instances_flags.ValidateLocalSsdFlags(args)
        instances_flags.ValidateNicFlags(args)
        instances_flags.ValidateServiceAccountAndScopeArgs(args)
        instances_flags.ValidateAcceleratorArgs(args)

        boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
        utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

        instance_template_ref = (Create.InstanceTemplateArg.ResolveAsResource(
            args, holder.resources))

        metadata = metadata_utils.ConstructMetadataMessage(
            client.messages,
            metadata=args.metadata,
            metadata_from_file=args.metadata_from_file)

        if hasattr(args, 'network_interface') and args.network_interface:
            network_interfaces = (
                instance_template_utils.CreateNetworkInterfaceMessages)(
                    resources=holder.resources,
                    scope_lister=flags.GetDefaultScopeLister(client),
                    messages=client.messages,
                    network_interface_arg=args.network_interface,
                    region=args.region,
                    support_network_tier=self._support_network_tier)
        else:
            network_tier = getattr(args, 'network_tier', None)
            network_interfaces = [
                instance_template_utils.CreateNetworkInterfaceMessage(
                    resources=holder.resources,
                    scope_lister=flags.GetDefaultScopeLister(client),
                    messages=client.messages,
                    network=args.network,
                    region=args.region,
                    subnet=args.subnet,
                    address=(instance_template_utils.EPHEMERAL_ADDRESS
                             if not args.no_address and not args.address else
                             args.address),
                    network_tier=network_tier)
            ]

        scheduling = instance_utils.CreateSchedulingMessage(
            messages=client.messages,
            maintenance_policy=args.maintenance_policy,
            preemptible=args.preemptible,
            restart_on_failure=args.restart_on_failure)

        if args.no_service_account:
            service_account = None
        else:
            service_account = args.service_account
        service_accounts = instance_utils.CreateServiceAccountMessages(
            messages=client.messages,
            scopes=[] if args.no_scopes else args.scopes,
            service_account=service_account)

        create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk
                                                                  or [])
        if create_boot_disk:
            image_expander = image_utils.ImageExpander(client,
                                                       holder.resources)
            try:
                image_uri, _ = image_expander.ExpandImageFlag(
                    user_project=instance_template_ref.project,
                    image=args.image,
                    image_family=args.image_family,
                    image_project=args.image_project,
                    return_image_resource=True)
            except utils.ImageNotFoundError as e:
                if args.IsSpecified('image_project'):
                    raise e
                image_uri, _ = image_expander.ExpandImageFlag(
                    user_project=instance_template_ref.project,
                    image=args.image,
                    image_family=args.image_family,
                    image_project=args.image_project,
                    return_image_resource=False)
                raise utils.ImageNotFoundError(
                    'The resource [{}] was not found. Is the image located in another '
                    'project? Use the --image-project flag to specify the '
                    'project where the image is located.'.format(image_uri))
        else:
            image_uri = None

        if args.tags:
            tags = client.messages.Tags(items=args.tags)
        else:
            tags = None

        persistent_disks = (
            instance_template_utils.CreatePersistentAttachedDiskMessages(
                client.messages, args.disk or []))

        persistent_create_disks = (
            instance_template_utils.CreatePersistentCreateDiskMessages(
                client, holder.resources, instance_template_ref.project,
                getattr(args, 'create_disk', [])))

        if create_boot_disk:
            boot_disk_list = [
                instance_template_utils.CreateDefaultBootAttachedDiskMessage(
                    messages=client.messages,
                    disk_type=args.boot_disk_type,
                    disk_device_name=args.boot_disk_device_name,
                    disk_auto_delete=args.boot_disk_auto_delete,
                    disk_size_gb=boot_disk_size_gb,
                    image_uri=image_uri)
            ]
        else:
            boot_disk_list = []

        local_ssds = []
        for x in args.local_ssd or []:
            local_ssd = instance_utils.CreateLocalSsdMessage(
                holder.resources, client.messages, x.get('device-name'),
                x.get('interface'), x.get('size'))
            local_ssds.append(local_ssd)

        disks = (boot_disk_list + persistent_disks + persistent_create_disks +
                 local_ssds)

        machine_type = instance_utils.InterpretMachineType(
            machine_type=args.machine_type,
            custom_cpu=args.custom_cpu,
            custom_memory=args.custom_memory,
            ext=getattr(args, 'custom_extensions', None))

        guest_accelerators = (
            instance_template_utils.CreateAcceleratorConfigMessages(
                client.messages, getattr(args, 'accelerator', None)))

        instance_properties = client.messages.InstanceProperties(
            machineType=machine_type,
            disks=disks,
            canIpForward=args.can_ip_forward,
            metadata=metadata,
            networkInterfaces=network_interfaces,
            serviceAccounts=service_accounts,
            scheduling=scheduling,
            tags=tags,
        )

        # TODO(b/36890961): Pass this directly into guestAccelerators once GA.
        if guest_accelerators:
            instance_properties.guestAccelerators = guest_accelerators

        request = client.messages.ComputeInstanceTemplatesInsertRequest(
            instanceTemplate=client.messages.InstanceTemplate(
                properties=instance_properties,
                description=args.description,
                name=instance_template_ref.Name(),
            ),
            project=instance_template_ref.project)

        if getattr(args, 'min_cpu_platform', None):
            request.instanceTemplate.properties.minCpuPlatform = args.min_cpu_platform

        return client.MakeRequests([(client.apitools_client.instanceTemplates,
                                     'Insert', request)])
예제 #4
0
def CreatePersistentCreateDiskMessages(compute_client,
                                       resources,
                                       csek_keys,
                                       create_disks,
                                       project,
                                       location,
                                       scope,
                                       holder,
                                       enable_kms=False,
                                       enable_snapshots=False,
                                       container_mount_disk=None,
                                       resource_policy=False,
                                       enable_source_snapshot_csek=False,
                                       enable_image_csek=False,
                                       support_replica_zones=False):
  """Returns a list of AttachedDisk messages for newly creating disks.

  Args:
    compute_client: creates resources,
    resources: parser of resources,
    csek_keys: customer suplied encryption keys,
    create_disks: disk objects - contains following properties * name - the name
      of disk, * description - an optional description for the disk, * mode -
      'rw' (R/W), 'ro' (R/O) access mode, * disk-size - the size of the disk, *
      disk-type - the type of the disk (HDD or SSD), * image - the name of the
      image to initialize from, * image-csek-required - the name of the CSK
      protected image, * image-family - the image family name, * image-project -
      the project name that has the image, * auto-delete - whether disks is
      deleted when VM is deleted, * device-name - device name on VM, *
      source-snapshot - the snapshot to initialize from, *
      source-snapshot-csek-required - CSK protected snapshot, *
      disk-resource-policy - resource policies applied to disk. *
      enable_source_snapshot_csek - CSK file for snapshot, * enable_image_csek -
      CSK file for image
    project: Project of instance that will own the new disks.
    location: Location of the instance that will own the new disks.
    scope: Location type of the instance that will own the new disks.
    holder: Convenience class to hold lazy initialized client and resources.
    enable_kms: True if KMS keys are supported for the disk.
    enable_snapshots: True if snapshot initialization is supported for the disk.
    container_mount_disk: list of disks to be mounted to container, if any.
    resource_policy: True if resource-policies are enabled
    enable_source_snapshot_csek: True if snapshot CSK files are enabled
    enable_image_csek: True if image CSK files are enabled
    support_replica_zones: True if we allow creation of regional disks

  Returns:
    list of API messages for attached disks
  """
  disks_messages = []

  messages = compute_client.messages
  compute = compute_client.apitools_client
  for disk in create_disks or []:
    name = disk.get('name')

    # Resolves the mode.
    mode_value = disk.get('mode', 'rw')
    if mode_value == 'rw':
      mode = messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
    else:
      mode = messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

    auto_delete_value = disk.get('auto-delete', 'yes')
    auto_delete = auto_delete_value == 'yes'

    disk_size_gb = utils.BytesToGb(disk.get('size'))
    disk_type = disk.get('type')
    if disk_type:
      disk_type_ref = instance_utils.ParseDiskType(resources, disk_type,
                                                   project, location, scope)
      disk_type_uri = disk_type_ref.SelfLink()
    else:
      disk_type_uri = None

    img = disk.get('image')
    img_family = disk.get('image-family')
    img_project = disk.get('image-project')

    image_uri = None
    if img or img_family:
      image_expander = image_utils.ImageExpander(compute_client, resources)
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=project,
          image=img,
          image_family=img_family,
          image_project=img_project,
          return_image_resource=False)

    image_key = None
    disk_key = None
    if csek_keys:
      image_key = csek_utils.MaybeLookupKeyMessagesByUri(
          csek_keys, resources, [image_uri], compute)
      if name:
        disk_ref = resources.Parse(
            name, collection='compute.disks', params={'zone': location})
        disk_key = csek_utils.MaybeLookupKeyMessage(csek_keys, disk_ref,
                                                    compute)

    if enable_kms:
      disk_key = kms_utils.MaybeGetKmsKeyFromDict(disk, messages, disk_key)

    initialize_params = messages.AttachedDiskInitializeParams(
        diskName=name,
        description=disk.get('description'),
        sourceImage=image_uri,
        diskSizeGb=disk_size_gb,
        diskType=disk_type_uri,
        sourceImageEncryptionKey=image_key)

    replica_zones = disk.get('replica-zones')
    if support_replica_zones and replica_zones:
      normalized_zones = []
      for zone in replica_zones:
        zone_ref = holder.resources.Parse(
            zone, collection='compute.zones', params={'project': project})
        normalized_zones.append(zone_ref.SelfLink())
      initialize_params.replicaZones = normalized_zones

    if enable_snapshots:
      snapshot_name = disk.get('source-snapshot')
      attached_snapshot_uri = instance_utils.ResolveSnapshotURI(
          snapshot=snapshot_name,
          user_project=project,
          resource_parser=resources)
      if attached_snapshot_uri:
        initialize_params.sourceImage = None
        initialize_params.sourceSnapshot = attached_snapshot_uri

    if resource_policy:
      policies = disk.get('disk-resource-policy')
      if policies:
        initialize_params.resourcePolicies = policies

    if enable_image_csek:
      image_key_file = disk.get('image_csek')
      if image_key_file:
        initialize_params.imageKeyFile = image_key_file

    if enable_source_snapshot_csek:
      snapshot_key_file = disk.get('source_snapshot_csek')
      if snapshot_key_file:
        initialize_params.snapshotKeyFile = snapshot_key_file
    boot = disk.get('boot') == 'yes'
    multi_writer = disk.get('multi-writer') == 'yes'
    if multi_writer:
      initialize_params.multiWriter = True
    device_name = instance_utils.GetDiskDeviceName(disk, name,
                                                   container_mount_disk)
    create_disk = messages.AttachedDisk(
        autoDelete=auto_delete,
        boot=boot,
        deviceName=device_name,
        initializeParams=initialize_params,
        mode=mode,
        type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
        diskEncryptionKey=disk_key)
    disks_messages.append(create_disk)

  return disks_messages
예제 #5
0
def _RunCreate(compute_api,
               args,
               support_source_instance,
               support_kms=False,
               support_min_node_cpu=False,
               support_confidential_compute=False,
               support_location_hint=False):
    """Common routine for creating instance template.

  This is shared between various release tracks.

  Args:
      compute_api: The compute api.
      args: argparse.Namespace, An object that contains the values for the
        arguments specified in the .Args() method.
      support_source_instance: indicates whether source instance is supported.
      support_kms: Indicate whether KMS is integrated or not.
      support_min_node_cpu: Indicate whether the --min-node-cpu flag for
        sole tenancy overcommit is supported.
      support_confidential_compute: Indicate whether confidential compute is
        supported.
      support_location_hint: Indicate whether location hint is supported

  Returns:
      A resource object dispatched by display.Displayer().
  """
    _ValidateInstancesFlags(args, support_kms=support_kms)
    instances_flags.ValidateNetworkTierArgs(args)

    instance_templates_flags.ValidateMeshModeFlags(args)

    client = compute_api.client

    boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
    utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

    instance_template_ref = (Create.InstanceTemplateArg.ResolveAsResource(
        args, compute_api.resources))

    AddScopesForMeshMode(args)
    AddMeshArgsToMetadata(args)

    metadata = metadata_utils.ConstructMetadataMessage(
        client.messages,
        metadata=args.metadata,
        metadata_from_file=args.metadata_from_file)

    if hasattr(args, 'network_interface') and args.network_interface:
        network_interfaces = (
            instance_template_utils.CreateNetworkInterfaceMessages)(
                resources=compute_api.resources,
                scope_lister=flags.GetDefaultScopeLister(client),
                messages=client.messages,
                network_interface_arg=args.network_interface,
                region=args.region)
    else:
        network_tier = getattr(args, 'network_tier', None)
        network_interfaces = [
            instance_template_utils.CreateNetworkInterfaceMessage(
                resources=compute_api.resources,
                scope_lister=flags.GetDefaultScopeLister(client),
                messages=client.messages,
                network=args.network,
                private_ip=args.private_network_ip,
                region=args.region,
                subnet=args.subnet,
                address=(instance_template_utils.EPHEMERAL_ADDRESS
                         if not args.no_address and not args.address else
                         args.address),
                network_tier=network_tier)
        ]

    # Compute the shieldedInstanceConfig message.
    shieldedinstance_config_message = BuildShieldedInstanceConfigMessage(
        messages=client.messages, args=args)

    if support_confidential_compute:
        confidential_instance_config_message = (
            BuildConfidentialInstanceConfigMessage(messages=client.messages,
                                                   args=args))

    node_affinities = sole_tenancy_util.GetSchedulingNodeAffinityListFromArgs(
        args, client.messages)

    min_node_cpu = None
    if support_min_node_cpu and args.IsSpecified('min_node_cpu'):
        min_node_cpu = args.min_node_cpu

    location_hint = None
    if support_location_hint and args.IsSpecified('location_hint'):
        location_hint = args.location_hint

    scheduling = instance_utils.CreateSchedulingMessage(
        messages=client.messages,
        maintenance_policy=args.maintenance_policy,
        preemptible=args.preemptible,
        restart_on_failure=args.restart_on_failure,
        node_affinities=node_affinities,
        min_node_cpu=min_node_cpu,
        location_hint=location_hint)

    if args.no_service_account:
        service_account = None
    else:
        service_account = args.service_account
    service_accounts = instance_utils.CreateServiceAccountMessages(
        messages=client.messages,
        scopes=[] if args.no_scopes else args.scopes,
        service_account=service_account)

    create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or [])
    if create_boot_disk:
        image_expander = image_utils.ImageExpander(client,
                                                   compute_api.resources)
        try:
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=instance_template_ref.project,
                image=args.image,
                image_family=args.image_family,
                image_project=args.image_project,
                return_image_resource=True)
        except utils.ImageNotFoundError as e:
            if args.IsSpecified('image_project'):
                raise e
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=instance_template_ref.project,
                image=args.image,
                image_family=args.image_family,
                image_project=args.image_project,
                return_image_resource=False)
            raise utils.ImageNotFoundError(
                'The resource [{}] was not found. Is the image located in another '
                'project? Use the --image-project flag to specify the '
                'project where the image is located.'.format(image_uri))
    else:
        image_uri = None

    if args.tags:
        tags = client.messages.Tags(items=args.tags)
    else:
        tags = None

    persistent_disks = (
        instance_template_utils.CreatePersistentAttachedDiskMessages(
            client.messages, args.disk or []))

    persistent_create_disks = (
        instance_template_utils.CreatePersistentCreateDiskMessages(
            client,
            compute_api.resources,
            instance_template_ref.project,
            getattr(args, 'create_disk', []),
            support_kms=support_kms))

    if create_boot_disk:
        boot_disk_list = [
            instance_template_utils.CreateDefaultBootAttachedDiskMessage(
                messages=client.messages,
                disk_type=args.boot_disk_type,
                disk_device_name=args.boot_disk_device_name,
                disk_auto_delete=args.boot_disk_auto_delete,
                disk_size_gb=boot_disk_size_gb,
                image_uri=image_uri,
                kms_args=args,
                support_kms=support_kms)
        ]
    else:
        boot_disk_list = []

    local_nvdimms = instance_utils.CreateLocalNvdimmMessages(
        args,
        compute_api.resources,
        client.messages,
    )

    local_ssds = instance_utils.CreateLocalSsdMessages(
        args,
        compute_api.resources,
        client.messages,
    )

    disks = (boot_disk_list + persistent_disks + persistent_create_disks +
             local_nvdimms + local_ssds)

    machine_type = instance_utils.InterpretMachineType(
        machine_type=args.machine_type,
        custom_cpu=args.custom_cpu,
        custom_memory=args.custom_memory,
        ext=getattr(args, 'custom_extensions', None),
        vm_type=getattr(args, 'custom_vm_type', None))

    guest_accelerators = (
        instance_template_utils.CreateAcceleratorConfigMessages(
            client.messages, getattr(args, 'accelerator', None)))

    instance_template = client.messages.InstanceTemplate(
        properties=client.messages.InstanceProperties(
            machineType=machine_type,
            disks=disks,
            canIpForward=args.can_ip_forward,
            metadata=metadata,
            minCpuPlatform=args.min_cpu_platform,
            networkInterfaces=network_interfaces,
            serviceAccounts=service_accounts,
            scheduling=scheduling,
            tags=tags,
            guestAccelerators=guest_accelerators,
        ),
        description=args.description,
        name=instance_template_ref.Name(),
    )

    instance_template.properties.shieldedInstanceConfig = shieldedinstance_config_message

    instance_template.properties.reservationAffinity = instance_utils.GetReservationAffinity(
        args, client)

    if support_confidential_compute:
        instance_template.properties.confidentialInstanceConfig = (
            confidential_instance_config_message)

    request = client.messages.ComputeInstanceTemplatesInsertRequest(
        instanceTemplate=instance_template,
        project=instance_template_ref.project)

    request.instanceTemplate.properties.labels = ParseCreateArgsWithMeshMode(
        args, client.messages.InstanceProperties.LabelsValue)

    _AddSourceInstanceToTemplate(compute_api, args, instance_template,
                                 support_source_instance)

    return client.MakeRequests([(client.apitools_client.instanceTemplates,
                                 'Insert', request)])
예제 #6
0
def CreatePersistentCreateDiskMessages(compute_client,
                                       resources,
                                       csek_keys,
                                       create_disks,
                                       instance_ref,
                                       enable_kms=False,
                                       enable_snapshots=False,
                                       container_mount_disk=None):
    """Returns a list of AttachedDisk messages for newly creating disks.

  Args:
    compute_client: creates resources,
    resources: parser of resources,
    csek_keys: customer suplied encryption keys,
    create_disks: disk objects - contains following properties
             * name - the name of disk,
             * description - an optional description for the disk,
             * mode - 'rw' (R/W), 'ro' (R/O) access mode,
             * disk-size - the size of the disk,
             * disk-type - the type of the disk (HDD or SSD),
             * image - the name of the image to initialize from,
             * image-family - the image family name,
             * image-project - the project name that has the image,
             * auto-delete - whether disks is deleted when VM is deleted,
             * device-name - device name on VM,
             * source-snapshot - the snapshot to initialize from.
    instance_ref: reference to the instance that will own the new disks.
    enable_kms: True if KMS keys are supported for the disk.
    enable_snapshots: True if snapshot initialization is supported for the disk.
    container_mount_disk: list of disks to be mounted to container, if any.

  Returns:
    list of API messages for attached disks
  """
    disks_messages = []

    messages = compute_client.messages
    compute = compute_client.apitools_client
    for disk in create_disks or []:
        name = disk.get('name')

        # Resolves the mode.
        mode_value = disk.get('mode', 'rw')
        if mode_value == 'rw':
            mode = messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
        else:
            mode = messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

        auto_delete_value = disk.get('auto-delete', 'yes')
        auto_delete = auto_delete_value == 'yes'

        disk_size_gb = utils.BytesToGb(disk.get('size'))
        disk_type = disk.get('type')
        if disk_type:
            disk_type_ref = resources.Parse(disk_type,
                                            collection='compute.diskTypes',
                                            params={
                                                'project':
                                                instance_ref.project,
                                                'zone': instance_ref.zone
                                            })

            disk_type_uri = disk_type_ref.SelfLink()
        else:
            disk_type_uri = None

        img = disk.get('image')
        img_family = disk.get('image-family')
        img_project = disk.get('image-project')

        image_uri = None
        if img or img_family:
            image_expander = image_utils.ImageExpander(compute_client,
                                                       resources)
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=instance_ref.project,
                image=img,
                image_family=img_family,
                image_project=img_project,
                return_image_resource=False)

        image_key = None
        disk_key = None
        if csek_keys:
            image_key = csek_utils.MaybeLookupKeyMessagesByUri(
                csek_keys, resources, [image_uri], compute)
            if name:
                disk_ref = resources.Parse(name,
                                           collection='compute.disks',
                                           params={'zone': instance_ref.zone})
                disk_key = csek_utils.MaybeLookupKeyMessage(
                    csek_keys, disk_ref, compute)

        if enable_kms:
            disk_key = kms_utils.MaybeGetKmsKeyFromDict(
                disk, messages, disk_key)

        initialize_params = messages.AttachedDiskInitializeParams(
            diskName=name,
            description=disk.get('description'),
            sourceImage=image_uri,
            diskSizeGb=disk_size_gb,
            diskType=disk_type_uri,
            sourceImageEncryptionKey=image_key)

        if enable_snapshots:
            snapshot_name = disk.get('source-snapshot')
            attached_snapshot_uri = ResolveSnapshotURI(
                snapshot=snapshot_name,
                user_project=instance_ref.project,
                resource_parser=resources)
            if attached_snapshot_uri:
                initialize_params.sourceImage = None
                initialize_params.sourceSnapshot = attached_snapshot_uri

        device_name = GetDiskDeviceName(disk, name, container_mount_disk)
        create_disk = messages.AttachedDisk(
            autoDelete=auto_delete,
            boot=False,
            deviceName=device_name,
            initializeParams=initialize_params,
            mode=mode,
            type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            diskEncryptionKey=disk_key)

        disks_messages.append(create_disk)

    return disks_messages
예제 #7
0
  def CreateRequests(self, args):
    """Creates and returns an InstanceTemplates.Insert request.

    Args:
      args: the argparse arguments that this command was invoked with.

    Returns:
      request: a ComputeInstanceTemplatesInsertRequest message object
    """
    self.ValidateDiskFlags(args)
    instances_flags.ValidateLocalSsdFlags(args)
    instances_flags.ValidateNicFlags(args)
    instances_flags.ValidateServiceAccountAndScopeArgs(args)

    boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
    utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

    instance_template_ref = (
        instance_templates_flags.INSTANCE_TEMPLATE_ARG.ResolveAsResource(
            args, self.resources))

    metadata = metadata_utils.ConstructMetadataMessage(
        self.messages,
        metadata=args.metadata,
        metadata_from_file=args.metadata_from_file)

    if hasattr(args, 'network_interface') and args.network_interface:
      network_interfaces = (
          instance_template_utils.CreateNetworkInterfaceMessages)(
              resources=self.resources,
              scope_lister=flags.GetDefaultScopeLister(self.compute_client),
              messages=self.messages,
              network_interface_arg=args.network_interface,
              region=args.region)
    else:
      network_interfaces = [
          instance_template_utils.CreateNetworkInterfaceMessage(
              resources=self.resources,
              scope_lister=flags.GetDefaultScopeLister(self.compute_client),
              messages=self.messages,
              network=args.network,
              region=args.region,
              subnet=args.subnet,
              address=(instance_template_utils.EPHEMERAL_ADDRESS
                       if not args.no_address and not args.address
                       else args.address))
      ]

    scheduling = instance_utils.CreateSchedulingMessage(
        messages=self.messages,
        maintenance_policy=args.maintenance_policy,
        preemptible=args.preemptible,
        restart_on_failure=args.restart_on_failure)

    if args.no_service_account:
      service_account = None
    else:
      service_account = args.service_account
    service_accounts = instance_utils.CreateServiceAccountMessages(
        messages=self.messages,
        scopes=[] if args.no_scopes else args.scopes,
        service_account=service_account)

    create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or [])
    if create_boot_disk:
      image_expander = image_utils.ImageExpander(self.compute_client,
                                                 self.resources)
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=instance_template_ref.project,
          image=args.image,
          image_family=args.image_family,
          image_project=args.image_project,
          return_image_resource=True)
    else:
      image_uri = None

    if args.tags:
      tags = self.messages.Tags(items=args.tags)
    else:
      tags = None

    persistent_disks = (
        instance_template_utils.CreatePersistentAttachedDiskMessages(
            self.messages, args.disk or []))

    persistent_create_disks = (
        instance_template_utils.CreatePersistentCreateDiskMessages(
            self, self.messages, getattr(args, 'create_disk', [])))

    if create_boot_disk:
      boot_disk_list = [
          instance_template_utils.CreateDefaultBootAttachedDiskMessage(
              messages=self.messages,
              disk_type=args.boot_disk_type,
              disk_device_name=args.boot_disk_device_name,
              disk_auto_delete=args.boot_disk_auto_delete,
              disk_size_gb=boot_disk_size_gb,
              image_uri=image_uri)]
    else:
      boot_disk_list = []

    local_ssds = []
    for x in args.local_ssd or []:
      local_ssd = instance_utils.CreateLocalSsdMessage(
          self.resources,
          self.messages,
          x.get('device-name'),
          x.get('interface'))
      local_ssds.append(local_ssd)

    disks = (
        boot_disk_list + persistent_disks + persistent_create_disks + local_ssds
    )

    machine_type = instance_utils.InterpretMachineType(
        machine_type=args.machine_type,
        custom_cpu=args.custom_cpu,
        custom_memory=args.custom_memory,
        ext=getattr(args, 'custom_extensions', None))

    request = self.messages.ComputeInstanceTemplatesInsertRequest(
        instanceTemplate=self.messages.InstanceTemplate(
            properties=self.messages.InstanceProperties(
                machineType=machine_type,
                disks=disks,
                canIpForward=args.can_ip_forward,
                metadata=metadata,
                networkInterfaces=network_interfaces,
                serviceAccounts=service_accounts,
                scheduling=scheduling,
                tags=tags,
            ),
            description=args.description,
            name=instance_template_ref.Name(),
        ),
        project=instance_template_ref.project)

    return [request]
예제 #8
0
def CreatePersistentCreateDiskMessages(client, resources, user_project,
                                       create_disks, support_kms=False):
  """Returns a list of AttachedDisk messages.

  Args:
    client: Compute client adapter
    resources: Compute resources registry
    user_project: name of user project
    create_disks: disk objects - contains following properties
             * name - the name of disk,
             * mode - 'rw' (R/W), 'ro' (R/O) access mode,
             * size - the size of the disk,
             * type - the type of the disk (HDD or SSD),
             * image - the name of the image to initialize from,
             * image-family - the image family name,
             * image-project - the project name that has the image,
             * auto-delete - whether disks is deleted when VM is deleted ('yes'
               if True),
             * device-name - device name on VM.
    support_kms: if KMS is supported

  Returns:
    list of API messages for attached disks
  """

  disks_messages = []
  for disk in create_disks or []:
    name = disk.get('name')
    # Resolves the mode.
    mode_value = disk.get('mode', 'rw')
    if mode_value == 'rw':
      mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
    else:
      mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

    auto_delete = disk.get('auto-delete') == 'yes'
    disk_size_gb = utils.BytesToGb(disk.get('size'))
    img = disk.get('image')
    img_family = disk.get('image-family')
    img_project = disk.get('image-project')

    image_uri = None
    if img or img_family:
      image_expander = image_utils.ImageExpander(client, resources)
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=user_project,
          image=img,
          image_family=img_family,
          image_project=img_project,
          return_image_resource=False)

    disk_key = None
    if support_kms:
      disk_key = kms_utils.MaybeGetKmsKeyFromDict(
          disk, client.messages, disk_key)

    create_disk = client.messages.AttachedDisk(
        autoDelete=auto_delete,
        boot=False,
        deviceName=disk.get('device-name'),
        initializeParams=client.messages.AttachedDiskInitializeParams(
            diskName=name,
            sourceImage=image_uri,
            diskSizeGb=disk_size_gb,
            diskType=disk.get('type')),
        mode=mode,
        type=client.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
        diskEncryptionKey=disk_key)

    disks_messages.append(create_disk)

  return disks_messages
예제 #9
0
  def _CreateRequests(self, args):
    instances_flags.ValidateDiskFlags(args)
    instances_flags.ValidateLocalSsdFlags(args)
    instances_flags.ValidateNicFlags(args)
    instances_flags.ValidateServiceAccountAndScopeArgs(args)
    instances_flags.ValidateAcceleratorArgs(args)

    # This feature is only exposed in alpha/beta
    allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                                  base.ReleaseTrack.BETA]
    self.csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)

    scheduling = instance_utils.CreateSchedulingMessage(
        messages=self.messages,
        maintenance_policy=args.maintenance_policy,
        preemptible=args.preemptible,
        restart_on_failure=args.restart_on_failure)

    if args.tags:
      tags = self.messages.Tags(items=args.tags)
    else:
      tags = None

    metadata = metadata_utils.ConstructMetadataMessage(
        self.messages,
        metadata=args.metadata,
        metadata_from_file=args.metadata_from_file)

    # If the user already provided an initial Windows password and
    # username through metadata, then there is no need to check
    # whether the image or the boot disk is Windows.

    boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
    utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

    instance_refs = instances_flags.INSTANCES_ARG.ResolveAsResource(
        args, self.resources, scope_lister=flags.GetDefaultScopeLister(
            self.compute_client, self.project))

    # Check if the zone is deprecated or has maintenance coming.
    zone_resource_fetcher = zone_utils.ZoneResourceFetcher(self.compute_client)
    zone_resource_fetcher.WarnForZonalCreation(instance_refs)

    network_interface_arg = getattr(args, 'network_interface', None)
    if network_interface_arg:
      network_interfaces = instance_utils.CreateNetworkInterfaceMessages(
          resources=self.resources,
          compute_client=self.compute_client,
          network_interface_arg=network_interface_arg,
          instance_refs=instance_refs,
          support_network_tier=self._support_network_tier)
    else:
      if self._support_public_dns is True:
        instances_flags.ValidatePublicDnsFlags(args)

      network_tier = getattr(args, 'network_tier', None)

      network_interfaces = [
          instance_utils.CreateNetworkInterfaceMessage(
              resources=self.resources,
              compute_client=self.compute_client,
              network=args.network,
              subnet=args.subnet,
              private_network_ip=args.private_network_ip,
              no_address=args.no_address,
              address=args.address,
              instance_refs=instance_refs,
              network_tier=network_tier,
              no_public_dns=getattr(args, 'no_public_dns', None),
              public_dns=getattr(args, 'public_dns', None),
              no_public_ptr=getattr(args, 'no_public_ptr', None),
              public_ptr=getattr(args, 'public_ptr', None),
              no_public_ptr_domain=getattr(args, 'no_public_ptr_domain', None),
              public_ptr_domain=getattr(args, 'public_ptr_domain', None))
      ]

    machine_type_uris = instance_utils.CreateMachineTypeUris(
        resources=self.resources,
        compute_client=self.compute_client,
        project=self.project,
        machine_type=args.machine_type,
        custom_cpu=args.custom_cpu,
        custom_memory=args.custom_memory,
        ext=getattr(args, 'custom_extensions', None),
        instance_refs=instance_refs)

    create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or [])
    if create_boot_disk:
      image_expander = image_utils.ImageExpander(self.compute_client,
                                                 self.resources)
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=self.project,
          image=args.image,
          image_family=args.image_family,
          image_project=args.image_project,
          return_image_resource=False)
    else:
      image_uri = None

    # A list of lists where the element at index i contains a list of
    # disk messages that should be set for the instance at index i.
    disks_messages = []

    # A mapping of zone to boot disk references for all existing boot
    # disks that are being attached.
    # TODO(user): Simplify this once resources.Resource becomes
    # hashable.
    existing_boot_disks = {}

    for instance_ref in instance_refs:
      persistent_disks, boot_disk_ref = (
          instance_utils.CreatePersistentAttachedDiskMessages(
              self.resources, self.compute_client, self.csek_keys,
              args.disk or [], instance_ref))
      persistent_create_disks = (
          instance_utils.CreatePersistentCreateDiskMessages(
              self,
              self.compute_client,
              self.resources,
              self.csek_keys,
              getattr(args, 'create_disk', []),
              instance_ref))
      local_ssds = []
      for x in args.local_ssd or []:
        local_ssds.append(
            instance_utils.CreateLocalSsdMessage(
                self.resources,
                self.messages,
                x.get('device-name'),
                x.get('interface'),
                instance_ref.zone)
        )

      if create_boot_disk:
        boot_disk = instance_utils.CreateDefaultBootAttachedDiskMessage(
            self.compute_client, self.resources,
            disk_type=args.boot_disk_type,
            disk_device_name=args.boot_disk_device_name,
            disk_auto_delete=args.boot_disk_auto_delete,
            disk_size_gb=boot_disk_size_gb,
            require_csek_key_create=(
                args.require_csek_key_create if self.csek_keys else None),
            image_uri=image_uri,
            instance_ref=instance_ref,
            csek_keys=self.csek_keys)
        persistent_disks = [boot_disk] + persistent_disks
      else:
        existing_boot_disks[boot_disk_ref.zone] = boot_disk_ref
      disks_messages.append(persistent_disks + persistent_create_disks +
                            local_ssds)

    accelerator_args = getattr(args, 'accelerator', None)

    project_to_sa = {}
    requests = []
    for instance_ref, machine_type_uri, disks in zip(
        instance_refs, machine_type_uris, disks_messages):
      if instance_ref.project not in project_to_sa:
        scopes = None
        if not args.no_scopes and not args.scopes:
          # User didn't provide any input on scopes. If project has no default
          # service account then we want to create a VM with no scopes
          request = (self.compute.projects,
                     'Get',
                     self.messages.ComputeProjectsGetRequest(
                         project=instance_ref.project))
          errors = []
          result = self.compute_client.MakeRequests([request], errors)
          if not errors:
            if not result[0].defaultServiceAccount:
              scopes = []
              log.status.Print(
                  'There is no default service account for project {}. '
                  'Instance {} will not have scopes.'.format(
                      instance_ref.project, instance_ref.Name))
        if scopes is None:
          scopes = [] if args.no_scopes else args.scopes

        if args.no_service_account:
          service_account = None
        else:
          service_account = args.service_account
        service_accounts = instance_utils.CreateServiceAccountMessages(
            messages=self.messages,
            scopes=scopes,
            service_account=service_account)
        project_to_sa[instance_ref.project] = service_accounts

      instance = self.messages.Instance(
          canIpForward=args.can_ip_forward,
          disks=disks,
          description=args.description,
          machineType=machine_type_uri,
          metadata=metadata,
          name=instance_ref.Name(),
          networkInterfaces=network_interfaces,
          serviceAccounts=project_to_sa[instance_ref.project],
          scheduling=scheduling,
          tags=tags)
      if getattr(args, 'min_cpu_platform', None):
        instance.minCpuPlatform = args.min_cpu_platform
      if accelerator_args:
        accelerator_type_name = accelerator_args['type']
        accelerator_type_ref = self.resources.Parse(
            accelerator_type_name,
            collection='compute.acceleratorTypes',
            params={'project': instance_ref.project,
                    'zone': instance_ref.zone})
        # Accelerator count is default to 1.
        accelerator_count = int(accelerator_args.get('count', 1))
        accelerators = instance_utils.CreateAcceleratorConfigMessages(
            self.compute_client.messages, accelerator_type_ref,
            accelerator_count)
        instance.guestAccelerators = accelerators

      request = self.messages.ComputeInstancesInsertRequest(
          instance=instance,
          project=instance_ref.project,
          zone=instance_ref.zone)

      sole_tenancy_host_arg = getattr(args, 'sole_tenancy_host', None)
      if sole_tenancy_host_arg:
        sole_tenancy_host_ref = self.resources.Parse(
            sole_tenancy_host_arg, collection='compute.hosts',
            params={'zone': instance_ref.zone})
        request.instance.host = sole_tenancy_host_ref.SelfLink()
      requests.append((self.compute.instances, 'Insert', request))
    return requests
def CreatePersistentCreateDiskMessages(compute_client, resources, csek_keys,
                                       create_disks, instance_ref):
    """Returns a list of AttachedDisk messages for newly creating disks.

  Args:
    compute_client: creates resources,
    resources: parser of resources,
    csek_keys: customer suplied encryption keys,
    create_disks: disk objects - contains following properties
             * name - the name of disk,
             * mode - 'rw' (R/W), 'ro' (R/O) access mode,
             * disk-size - the size of the disk,
             * disk-type - the type of the disk (HDD or SSD),
             * image - the name of the image to initialize from,
             * image-family - the image family name,
             * image-project - the project name that has the image,
             * auto-delete - whether disks is deleted when VM is deleted,
             * device-name - device name on VM.
    instance_ref: reference to the instance that will own the new disks.
  Returns:
    list of API messages for attached disks
  """
    disks_messages = []

    messages = compute_client.messages
    compute = compute_client.apitools_client
    for disk in create_disks or []:
        name = disk.get('name')

        # Resolves the mode.
        mode_value = disk.get('mode', 'rw')
        if mode_value == 'rw':
            mode = messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
        else:
            mode = messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

        auto_delete_value = disk.get('auto-delete', 'yes')
        auto_delete = auto_delete_value == 'yes'

        disk_size_gb = utils.BytesToGb(disk.get('size'))
        disk_type = disk.get('type')
        if disk_type:
            disk_type_ref = resources.Parse(disk_type,
                                            collection='compute.diskTypes',
                                            params={
                                                'project':
                                                instance_ref.project,
                                                'zone': instance_ref.zone
                                            })

            disk_type_uri = disk_type_ref.SelfLink()
        else:
            disk_type_ref = None
            disk_type_uri = None

        image_expander = image_utils.ImageExpander(compute_client, resources)
        image_uri, _ = image_expander.ExpandImageFlag(
            user_project=instance_ref.project,
            image=disk.get('image'),
            image_family=disk.get('image-family'),
            image_project=disk.get('image-project'),
            return_image_resource=False)

        image_key = None
        disk_key = None
        if csek_keys:
            image_key = csek_utils.MaybeLookupKeyMessagesByUri(
                csek_keys, resources, [image_uri], compute)
            if name:
                disk_ref = resources.Parse(name,
                                           collection='compute.disks',
                                           params={'zone': instance_ref.zone})
                disk_key = csek_utils.MaybeLookupKeyMessage(
                    csek_keys, disk_ref, compute)

        create_disk = messages.AttachedDisk(
            autoDelete=auto_delete,
            boot=False,
            deviceName=disk.get('device-name'),
            initializeParams=messages.AttachedDiskInitializeParams(
                diskName=name,
                sourceImage=image_uri,
                diskSizeGb=disk_size_gb,
                diskType=disk_type_uri,
                sourceImageEncryptionKey=image_key),
            mode=mode,
            type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            diskEncryptionKey=disk_key)

        disks_messages.append(create_disk)

    return disks_messages
예제 #11
0
    def Run(self, args):
        compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = compute_holder.client

        self.Validate(args)

        size_gb = utils.BytesToGb(args.size)

        from_image = args.image or args.image_family
        if not size_gb and not args.source_snapshot and not from_image:
            if args.type and 'pd-ssd' in args.type:
                size_gb = constants.DEFAULT_SSD_DISK_SIZE_GB
            else:
                size_gb = constants.DEFAULT_STANDARD_DISK_SIZE_GB

        utils.WarnIfDiskSizeIsTooSmall(size_gb, args.type)

        requests = []
        disk_refs = Create.disks_arg.ResolveAsResource(
            args,
            compute_holder.resources,
            scope_lister=flags.GetDefaultScopeLister(client))

        # Check if the zone is deprecated or has maintenance coming.
        zone_resource_fetcher = zone_utils.ZoneResourceFetcher(client)
        zone_resource_fetcher.WarnForZonalCreation(
            (ref for ref in disk_refs if ref.Collection() == 'compute.disks'))
        # Check if the region is deprecated or has maintenance coming.
        region_resource_fetcher = region_utils.RegionResourceFetcher(client)
        region_resource_fetcher.WarnForRegionalCreation(
            (ref for ref in disk_refs
             if ref.Collection() == 'compute.regionDisks'))

        project_to_source_image = {}

        image_expander = image_utils.ImageExpander(client,
                                                   compute_holder.resources)

        for disk_ref in disk_refs:
            if from_image:
                if disk_ref.project not in project_to_source_image:
                    source_image_uri, _ = image_expander.ExpandImageFlag(
                        user_project=disk_ref.project,
                        image=args.image,
                        image_family=args.image_family,
                        image_project=args.image_project,
                        return_image_resource=False)
                    project_to_source_image[
                        disk_ref.project] = argparse.Namespace()
                    project_to_source_image[
                        disk_ref.project].uri = source_image_uri
            else:
                project_to_source_image[
                    disk_ref.project] = argparse.Namespace()
                project_to_source_image[disk_ref.project].uri = None

        snapshot_ref = disks_flags.SOURCE_SNAPSHOT_ARG.ResolveAsResource(
            args, compute_holder.resources)
        if snapshot_ref:
            snapshot_uri = snapshot_ref.SelfLink()
        else:
            snapshot_uri = None

        # This feature is only exposed in alpha/beta
        allow_rsa_encrypted = self.ReleaseTrack() in [
            base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA
        ]
        csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)

        for project in project_to_source_image:
            source_image_uri = project_to_source_image[project].uri
            project_to_source_image[project].keys = (
                csek_utils.MaybeLookupKeyMessagesByUri(
                    csek_keys, compute_holder.resources,
                    [source_image_uri, snapshot_uri], client.apitools_client))

        for disk_ref in disk_refs:
            if args.type:
                if disk_ref.Collection() == 'compute.disks':
                    type_ref = compute_holder.resources.Parse(
                        args.type,
                        collection='compute.diskTypes',
                        params={'zone': disk_ref.zone})
                elif disk_ref.Collection() == 'compute.regionDisks':
                    type_ref = compute_holder.resources.Parse(
                        args.type,
                        collection='compute.regionDiskTypes',
                        params={'region': disk_ref.region})
                type_uri = type_ref.SelfLink()
            else:
                type_uri = None

            if csek_keys:
                disk_key_or_none = csek_keys.LookupKey(
                    disk_ref, args.require_csek_key_create)
                disk_key_message_or_none = csek_utils.MaybeToMessage(
                    disk_key_or_none, client.apitools_client)
                kwargs = {
                    'diskEncryptionKey':
                    disk_key_message_or_none,
                    'sourceImageEncryptionKey':
                    project_to_source_image[disk_ref.project].keys[0],
                    'sourceSnapshotEncryptionKey':
                    project_to_source_image[disk_ref.project].keys[1]
                }
            else:
                kwargs = {}

            if disk_ref.Collection() == 'compute.disks':
                request = client.messages.ComputeDisksInsertRequest(
                    disk=client.messages.Disk(name=disk_ref.Name(),
                                              description=args.description,
                                              sizeGb=size_gb,
                                              sourceSnapshot=snapshot_uri,
                                              type=type_uri,
                                              **kwargs),
                    project=disk_ref.project,
                    sourceImage=project_to_source_image[disk_ref.project].uri,
                    zone=disk_ref.zone)
                request = (client.apitools_client.disks, 'Insert', request)
            elif disk_ref.Collection() == 'compute.regionDisks':

                def SelfLink(zone, disk_ref):
                    return compute_holder.resources.Parse(
                        zone,
                        collection='compute.zones',
                        params={
                            'project': disk_ref.project
                        }).SelfLink()

                zones = [
                    SelfLink(zone, disk_ref) for zone in args.replica_zones
                ]
                request = client.messages.ComputeRegionDisksInsertRequest(
                    disk=client.messages.Disk(name=disk_ref.Name(),
                                              description=args.description,
                                              sizeGb=size_gb,
                                              sourceSnapshot=snapshot_uri,
                                              type=type_uri,
                                              replicaZones=zones,
                                              **kwargs),
                    project=disk_ref.project,
                    sourceImage=project_to_source_image[disk_ref.project].uri,
                    region=disk_ref.region)
                request = (client.apitools_client.regionDisks, 'Insert',
                           request)
            requests.append(request)

        return client.MakeRequests(requests)
예제 #12
0
def _RunCreate(compute_api,
               args,
               support_network_tier=False,
               support_labels=False):
    """Common routine for creating instance template.

  This is shared between various release tracks.

  Args:
      compute_api: The compute api.
      args: argparse.Namespace, An object that contains the values for the
          arguments specified in the .Args() method.
      support_network_tier: Indicates whether network tier is supported or not.
      support_labels: Indicates whether user labels are supported or not.

  Returns:
      A resource object dispatched by display.Displayer().
  """
    _ValidateInstancesFlags(args)
    if support_network_tier:
        instances_flags.ValidateNetworkTierArgs(args)

    client = compute_api.client

    boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
    utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

    instance_template_ref = (Create.InstanceTemplateArg.ResolveAsResource(
        args, compute_api.resources))

    metadata = metadata_utils.ConstructMetadataMessage(
        client.messages,
        metadata=args.metadata,
        metadata_from_file=args.metadata_from_file)

    if hasattr(args, 'network_interface') and args.network_interface:
        network_interfaces = (
            instance_template_utils.CreateNetworkInterfaceMessages)(
                resources=compute_api.resources,
                scope_lister=flags.GetDefaultScopeLister(client),
                messages=client.messages,
                network_interface_arg=args.network_interface,
                region=args.region,
                support_network_tier=support_network_tier)
    else:
        network_tier = getattr(args, 'network_tier', None)
        network_interfaces = [
            instance_template_utils.CreateNetworkInterfaceMessage(
                resources=compute_api.resources,
                scope_lister=flags.GetDefaultScopeLister(client),
                messages=client.messages,
                network=args.network,
                region=args.region,
                subnet=args.subnet,
                address=(instance_template_utils.EPHEMERAL_ADDRESS
                         if not args.no_address and not args.address else
                         args.address),
                network_tier=network_tier)
        ]

    scheduling = instance_utils.CreateSchedulingMessage(
        messages=client.messages,
        maintenance_policy=args.maintenance_policy,
        preemptible=args.preemptible,
        restart_on_failure=args.restart_on_failure)

    if args.no_service_account:
        service_account = None
    else:
        service_account = args.service_account
    service_accounts = instance_utils.CreateServiceAccountMessages(
        messages=client.messages,
        scopes=[] if args.no_scopes else args.scopes,
        service_account=service_account)

    create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or [])
    if create_boot_disk:
        image_expander = image_utils.ImageExpander(client,
                                                   compute_api.resources)
        try:
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=instance_template_ref.project,
                image=args.image,
                image_family=args.image_family,
                image_project=args.image_project,
                return_image_resource=True)
        except utils.ImageNotFoundError as e:
            if args.IsSpecified('image_project'):
                raise e
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=instance_template_ref.project,
                image=args.image,
                image_family=args.image_family,
                image_project=args.image_project,
                return_image_resource=False)
            raise utils.ImageNotFoundError(
                'The resource [{}] was not found. Is the image located in another '
                'project? Use the --image-project flag to specify the '
                'project where the image is located.'.format(image_uri))
    else:
        image_uri = None

    if args.tags:
        tags = client.messages.Tags(items=args.tags)
    else:
        tags = None

    persistent_disks = (
        instance_template_utils.CreatePersistentAttachedDiskMessages(
            client.messages, args.disk or []))

    persistent_create_disks = (
        instance_template_utils.CreatePersistentCreateDiskMessages(
            client, compute_api.resources, instance_template_ref.project,
            getattr(args, 'create_disk', [])))

    if create_boot_disk:
        boot_disk_list = [
            instance_template_utils.CreateDefaultBootAttachedDiskMessage(
                messages=client.messages,
                disk_type=args.boot_disk_type,
                disk_device_name=args.boot_disk_device_name,
                disk_auto_delete=args.boot_disk_auto_delete,
                disk_size_gb=boot_disk_size_gb,
                image_uri=image_uri)
        ]
    else:
        boot_disk_list = []

    local_ssds = []
    for x in args.local_ssd or []:
        local_ssd = instance_utils.CreateLocalSsdMessage(
            compute_api.resources, client.messages, x.get('device-name'),
            x.get('interface'), x.get('size'))
        local_ssds.append(local_ssd)

    disks = (boot_disk_list + persistent_disks + persistent_create_disks +
             local_ssds)

    machine_type = instance_utils.InterpretMachineType(
        machine_type=args.machine_type,
        custom_cpu=args.custom_cpu,
        custom_memory=args.custom_memory,
        ext=getattr(args, 'custom_extensions', None))

    guest_accelerators = (
        instance_template_utils.CreateAcceleratorConfigMessages(
            client.messages, getattr(args, 'accelerator', None)))

    request = client.messages.ComputeInstanceTemplatesInsertRequest(
        instanceTemplate=client.messages.InstanceTemplate(
            properties=client.messages.InstanceProperties(
                machineType=machine_type,
                disks=disks,
                canIpForward=args.can_ip_forward,
                metadata=metadata,
                minCpuPlatform=args.min_cpu_platform,
                networkInterfaces=network_interfaces,
                serviceAccounts=service_accounts,
                scheduling=scheduling,
                tags=tags,
                guestAccelerators=guest_accelerators,
            ),
            description=args.description,
            name=instance_template_ref.Name(),
        ),
        project=instance_template_ref.project)

    if support_labels and args.labels:
        labels = client.messages.InstanceProperties.LabelsValue(
            additionalProperties=[
                client.messages.InstanceProperties.LabelsValue.
                AdditionalProperty(key=key, value=value)
                for key, value in sorted(args.labels.iteritems())
            ])
        request.instanceTemplate.properties.labels = labels

    return client.MakeRequests([(client.apitools_client.instanceTemplates,
                                 'Insert', request)])
def CreatePersistentCreateDiskMessages(client,
                                       resources,
                                       user_project,
                                       create_disks,
                                       support_kms=False,
                                       container_mount_disk=None,
                                       support_multi_writer=False):
    """Returns a list of AttachedDisk messages.

  Args:
    client: Compute client adapter
    resources: Compute resources registry
    user_project: name of user project
    create_disks: disk objects - contains following properties
             * name - the name of disk,
             * description - an optional description for the disk,
             * mode - 'rw' (R/W), 'ro' (R/O) access mode,
             * size - the size of the disk,
             * provisioned-iops - Indicates how many IOPS must be provisioned
               for the disk.
             * type - the type of the disk (HDD or SSD),
             * image - the name of the image to initialize from,
             * image-family - the image family name,
             * image-project - the project name that has the image,
             * auto-delete - whether disks is deleted when VM is deleted ('yes'
               if True),
             * device-name - device name on VM,
             * disk-resource-policy - resource policies applied to disk.

    support_kms: if KMS is supported
    container_mount_disk: list of disks to be mounted to container, if any.
    support_multi_writer: if multi writer disks are supported.

  Returns:
    list of API messages for attached disks
  """

    disks_messages = []
    for disk in create_disks or []:
        name = disk.get('name')
        # Resolves the mode.
        mode_value = disk.get('mode', 'rw')
        if mode_value == 'rw':
            mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
        else:
            mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

        auto_delete = disk.get('auto-delete', False)
        boot = disk.get('boot', False)
        disk_size_gb = utils.BytesToGb(disk.get('size'))
        img = disk.get('image')
        img_family = disk.get('image-family')
        img_project = disk.get('image-project')

        image_uri = None
        if img or img_family:
            image_expander = image_utils.ImageExpander(client, resources)
            image_uri, _ = image_expander.ExpandImageFlag(
                user_project=user_project,
                image=img,
                image_family=img_family,
                image_project=img_project,
                return_image_resource=False)

        disk_key = None
        if support_kms:
            disk_key = kms_utils.MaybeGetKmsKeyFromDict(
                disk, client.messages, disk_key)

        device_name = instance_utils.GetDiskDeviceName(disk, name,
                                                       container_mount_disk)

        init_params = client.messages.AttachedDiskInitializeParams(
            diskName=name,
            description=disk.get('description'),
            sourceImage=image_uri,
            diskSizeGb=disk_size_gb,
            diskType=disk.get('type'),
            provisionedIops=disk.get('provisioned-iops'))

        policies = disk.get('disk-resource-policy')
        if policies:
            init_params.resourcePolicies = policies

        multi_writer = disk.get('multi-writer')
        if support_multi_writer and multi_writer:
            init_params.multiWriter = True

        create_disk = client.messages.AttachedDisk(
            autoDelete=auto_delete,
            boot=boot,
            deviceName=device_name,
            initializeParams=init_params,
            mode=mode,
            type=client.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            diskEncryptionKey=disk_key)

        disks_messages.append(create_disk)

    return disks_messages
예제 #14
0
    def Run(self, args):
        """Returns a list of requests necessary for adding images."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client
        messages = client.messages
        resource_parser = holder.resources

        image_ref = Create.DISK_IMAGE_ARG.ResolveAsResource(
            args, holder.resources)
        image = messages.Image(
            name=image_ref.image,
            description=args.description,
            sourceType=messages.Image.SourceTypeValueValuesEnum.RAW,
            family=args.family)

        csek_keys = csek_utils.CsekKeyStore.FromArgs(
            args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS)
        if csek_keys:
            image.imageEncryptionKey = csek_utils.MaybeToMessage(
                csek_keys.LookupKey(
                    image_ref, raise_if_missing=args.require_csek_key_create),
                client.apitools_client)
        image.imageEncryptionKey = kms_utils.MaybeGetKmsKey(
            args, image_ref.project, client.apitools_client,
            image.imageEncryptionKey)

        # Validate parameters.
        if args.source_disk_zone and not args.source_disk:
            raise exceptions.ToolException(
                'You cannot specify [--source-disk-zone] unless you are specifying '
                '[--source-disk].')

        source_image_project = getattr(args, 'source_image_project', None)
        source_image = getattr(args, 'source_image', None)
        source_image_family = getattr(args, 'source_image_family', None)

        if source_image_project and not (source_image or source_image_family):
            raise exceptions.ToolException(
                'You cannot specify [--source-image-project] unless you are '
                'specifying [--source-image] or [--source-image-family].')

        if source_image or source_image_family:
            image_expander = image_utils.ImageExpander(client, resource_parser)
            _, source_image_ref = image_expander.ExpandImageFlag(
                user_project=image_ref.project,
                image=source_image,
                image_family=source_image_family,
                image_project=source_image_project,
                return_image_resource=True)
            image.sourceImage = source_image_ref.selfLink
            image.sourceImageEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_image_ref, client.apitools_client)

        # TODO(b/30086260): use resources.REGISTRY.Parse() for GCS URIs.
        if args.source_uri:
            source_uri = utils.NormalizeGoogleStorageUri(args.source_uri)
            image.rawDisk = messages.Image.RawDiskValue(source=source_uri)
        elif args.source_disk:
            source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceDisk = source_disk_ref.SelfLink()
            image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_disk_ref, client.apitools_client)

        if args.licenses:
            image.licenses = args.licenses

        guest_os_features = getattr(args, 'guest_os_features', [])
        if guest_os_features:
            guest_os_feature_messages = []
            for feature in guest_os_features:
                gf_type = messages.GuestOsFeature.TypeValueValuesEnum(feature)
                guest_os_feature = messages.GuestOsFeature()
                guest_os_feature.type = gf_type
                guest_os_feature_messages.append(guest_os_feature)
            image.guestOsFeatures = guest_os_feature_messages

        request = messages.ComputeImagesInsertRequest(
            image=image, project=image_ref.project)

        args_labels = getattr(args, 'labels', None)
        if args_labels:
            labels = messages.Image.LabelsValue(additionalProperties=[
                messages.Image.LabelsValue.AdditionalProperty(key=key,
                                                              value=value)
                for key, value in sorted(args_labels.iteritems())
            ])
            request.image.labels = labels

        # --force is in GA, --force-create is in beta and deprecated.
        if args.force or getattr(args, 'force_create', None):
            request.forceCreate = True

        return client.MakeRequests([(client.apitools_client.images, 'Insert',
                                     request)])
def _RunCreate(compute_api,
               args,
               support_source_instance,
               support_kms=False,
               support_post_key_revocation_action_type=False,
               support_multi_writer=False,
               support_mesh=False,
               support_host_error_timeout_seconds=False,
               support_numa_node_count=False,
               support_visible_core_count=False,
               support_disk_architecture=False,
               support_key_revocation_action_type=False,
               support_max_run_duration=False):
  """Common routine for creating instance template.

  This is shared between various release tracks.

  Args:
      compute_api: The compute api.
      args: argparse.Namespace, An object that contains the values for the
        arguments specified in the .Args() method.
      support_source_instance: indicates whether source instance is supported.
      support_kms: Indicate whether KMS is integrated or not.
      support_post_key_revocation_action_type: Indicate whether
        post_key_revocation_action_type is supported.
      support_multi_writer: Indicates whether a disk can have multiple writers.
      support_mesh: Indicates whether adding VM to a Anthos Service Mesh is
        supported.
      support_host_error_timeout_seconds: Indicate the timeout in seconds for
        host error detection.
      support_numa_node_count: Indicates whether setting NUMA node count is
        supported.
      support_visible_core_count: Indicates whether setting a custom visible
      support_disk_architecture: Storage resources can be used to create boot
        disks compatible with ARM64 or X86_64 machine architectures. If this
        field is not specified, the default is ARCHITECTURE_UNSPECIFIED.
      support_key_revocation_action_type: Indicate whether
        key_revocation_action_type is supported.
      support_max_run_duration: Indicate whether max-run-duration or
        termination-time issupported.

  Returns:
      A resource object dispatched by display.Displayer().
  """
  _ValidateInstancesFlags(
      args,
      support_kms=support_kms,
      support_max_run_duration=support_max_run_duration)
  instances_flags.ValidateNetworkTierArgs(args)

  instance_templates_flags.ValidateServiceProxyFlags(args)
  if support_mesh:
    instance_templates_flags.ValidateMeshFlag(args)

  client = compute_api.client

  boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
  utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)

  instance_template_ref = (
      Create.InstanceTemplateArg.ResolveAsResource(args, compute_api.resources))

  AddScopesForServiceProxy(args)
  AddServiceProxyArgsToMetadata(args)

  if hasattr(args, 'network_interface') and args.network_interface:
    network_interfaces = (
        instance_template_utils.CreateNetworkInterfaceMessages)(
            resources=compute_api.resources,
            scope_lister=flags.GetDefaultScopeLister(client),
            messages=client.messages,
            network_interface_arg=args.network_interface,
            region=args.region)
  else:
    network_tier = getattr(args, 'network_tier', None)
    stack_type = getattr(args, 'stack_type', None)
    ipv6_network_tier = getattr(args, 'ipv6_network_tier', None)
    network_interfaces = [
        instance_template_utils.CreateNetworkInterfaceMessage(
            resources=compute_api.resources,
            scope_lister=flags.GetDefaultScopeLister(client),
            messages=client.messages,
            network=args.network,
            private_ip=args.private_network_ip,
            region=args.region,
            subnet=args.subnet,
            address=(instance_template_utils.EPHEMERAL_ADDRESS
                     if not args.no_address and not args.address else
                     args.address),
            network_tier=network_tier,
            stack_type=stack_type,
            ipv6_network_tier=ipv6_network_tier)
    ]

  if support_mesh:
    ConfigureMeshTemplate(args, instance_template_ref, network_interfaces)

  metadata = metadata_utils.ConstructMetadataMessage(
      client.messages,
      metadata=args.metadata,
      metadata_from_file=args.metadata_from_file)

  # Compute the shieldedInstanceConfig message.
  shieldedinstance_config_message = BuildShieldedInstanceConfigMessage(
      messages=client.messages, args=args)

  confidential_instance_config_message = (
      BuildConfidentialInstanceConfigMessage(
          messages=client.messages, args=args))

  node_affinities = sole_tenancy_util.GetSchedulingNodeAffinityListFromArgs(
      args, client.messages)

  location_hint = None
  if args.IsSpecified('location_hint'):
    location_hint = args.location_hint

  provisioning_model = None
  if (hasattr(args, 'provisioning_model') and
      args.IsSpecified('provisioning_model')):
    provisioning_model = args.provisioning_model

  termination_action = None
  if (hasattr(args, 'instance_termination_action') and
      args.IsSpecified('instance_termination_action')):
    termination_action = args.instance_termination_action

  max_run_duration = None
  if (hasattr(args, 'max_run_duration') and
      args.IsSpecified('max_run_duration')):
    max_run_duration = args.max_run_duration

  termination_time = None
  if (hasattr(args, 'termination_time') and
      args.IsSpecified('termination_time')):
    termination_time = args.termination_time

  host_error_timeout_seconds = None
  if support_host_error_timeout_seconds and args.IsSpecified(
      'host_error_timeout_seconds'):
    host_error_timeout_seconds = args.host_error_timeout_seconds
  scheduling = instance_utils.CreateSchedulingMessage(
      messages=client.messages,
      maintenance_policy=args.maintenance_policy,
      preemptible=args.preemptible,
      restart_on_failure=args.restart_on_failure,
      node_affinities=node_affinities,
      min_node_cpu=args.min_node_cpu,
      location_hint=location_hint,
      provisioning_model=provisioning_model,
      instance_termination_action=termination_action,
      host_error_timeout_seconds=host_error_timeout_seconds,
      max_run_duration=max_run_duration,
      termination_time=termination_time)

  if args.no_service_account:
    service_account = None
  else:
    service_account = args.service_account
  service_accounts = instance_utils.CreateServiceAccountMessages(
      messages=client.messages,
      scopes=[] if args.no_scopes else args.scopes,
      service_account=service_account)

  create_boot_disk = not (
      instance_utils.UseExistingBootDisk((args.disk or []) +
                                         (args.create_disk or [])))
  if create_boot_disk:
    image_expander = image_utils.ImageExpander(client, compute_api.resources)
    try:
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=instance_template_ref.project,
          image=args.image,
          image_family=args.image_family,
          image_project=args.image_project,
          return_image_resource=True)
    except utils.ImageNotFoundError as e:
      if args.IsSpecified('image_project'):
        raise e
      image_uri, _ = image_expander.ExpandImageFlag(
          user_project=instance_template_ref.project,
          image=args.image,
          image_family=args.image_family,
          image_project=args.image_project,
          return_image_resource=False)
      raise utils.ImageNotFoundError(
          'The resource [{}] was not found. Is the image located in another '
          'project? Use the --image-project flag to specify the '
          'project where the image is located.'.format(image_uri))
  else:
    image_uri = None

  if args.tags:
    tags = client.messages.Tags(items=args.tags)
  else:
    tags = None

  persistent_disks = (
      instance_template_utils.CreatePersistentAttachedDiskMessages(
          client.messages, args.disk or []))

  persistent_create_disks = (
      instance_template_utils.CreatePersistentCreateDiskMessages(
          client,
          compute_api.resources,
          instance_template_ref.project,
          getattr(args, 'create_disk', []),
          support_kms=support_kms,
          support_multi_writer=support_multi_writer,
          support_disk_architecture=support_disk_architecture))

  if create_boot_disk:
    boot_disk_list = [
        instance_template_utils.CreateDefaultBootAttachedDiskMessage(
            messages=client.messages,
            disk_type=args.boot_disk_type,
            disk_device_name=args.boot_disk_device_name,
            disk_auto_delete=args.boot_disk_auto_delete,
            disk_size_gb=boot_disk_size_gb,
            image_uri=image_uri,
            kms_args=args,
            support_kms=support_kms,
            disk_provisioned_iops=args.boot_disk_provisioned_iops)
    ]
  else:
    boot_disk_list = []

  local_nvdimms = create_utils.CreateLocalNvdimmMessages(
      args,
      compute_api.resources,
      client.messages,
  )

  local_ssds = create_utils.CreateLocalSsdMessages(
      args,
      compute_api.resources,
      client.messages,
  )

  disks = (
      boot_disk_list + persistent_disks + persistent_create_disks +
      local_nvdimms + local_ssds)

  machine_type = instance_utils.InterpretMachineType(
      machine_type=args.machine_type,
      custom_cpu=args.custom_cpu,
      custom_memory=args.custom_memory,
      ext=getattr(args, 'custom_extensions', None),
      vm_type=getattr(args, 'custom_vm_type', None))

  guest_accelerators = (
      instance_template_utils.CreateAcceleratorConfigMessages(
          client.messages, getattr(args, 'accelerator', None)))

  instance_template = client.messages.InstanceTemplate(
      properties=client.messages.InstanceProperties(
          machineType=machine_type,
          disks=disks,
          canIpForward=args.can_ip_forward,
          metadata=metadata,
          minCpuPlatform=args.min_cpu_platform,
          networkInterfaces=network_interfaces,
          serviceAccounts=service_accounts,
          scheduling=scheduling,
          tags=tags,
          guestAccelerators=guest_accelerators,
      ),
      description=args.description,
      name=instance_template_ref.Name(),
  )

  instance_template.properties.shieldedInstanceConfig = shieldedinstance_config_message

  instance_template.properties.reservationAffinity = instance_utils.GetReservationAffinity(
      args, client)

  instance_template.properties.confidentialInstanceConfig = (
      confidential_instance_config_message)

  if args.IsSpecified('network_performance_configs'):
    instance_template.properties.networkPerformanceConfig = (
        instance_utils.GetNetworkPerformanceConfig(args, client))

  if args.IsSpecified('resource_policies'):
    instance_template.properties.resourcePolicies = getattr(
        args, 'resource_policies', [])

  if support_post_key_revocation_action_type and args.IsSpecified(
      'post_key_revocation_action_type'):
    instance_template.properties.postKeyRevocationActionType = arg_utils.ChoiceToEnum(
        args.post_key_revocation_action_type, client.messages.InstanceProperties
        .PostKeyRevocationActionTypeValueValuesEnum)

  if support_key_revocation_action_type and args.IsSpecified(
      'key_revocation_action_type'):
    instance_template.properties.keyRevocationActionType = arg_utils.ChoiceToEnum(
        args.key_revocation_action_type, client.messages.InstanceProperties
        .KeyRevocationActionTypeValueValuesEnum)

  if args.private_ipv6_google_access_type is not None:
    instance_template.properties.privateIpv6GoogleAccess = (
        instances_flags.GetPrivateIpv6GoogleAccessTypeFlagMapperForTemplate(
            client.messages).GetEnumForChoice(
                args.private_ipv6_google_access_type))

  # Create an AdvancedMachineFeatures message if any of the features requiring
  # one have been specified.
  has_visible_core_count = (
      support_visible_core_count and args.visible_core_count is not None)
  if (args.enable_nested_virtualization is not None or
      args.threads_per_core is not None or
      (support_numa_node_count and args.numa_node_count is not None) or
      has_visible_core_count or args.enable_uefi_networking is not None):

    visible_core_count = args.visible_core_count if has_visible_core_count else None
    instance_template.properties.advancedMachineFeatures = (
        instance_utils.CreateAdvancedMachineFeaturesMessage(
            client.messages, args.enable_nested_virtualization,
            args.threads_per_core,
            args.numa_node_count if support_numa_node_count else None,
            visible_core_count, args.enable_uefi_networking))

  if args.resource_manager_tags:
    ret_resource_manager_tags = resource_manager_tags_utils.GetResourceManagerTags(
        args.resource_manager_tags)
    if ret_resource_manager_tags is not None:
      properties = client.messages.InstanceProperties
      instance_template.properties.resourceManagerTags = properties.ResourceManagerTagsValue(
          additionalProperties=[
              properties.ResourceManagerTagsValue.AdditionalProperty(
                  key=key, value=value) for key, value in sorted(
                      six.iteritems(ret_resource_manager_tags))
          ])

  request = client.messages.ComputeInstanceTemplatesInsertRequest(
      instanceTemplate=instance_template, project=instance_template_ref.project)

  request.instanceTemplate.properties.labels = ParseCreateArgsWithServiceProxy(
      args, client.messages.InstanceProperties.LabelsValue)

  _AddSourceInstanceToTemplate(compute_api, args, instance_template,
                               support_source_instance)

  return client.MakeRequests([(client.apitools_client.instanceTemplates,
                               'Insert', request)])