def CreatePersistentAttachedDiskMessages(resources,
                                         compute_client,
                                         csek_keys,
                                         disks,
                                         project,
                                         location,
                                         scope,
                                         container_mount_disk=None):
  """Returns a list of AttachedDisk messages and the boot disk's reference."""
  disks_messages = []

  messages = compute_client.messages
  compute = compute_client.apitools_client
  for disk in disks:
    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

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

    if 'scope' in disk and disk['scope'] == 'regional':
      scope = compute_scopes.ScopeEnum.REGION
    else:
      scope = compute_scopes.ScopeEnum.ZONE
    disk_ref = instance_utils.ParseDiskResource(resources, name, project,
                                                location, scope)

    # TODO(b/36051031) drop test after CSEK goes GA
    if csek_keys:
      disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
          csek_keys, disk_ref, compute)
      kwargs = {'diskEncryptionKey': disk_key_or_none}
    else:
      kwargs = {}

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

    attached_disk = messages.AttachedDisk(
        autoDelete=auto_delete,
        boot=boot,
        deviceName=device_name,
        mode=mode,
        source=disk_ref.SelfLink(),
        type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
        **kwargs)

    # The boot disk must end up at index 0.
    if boot:
      disks_messages = [attached_disk] + disks_messages
    else:
      disks_messages.append(attached_disk)

  return disks_messages
Exemple #2
0
  def CreateRequests(self, args):
    """Returns a request for attaching a disk to an instance."""
    instance_ref = self.CreateZonalReference(args.name, args.zone)
    disk_ref = self.CreateZonalReference(
        args.disk, instance_ref.zone, resource_type='disks')

    if args.mode == 'rw':
      mode = self.messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
    else:
      mode = self.messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

    # TODO(user) drop test after CSEK goes GA
    if hasattr(args, 'csek_key_file'):
      csek_keys = csek_utils.CsekKeyStore.FromArgs(args)
      disk_key_or_none = csek_utils.MaybeLookupKeyMessage(csek_keys, disk_ref,
                                                          self.compute)
      kwargs = {'diskEncryptionKey': disk_key_or_none}
    else:
      kwargs = {}

    request = self.messages.ComputeInstancesAttachDiskRequest(
        instance=instance_ref.Name(),
        project=self.project,
        attachedDisk=self.messages.AttachedDisk(
            deviceName=args.device_name,
            mode=mode,
            source=disk_ref.SelfLink(),
            type=self.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            **kwargs),
        zone=instance_ref.zone)

    return [request]
Exemple #3
0
  def CreateRequests(self, args):
    """Returns a request for attaching a disk to an instance."""
    instance_ref = instance_flags.INSTANCE_ARG.ResolveAsResource(
        args, self.resources, scope_lister=flags.GetDefaultScopeLister(
            self.compute_client, self.project))

    disk_ref = self.resources.Parse(
        args.disk, collection='compute.disks',
        params={'zone': instance_ref.zone})

    if args.mode == 'rw':
      mode = self.messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
    else:
      mode = self.messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

    allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                                  base.ReleaseTrack.BETA]
    csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)
    disk_key_or_none = csek_utils.MaybeLookupKeyMessage(csek_keys, disk_ref,
                                                        self.compute)

    request = self.messages.ComputeInstancesAttachDiskRequest(
        instance=instance_ref.Name(),
        project=self.project,
        attachedDisk=self.messages.AttachedDisk(
            deviceName=args.device_name,
            mode=mode,
            source=disk_ref.SelfLink(),
            type=self.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            diskEncryptionKey=disk_key_or_none),
        zone=instance_ref.zone)

    return [request]
Exemple #4
0
    def CreateRequests(self, args):
        """Returns a list of requests necessary for snapshotting disks."""
        disk_refs = disks_flags.DISKS_ARG.ResolveAsResource(
            args,
            self.resources,
            scope_lister=flags.GetDefaultScopeLister(self.compute_client,
                                                     self.project))
        if args.snapshot_names:
            if len(disk_refs) != len(args.snapshot_names):
                raise exceptions.ToolException(
                    '[--snapshot-names] must have the same number of values as disks '
                    'being snapshotted.')
            snapshot_names = args.snapshot_names
        else:
            # Generates names like "d52jsqy3db4q".
            snapshot_names = [
                name_generator.GenerateRandomName() for _ in disk_refs
            ]

        snapshot_refs = [
            self.resources.Parse(snapshot_name, collection='compute.snapshots')
            for snapshot_name in snapshot_names
        ]
        self._target_to_get_request = {}

        requests = []

        for disk_ref, snapshot_ref in zip(disk_refs, snapshot_refs):
            # 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)
            disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
                csek_keys, disk_ref, self.compute)

            # TODO(user) drop test after 'guestFlush' goes GA
            if hasattr(args, 'guest_flush') and args.guest_flush:
                request_kwargs = {'guestFlush': True}
            else:
                request_kwargs = {}

            request = self.messages.ComputeDisksCreateSnapshotRequest(
                disk=disk_ref.Name(),
                snapshot=self.messages.Snapshot(
                    name=snapshot_ref.Name(),
                    description=args.description,
                    sourceDiskEncryptionKey=disk_key_or_none),
                project=self.project,
                zone=disk_ref.zone,
                **request_kwargs)
            requests.append(request)

            self._target_to_get_request[disk_ref.SelfLink()] = (
                snapshot_ref.SelfLink(), self.compute.snapshots,
                self.messages.ComputeSnapshotsGetRequest(
                    snapshot=snapshot_ref.Name(), project=self.project))

        return requests
def GetSourceMachineImageKey(args, source_image, compute_client, holder):
  machine_image_ref = source_image.ResolveAsResource(args, holder.resources)
  csek_keys = csek_utils.CsekKeyStore.FromFile(
      args.source_machine_image_csek_key_file, allow_rsa_encrypted=False)
  disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
      csek_keys, machine_image_ref, compute_client.apitools_client)
  return disk_key_or_none
Exemple #6
0
    def CreateRequests(self, args):
        """Returns a list of requests necessary for adding images."""

        image = self.messages.Image(
            name=args.name,
            description=args.description,
            sourceType=self.messages.Image.SourceTypeValueValuesEnum.RAW,
            family=args.family)

        csek_keys = csek_utils.CsekKeyStore.FromArgs(
            args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS)
        if csek_keys:
            image_ref = self.resources.Parse(args.name,
                                             collection='compute.images')
            image.imageEncryptionKey = csek_utils.MaybeToMessage(
                csek_keys.LookupKey(
                    image_ref, raise_if_missing=args.require_csek_key_create),
                self.compute_client.apitools_client)

        # 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].')

        if args.source_disk and args.source_uri:
            raise exceptions.ConflictingArgumentsException(
                '--source-uri', '--source-disk')

        if not (args.source_disk or args.source_uri):
            raise exceptions.MinimumArgumentException([
                '--source-uri', '--source-disk'
            ], 'Please specify either the source disk or the Google Cloud Storage '
                                                      'URI of the disk image.')

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

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

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

        return [request]
Exemple #7
0
  def Run(self, args):
    holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
    client = holder.client

    csek_key_file = args.csek_key_file
    request_list = []
    instance_refs = flags.INSTANCES_ARG.ResolveAsResource(
        args, holder.resources,
        scope_lister=flags.GetInstanceZoneScopeLister(client))
    if csek_key_file:
      instances = self.GetInstances(client, instance_refs)
    else:
      instances = [None for _ in instance_refs]
    for instance_ref, instance in zip(instance_refs, instances):
      disks = []

      if csek_key_file:
        allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                                      base.ReleaseTrack.BETA]
        csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)
        for disk in instance.disks:
          disk_resource = resources.REGISTRY.Parse(disk.source)

          disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
              csek_keys, disk_resource, client.apitools_client)

          if disk_key_or_none:
            disks.append(client.messages.CustomerEncryptionKeyProtectedDisk(
                diskEncryptionKey=disk_key_or_none,
                source=disk.source))

      if disks:
        encryption_req = client.messages.InstancesStartWithEncryptionKeyRequest(
            disks=disks)

        request = (
            client.apitools_client.instances,
            'StartWithEncryptionKey',
            client.messages.ComputeInstancesStartWithEncryptionKeyRequest(
                instance=instance_ref.Name(),
                instancesStartWithEncryptionKeyRequest=encryption_req,
                project=instance_ref.project,
                zone=instance_ref.zone))
      else:
        request = (
            client.apitools_client.instances,
            'Start',
            client.messages.ComputeInstancesStartRequest(
                instance=instance_ref.Name(),
                project=instance_ref.project,
                zone=instance_ref.zone))

      request_list.append(request)
    return client.MakeRequests(request_list)
def CreatePersistentAttachedDiskMessages(
    resources, compute_client, csek_keys, disks, instance_ref):
  """Returns a list of AttachedDisk messages and the boot disk's reference."""
  disks_messages = []
  boot_disk_ref = None

  messages = compute_client.messages
  compute = compute_client.apitools_client
  for disk in disks:
    name = disk['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

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

    disk_ref = resources.Parse(
        name,
        collection='compute.disks',
        params={'zone': instance_ref.zone})

    if boot:
      boot_disk_ref = disk_ref

    # TODO(user) drop test after CSEK goes GA
    if csek_keys:
      disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
          csek_keys, disk_ref, compute)
      kwargs = {'diskEncryptionKey': disk_key_or_none}
    else:
      kwargs = {}

    attached_disk = messages.AttachedDisk(
        autoDelete=auto_delete,
        boot=boot,
        deviceName=disk.get('device-name'),
        mode=mode,
        source=disk_ref.SelfLink(),
        type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
        **kwargs)

    # The boot disk must end up at index 0.
    if boot:
      disks_messages = [attached_disk] + disks_messages
    else:
      disks_messages.append(attached_disk)

  return disks_messages, boot_disk_ref
Exemple #9
0
  def CreateRequests(self, args):
    """Returns a list of requests necessary for snapshotting disks."""
    if args.snapshot_names:
      if len(args.disk_names) != len(args.snapshot_names):
        raise exceptions.ToolException(
            '[--snapshot-names] must have the same number of values as disks '
            'being snapshotted.')
      snapshot_names = args.snapshot_names
    else:
      # Generates names like "d52jsqy3db4q".
      snapshot_names = [name_generator.GenerateRandomName()
                        for _ in args.disk_names]

    snapshot_refs = [
        self.CreateGlobalReference(snapshot_name, resource_type='snapshots')
        for snapshot_name in snapshot_names]

    self._target_to_get_request = {}

    requests = []
    disk_refs = self.CreateZonalReferences(
        args.disk_names, args.zone, resource_type='disks')

    for disk_ref, snapshot_ref in zip(disk_refs, snapshot_refs):
      # TODO(user) drop test after CSEK goes GA
      if hasattr(args, 'csek_key_file'):
        csek_keys = csek_utils.CsekKeyStore.FromArgs(args)
        disk_key_or_none = csek_utils.MaybeLookupKeyMessage(csek_keys, disk_ref,
                                                            self.compute)
        kwargs = {'sourceDiskEncryptionKey': disk_key_or_none}
      else:
        kwargs = {}
      request = self.messages.ComputeDisksCreateSnapshotRequest(
          disk=disk_ref.Name(),
          snapshot=self.messages.Snapshot(
              name=snapshot_ref.Name(),
              description=args.description,
              **kwargs
          ),
          project=self.project,
          zone=disk_ref.zone)
      requests.append(request)

      self._target_to_get_request[disk_ref.SelfLink()] = (
          snapshot_ref.SelfLink(),
          self.compute.snapshots,
          self.messages.ComputeSnapshotsGetRequest(
              snapshot=snapshot_ref.Name(),
              project=self.project))

    return requests
Exemple #10
0
    def _Run(self,
             args,
             support_disk_scope=False,
             support_force_attach=False,
             support_boot=False):
        """Invokes a request for attaching a disk to an instance."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client

        instance_ref = flags.INSTANCE_ARG.ResolveAsResource(
            args,
            holder.resources,
            scope_lister=flags.GetInstanceZoneScopeLister(client))

        disk_ref = self.ParseDiskRef(holder.resources, args, instance_ref,
                                     support_disk_scope)

        if args.mode == 'rw':
            mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE
        else:
            mode = client.messages.AttachedDisk.ModeValueValuesEnum.READ_ONLY

        allow_rsa_encrypted = self.ReleaseTrack() in [
            base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA
        ]
        csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)
        disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
            csek_keys, disk_ref, client.apitools_client)

        attached_disk = client.messages.AttachedDisk(
            deviceName=args.device_name,
            mode=mode,
            source=disk_ref.SelfLink(),
            type=client.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
            diskEncryptionKey=disk_key_or_none)

        if support_boot and args.boot:
            attached_disk.boot = args.boot

        request = client.messages.ComputeInstancesAttachDiskRequest(
            instance=instance_ref.Name(),
            project=instance_ref.project,
            attachedDisk=attached_disk,
            zone=instance_ref.zone)

        if support_force_attach and args.force_attach:
            request.forceAttach = args.force_attach

        return client.MakeRequests([(client.apitools_client.instances,
                                     'AttachDisk', request)])
    def CreatePersistentAttachedDiskMessages(self, args, instance_ref):
        """Returns a list of AttachedDisk messages and the boot disk's reference."""
        disks = []
        boot_disk_ref = None

        for disk in args.disk or []:
            name = disk['name']

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

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

            disk_ref = self.CreateZonalReference(name,
                                                 instance_ref.zone,
                                                 resource_type='disks')
            if boot:
                boot_disk_ref = disk_ref

            if self.csek_keys:
                disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
                    self.csek_keys, disk_ref, self.compute)
                kwargs = {'diskEncryptionKey': disk_key_or_none}
            else:
                kwargs = {}

            attached_disk = self.messages.AttachedDisk(
                autoDelete=auto_delete,
                boot=boot,
                deviceName=disk.get('device-name'),
                mode=mode,
                source=disk_ref.SelfLink(),
                type=self.messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT,
                **kwargs)

            # The boot disk must end up at index 0.
            if boot:
                disks = [attached_disk] + disks
            else:
                disks.append(attached_disk)

        return disks, boot_disk_ref
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)

        disk_key = kms_utils.MaybeGetKmsKeyFromDict(disk, instance_ref.project,
                                                    compute, disk_key)

        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
def CreatePersistentCreateDiskMessages(compute_client,
                                       resources, csek_keys, create_disks,
                                       instance_ref, enable_kms=False,
                                       enable_snapshots=False,
                                       container_mount_disk=None,
                                       resource_policy=False,
                                       enable_source_snapshot_csek=False,
                                       enable_image_csek=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
    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.
    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

  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

    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

    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
Exemple #14
0
    def Run(self, args):
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client

        csek_key_file = args.csek_key_file
        request_list = []
        instance_refs = flags.INSTANCES_ARG.ResolveAsResource(
            args,
            holder.resources,
            scope_lister=flags.GetInstanceZoneScopeLister(client))

        # If csek_key_file is supplied, we must first get a reference to the
        # instances specified in the file to ensure that they exist.
        # Only then can we verify that the key specified in the file matches what
        # was used to create the instance.
        if csek_key_file:
            instances = self.GetInstances(client, instance_refs)
        else:
            instances = [None for _ in instance_refs]

        for instance_ref, instance in zip(instance_refs, instances):
            disks = []

            if instance:
                allow_rsa_encrypted = self.ReleaseTrack() in [
                    base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA
                ]
                csek_keys = csek_utils.CsekKeyStore.FromArgs(
                    args, allow_rsa_encrypted)
                for disk in instance.disks:
                    disk_resource = resources.REGISTRY.Parse(disk.source)

                    disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
                        csek_keys, disk_resource, client.apitools_client)

                    if disk_key_or_none:
                        disks.append(
                            client.messages.CustomerEncryptionKeyProtectedDisk(
                                diskEncryptionKey=disk_key_or_none,
                                source=disk.source))
            if disks:
                encryption_req = client.messages.InstancesResumeRequest(
                    disks=disks)

                request = (client.apitools_client.instances, 'Resume',
                           client.messages.ComputeInstancesResumeRequest(
                               instance=instance_ref.Name(),
                               instancesResumeRequest=encryption_req,
                               project=instance_ref.project,
                               zone=instance_ref.zone))

            else:
                request = (client.apitools_client.instances, 'Resume',
                           client.messages.ComputeInstancesResumeRequest(
                               instance=instance_ref.Name(),
                               project=instance_ref.project,
                               zone=instance_ref.zone))

            request_list.append(request)

        errors_to_collect = []
        responses = client.BatchRequests(request_list, errors_to_collect)
        if errors_to_collect:
            raise exceptions.MultiError(errors_to_collect)

        operation_refs = [
            holder.resources.Parse(r.selfLink) for r in responses
        ]

        if args.async_:
            for operation_ref in operation_refs:
                log.status.Print(
                    'Resume instance in progress for [{}].'.format(
                        operation_ref.SelfLink()))
            log.status.Print(
                'Use [gcloud compute operations describe URI] command to check the '
                'status of the operation(s).')
            return responses

        operation_poller = poller.BatchPoller(client,
                                              client.apitools_client.instances,
                                              instance_refs)

        result = waiter.WaitFor(operation_poller,
                                poller.OperationBatch(operation_refs),
                                'Resuming instance(s) {0}'.format(', '.join(
                                    i.Name() for i in instance_refs)),
                                max_wait_ms=None)

        for instance_ref in instance_refs:
            log.status.Print('Updated [{0}].'.format(instance_ref))

        return result
Exemple #15
0
    def Run(self, args):
        """Returns a list of requests necessary for snapshotting disks."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())

        disk_refs = SnapshotDisks.disks_arg.ResolveAsResource(
            args,
            holder.resources,
            scope_lister=flags.GetDefaultScopeLister(holder.client))
        if args.snapshot_names:
            if len(disk_refs) != len(args.snapshot_names):
                raise exceptions.ToolException(
                    '[--snapshot-names] must have the same number of values as disks '
                    'being snapshotted.')
            snapshot_names = args.snapshot_names
        else:
            # Generates names like "d52jsqy3db4q".
            snapshot_names = [
                name_generator.GenerateRandomName() for _ in disk_refs
            ]

        snapshot_refs = [
            holder.resources.Parse(
                snapshot_name,
                params={
                    'project': properties.VALUES.core.project.GetOrFail,
                },
                collection='compute.snapshots')
            for snapshot_name in snapshot_names
        ]

        client = holder.client.apitools_client
        messages = holder.client.messages

        requests = []

        for disk_ref, snapshot_ref in zip(disk_refs, snapshot_refs):
            # 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)
            disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
                csek_keys, disk_ref, client)

            snapshot_message = messages.Snapshot(
                name=snapshot_ref.Name(),
                description=args.description,
                sourceDiskEncryptionKey=disk_key_or_none)
            if (hasattr(args, 'storage_location')
                    and args.IsSpecified('storage_location')):
                snapshot_message.storageLocations = [args.storage_location]
            if (hasattr(args, 'labels') and args.IsSpecified('labels')):
                snapshot_message.labels = labels_util.ParseCreateArgs(
                    args, messages.Snapshot.LabelsValue)

            if disk_ref.Collection() == 'compute.disks':
                request = messages.ComputeDisksCreateSnapshotRequest(
                    disk=disk_ref.Name(),
                    snapshot=snapshot_message,
                    project=disk_ref.project,
                    zone=disk_ref.zone,
                    guestFlush=args.guest_flush)
                requests.append((client.disks, 'CreateSnapshot', request))
            elif disk_ref.Collection() == 'compute.regionDisks':
                request = messages.ComputeRegionDisksCreateSnapshotRequest(
                    disk=disk_ref.Name(),
                    snapshot=snapshot_message,
                    project=disk_ref.project,
                    region=disk_ref.region)
                if hasattr(request,
                           'guestFlush'):  # only available in alpha API
                    guest_flush = getattr(args, 'guest_flush', None)
                    if guest_flush is not None:
                        request.guestFlush = guest_flush
                requests.append(
                    (client.regionDisks, 'CreateSnapshot', request))

        errors_to_collect = []
        responses = holder.client.BatchRequests(requests, errors_to_collect)
        for r in responses:
            err = getattr(r, 'error', None)
            if err:
                errors_to_collect.append(poller.OperationErrors(err.errors))
        if errors_to_collect:
            raise core_exceptions.MultiError(errors_to_collect)

        operation_refs = [
            holder.resources.Parse(r.selfLink) for r in responses
        ]

        if args. async:
            for operation_ref in operation_refs:
                log.status.Print('Disk snapshot in progress for [{}].'.format(
                    operation_ref.SelfLink()))
            log.status.Print(
                'Use [gcloud compute operations describe URI] command '
                'to check the status of the operation(s).')
            return responses

        operation_poller = poller.BatchPoller(holder.client, client.snapshots,
                                              snapshot_refs)
        return waiter.WaitFor(operation_poller,
                              poller.OperationBatch(operation_refs),
                              'Creating snapshot(s) {0}'.format(', '.join(
                                  s.Name() for s in snapshot_refs)),
                              max_wait_ms=None)
Exemple #16
0
  def _Run(self,
           args,
           support_source_instant_snapshot=False,
           support_snapshot_type=False):
    holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
    client = holder.client.apitools_client
    messages = holder.client.messages
    snap_ref = holder.resources.Parse(
        args.name,
        params={
            'project': properties.VALUES.core.project.GetOrFail,
        },
        collection='compute.snapshots')

    snapshot_message = messages.Snapshot(
        name=snap_ref.Name(), description=args.description)
    # This feature is only exposed in alpha/beta
    allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                                  base.ReleaseTrack.BETA]
    if args.source_disk:
      disk_ref = snap_flags.SOURCE_DISK_ARG.ResolveAsResource(
          args, holder.resources,
          scope_lister=flags.GetDefaultScopeLister(holder.client))
      snapshot_message.sourceDisk = disk_ref.SelfLink()
      if args.source_disk_key_file:
        source_keys = csek_utils.CsekKeyStore.FromFile(
            args.source_disk_key_file, allow_rsa_encrypted)
        disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
            source_keys, disk_ref, client)
        snapshot_message.sourceDiskEncryptionKey = disk_key_or_none
    if args.csek_key_file:
      csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted)
      snap_key_or_none = csek_utils.MaybeLookupKeyMessage(csek_keys, snap_ref,
                                                          client)
      snapshot_message.snapshotEncryptionKey = snap_key_or_none
    if hasattr(args, 'labels') and args.IsSpecified('labels'):
      snapshot_message.labels = labels_util.ParseCreateArgs(
          args, messages.Snapshot.LabelsValue)
    if args.storage_location:
      snapshot_message.storageLocations = [args.storage_location]
    if args.guest_flush:
      snapshot_message.guestFlush = True
    if args.chain_name:
      snapshot_message.chainName = args.chain_name
    if support_source_instant_snapshot and args.source_instant_snapshot:
      iss_ref = snap_flags.SOURCE_INSTANT_SNAPSHOT_ARG.ResolveAsResource(
          args, holder.resources,
          scope_lister=flags.GetDefaultScopeLister(holder.client))
      snapshot_message.sourceInstantSnapshot = iss_ref.SelfLink()

    if support_snapshot_type and args.IsSpecified('snapshot_type'):
      snapshot_message.snapshotType = snapshot_message.SnapshotTypeValueValuesEnum(
          args.snapshot_type)

    request = messages.ComputeSnapshotsInsertRequest(
        snapshot=snapshot_message,
        project=snap_ref.project
    )
    result = client.snapshots.Insert(request)
    operation_ref = resources.REGISTRY.Parse(
        result.name,
        params={'project': snap_ref.project},
        collection='compute.globalOperations')
    if args.async_:
      log.UpdatedResource(
          operation_ref,
          kind='gce snapshot {0}'.format(snap_ref.Name()),
          is_async=True,
          details='Use [gcloud compute operations describe] command '
                  'to check the status of this operation.'
      )
      return result
    operation_poller = poller.Poller(client.snapshots, snap_ref)
    return waiter.WaitFor(
        operation_poller, operation_ref,
        'Creating gce snapshot {0}'.format(snap_ref.Name()))
Exemple #17
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)

        # 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

        alpha_or_beta = self.ReleaseTrack() in (base.ReleaseTrack.BETA,
                                                base.ReleaseTrack.ALPHA)
        if alpha_or_beta and args.force_create:
            request.forceCreate = True

        return client.MakeRequests([(client.apitools_client.images, 'Insert',
                                     request)])
Exemple #18
0
def CreatePersistentCreateDiskMessages(compute_client,
                                       resources,
                                       csek_keys,
                                       create_disks,
                                       project,
                                       location,
                                       scope,
                                       holder,
                                       enable_kms=False,
                                       enable_snapshots=False,
                                       container_mount_disk=None,
                                       enable_source_snapshot_csek=False,
                                       enable_image_csek=False,
                                       support_replica_zones=False,
                                       use_disk_type_uri=True,
                                       support_multi_writer=False,
                                       support_image_family_scope=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.
    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
    use_disk_type_uri: True to use disk type URI, False if naked type.
    support_multi_writer: True if we allow multiple instances to write to disk.
    support_image_family_scope: True if the zonal image views are supported.

  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 = disk.get('auto-delete', True)
    disk_size_gb = utils.BytesToGb(disk.get('size'))
    disk_type = disk.get('type')
    if disk_type:
      if use_disk_type_uri:
        disk_type_ref = instance_utils.ParseDiskType(resources, disk_type,
                                                     project, location, scope)
        disk_type = disk_type_ref.SelfLink()
    else:
      disk_type = None

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

    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_family_scope=image_family_scope,
          support_image_family_scope=support_image_family_scope)

    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,
        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

    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', False)

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

    provisioned_iops = disk.get('provisioned-iops')
    if provisioned_iops:
      initialize_params.provisionedIops = provisioned_iops

    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
Exemple #19
0
  def CreateRequests(self, args):
    """Returns a list of requests necessary for adding images."""

    image_ref = flags.DISK_IMAGE_ARG.ResolveAsResource(args, self.resources)
    image = self.messages.Image(
        name=image_ref.image,
        description=args.description,
        sourceType=self.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),
          self.compute_client.apitools_client)

    # 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].')

    if args.source_disk and args.source_uri:
      raise exceptions.ConflictingArgumentsException(
          '--source-uri', '--source-disk')

    if not (args.source_disk or args.source_uri):
      raise exceptions.MinimumArgumentException(
          ['--source-uri', '--source-disk'],
          'Please specify either the source disk or the Google Cloud Storage '
          'URI of the disk image.'
      )

    # TODO(b/30086260): use resources.REGISTRY.Parse() for GCS URIs.
    if args.source_uri:
      source_uri = utils.NormalizeGoogleStorageUri(args.source_uri)
      image.rawDisk = self.messages.Image.RawDiskValue(source=source_uri)
    else:
      source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource(
          args, self.resources,
          scope_lister=compute_flags.GetDefaultScopeLister(self.compute_client))
      image.sourceDisk = source_disk_ref.SelfLink()
      image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage(
          csek_keys, source_disk_ref, self.compute_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 = self.messages.GuestOsFeature.TypeValueValuesEnum(feature)
        guest_os_feature = self.messages.GuestOsFeature()
        guest_os_feature.type = gf_type
        guest_os_feature_messages.append(guest_os_feature)
      image.guestOsFeatures = guest_os_feature_messages

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

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

    return [request]
Exemple #20
0
    def _Run(self,
             args,
             supports_storage_location=False,
             supports_shielded_instance_initial_state=False):
        """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, 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 = str(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

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

        if (supports_storage_location
                and 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)])
Exemple #21
0
    def Run(self, args):
        """Returns a list of requests necessary for snapshotting disks."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())

        disk_refs = SnapshotDisks.disks_arg.ResolveAsResource(
            args,
            holder.resources,
            scope_lister=flags.GetDefaultScopeLister(holder.client))
        if args.snapshot_names:
            if len(disk_refs) != len(args.snapshot_names):
                raise exceptions.ToolException(
                    '[--snapshot-names] must have the same number of values as disks '
                    'being snapshotted.')
            snapshot_names = args.snapshot_names
        else:
            # Generates names like "d52jsqy3db4q".
            snapshot_names = [
                name_generator.GenerateRandomName() for _ in disk_refs
            ]

        snapshot_refs = [
            holder.resources.Parse(snapshot_name,
                                   collection='compute.snapshots')
            for snapshot_name in snapshot_names
        ]

        client = holder.client.apitools_client
        messages = holder.client.messages

        requests = []

        for disk_ref, snapshot_ref in zip(disk_refs, snapshot_refs):
            # 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)
            disk_key_or_none = csek_utils.MaybeLookupKeyMessage(
                csek_keys, disk_ref, client)

            # TODO(user) drop test after 'guestFlush' goes GA
            if hasattr(args, 'guest_flush') and args.guest_flush:
                request_kwargs = {'guestFlush': True}
            else:
                request_kwargs = {}

            if disk_ref.Collection() == 'compute.disks':
                request = messages.ComputeDisksCreateSnapshotRequest(
                    disk=disk_ref.Name(),
                    snapshot=messages.Snapshot(
                        name=snapshot_ref.Name(),
                        description=args.description,
                        sourceDiskEncryptionKey=disk_key_or_none),
                    project=disk_ref.project,
                    zone=disk_ref.zone,
                    **request_kwargs)
                requests.append((client.disks, 'CreateSnapshot', request))
            elif disk_ref.Collection() == 'compute.regionDisks':
                request = messages.ComputeRegionDisksCreateSnapshotRequest(
                    disk=disk_ref.Name(),
                    snapshot=messages.Snapshot(
                        name=snapshot_ref.Name(),
                        description=args.description,
                        sourceDiskEncryptionKey=disk_key_or_none),
                    project=disk_ref.project,
                    region=disk_ref.region,
                    **request_kwargs)
                requests.append(
                    (client.regionDisks, 'CreateSnapshot', request))

        errors_to_collect = []
        responses = holder.client.BatchRequests(requests, errors_to_collect)
        if errors_to_collect:
            raise core_exceptions.MultiError(errors_to_collect)

        operation_refs = [
            holder.resources.Parse(r.selfLink) for r in responses
        ]

        if args. async:
            for operation_ref in operation_refs:
                log.status.Print('Disk snapshot in progress for [{}].'.format(
                    operation_ref.SelfLink()))
            log.status.Print(
                'Use [gcloud compute operations describe URI] command '
                'to check the status of the operation(s).')
            return responses

        operation_poller = poller.BatchPoller(holder.client, client.snapshots,
                                              snapshot_refs)
        return waiter.WaitFor(
            operation_poller, poller.OperationBatch(operation_refs),
            'Creating snapshot(s) {0}'.format(', '.join(
                s.Name() for s in snapshot_refs)))