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 CreateDefaultBootAttachedDiskMessage(compute_client, resources, disk_type, disk_device_name, disk_auto_delete, disk_size_gb, require_csek_key_create, image_uri, instance_ref, csek_keys=None, kms_args=None): """Returns an AttachedDisk message for creating a new boot disk.""" messages = compute_client.messages compute = compute_client.apitools_client 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 if csek_keys: # If we're going to encrypt the boot disk make sure that we select # a name predictably, instead of letting the API deal with name # conflicts automatically. # # Note that when csek keys are being used we *always* want force this # even if we don't have any encryption key for default disk name. # # Consider the case where the user's key file has a key for disk `foo-1` # and no other disk. Assume she runs # gcloud compute instances create foo --csek-key-file f \ # --no-require-csek-key-create # and gcloud doesn't force the disk name to be `foo`. The API might # select name `foo-1` for the new disk, but has no way of knowing # that the user has a key file mapping for that disk name. That # behavior violates the principle of least surprise. # # Instead it's better for gcloud to force a specific disk name in the # instance create, and fail if that name isn't available. effective_boot_disk_name = (disk_device_name or instance_ref.Name()) disk_ref = resources.Parse(effective_boot_disk_name, collection='compute.disks', params={ 'project': instance_ref.project, 'zone': instance_ref.zone }) disk_key_or_none = csek_utils.MaybeToMessage( csek_keys.LookupKey(disk_ref, require_csek_key_create), compute) [image_key_or_none ] = csek_utils.MaybeLookupKeyMessagesByUri(csek_keys, resources, [image_uri], compute) kwargs_init_parms = {'sourceImageEncryptionKey': image_key_or_none} kwargs_disk = {'diskEncryptionKey': disk_key_or_none} else: kwargs_disk = {} kwargs_init_parms = {} effective_boot_disk_name = disk_device_name kms_key = kms_utils.MaybeGetKmsKey( kms_args, instance_ref.project, compute, kwargs_disk.get('diskEncryptionKey', None)) if kms_key: kwargs_disk = {'diskEncryptionKey': kms_key} return messages.AttachedDisk( autoDelete=disk_auto_delete, boot=True, deviceName=effective_boot_disk_name, initializeParams=messages.AttachedDiskInitializeParams( sourceImage=image_uri, diskSizeGb=disk_size_gb, diskType=disk_type_uri, **kwargs_init_parms), mode=messages.AttachedDisk.ModeValueValuesEnum.READ_WRITE, type=messages.AttachedDisk.TypeValueValuesEnum.PERSISTENT, **kwargs_disk)
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
def CreateRequests(self, args): """Returns a list of requests necessary for adding disks.""" size_gb = utils.BytesToGb(args.size) # TODO(user): remove getattr on image family GA from_image = args.image or getattr(args, 'image_family', None) 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 = self.CreateZonalReferences(args.names, args.zone) # Check if the zone is deprecated or has maintenance coming. self.WarnForZonalCreation(disk_refs) if from_image: source_image_uri, _ = self.ExpandImageFlag( args, return_image_resource=False) else: source_image_uri = None if args.source_snapshot: snapshot_ref = self.CreateGlobalReference( args.source_snapshot, resource_type='snapshots') snapshot_uri = snapshot_ref.SelfLink() else: snapshot_uri = None if hasattr(args, 'csek_key_file'): csek_keys = csek_utils.CsekKeyStore.FromArgs(args) else: csek_keys = None image_key_message_or_none, snapshot_key_message_or_none = ( csek_utils.MaybeLookupKeyMessagesByUri( csek_keys, self.resources, [source_image_uri, snapshot_uri], self.compute)) for disk_ref in disk_refs: if args.type: type_ref = self.CreateZonalReference(args.type, disk_ref.zone, resource_type='diskTypes') 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, self.compute) kwargs = { 'diskEncryptionKey': disk_key_message_or_none, 'sourceImageEncryptionKey': image_key_message_or_none, 'sourceSnapshotEncryptionKey': snapshot_key_message_or_none } else: kwargs = {} request = self.messages.ComputeDisksInsertRequest( disk=self.messages.Disk(name=disk_ref.Name(), description=args.description, sizeGb=size_gb, sourceSnapshot=snapshot_uri, type=type_uri, **kwargs), project=self.project, sourceImage=source_image_uri, zone=disk_ref.zone) requests.append(request) return requests
def _Run(self, args, supports_kms_keys=False, supports_physical_block=False, support_shared_disk=False, support_vss_erase=False): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = compute_holder.client self.show_unformated_message = not (args.IsSpecified('image') or args.IsSpecified('image_family') or args.IsSpecified('source_snapshot')) if self.source_disk_enabled: self.show_unformated_message = self.show_unformated_message and not ( args.IsSpecified('source_disk')) disk_refs = self.ValidateAndParseDiskRefs(args, compute_holder) from_image = self.GetFromImage(args) size_gb = self.GetDiskSizeGb(args, from_image) self.WarnAboutScopeDeprecationsAndMaintenance(disk_refs, client) project_to_source_image = self.GetProjectToSourceImageDict( args, disk_refs, compute_holder, from_image) snapshot_uri = self.GetSnapshotUri(args, compute_holder) # Those features are only exposed in alpha/beta, it would be nice to have # code supporting them only in alpha and beta versions of the command. labels = self.GetLabels(args, client) 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)) # end of alpha/beta features. guest_os_feature_messages = _ParseGuestOsFeaturesToMessages( args, client.messages) requests = [] for disk_ref in disk_refs: type_uri = self.GetDiskTypeUri(args, disk_ref, compute_holder) # Those features are only exposed in alpha/beta, it would be nice to have # code supporting them only in alpha and beta versions of the command. # TODO(b/65161039): Stop checking release path in the middle of GA code. kwargs = {} 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 kwargs['sourceImageEncryptionKey'] = ( project_to_source_image[disk_ref.project].keys[0]) kwargs['sourceSnapshotEncryptionKey'] = ( project_to_source_image[disk_ref.project].keys[1]) if labels: kwargs['labels'] = labels if supports_kms_keys: kwargs['diskEncryptionKey'] = kms_utils.MaybeGetKmsKey( args, client.messages, kwargs.get('diskEncryptionKey', None)) # end of alpha/beta features. if supports_physical_block and args.IsSpecified('physical_block_size'): physical_block_size_bytes = int(args.physical_block_size) else: physical_block_size_bytes = None resource_policies = getattr(args, 'resource_policies', None) if resource_policies: if disk_ref.Collection() == 'compute.regionDisks': disk_region = disk_ref.region else: disk_region = utils.ZoneNameToRegionName(disk_ref.zone) parsed_resource_policies = [] for policy in resource_policies: resource_policy_ref = resource_util.ParseResourcePolicy( compute_holder.resources, policy, project=disk_ref.project, region=disk_region) parsed_resource_policies.append(resource_policy_ref.SelfLink()) kwargs['resourcePolicies'] = parsed_resource_policies disk = client.messages.Disk( name=disk_ref.Name(), description=args.description, sizeGb=size_gb, sourceSnapshot=snapshot_uri, type=type_uri, physicalBlockSizeBytes=physical_block_size_bytes, **kwargs) if self.source_disk_enabled: source_disk_ref = self.GetSourceDiskUri(args, compute_holder) disk.sourceDisk = source_disk_ref if (support_shared_disk and disk_ref.Collection() == 'compute.regionDisks' and args.IsSpecified('multi_writer')): raise exceptions.InvalidArgumentException('--multi-writer', ( '--multi-writer can be used only with --zone flag')) if (support_shared_disk and disk_ref.Collection() == 'compute.disks' and args.IsSpecified('multi_writer')): disk.multiWriter = args.multi_writer if guest_os_feature_messages: disk.guestOsFeatures = guest_os_feature_messages if support_vss_erase and args.IsSpecified('erase_windows_vss_signature'): disk.eraseWindowsVssSignature = args.erase_windows_vss_signature disk.licenses = self.ParseLicenses(args) if disk_ref.Collection() == 'compute.disks': request = client.messages.ComputeDisksInsertRequest( disk=disk, 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': disk.replicaZones = self.GetReplicaZones(args, compute_holder, disk_ref) request = client.messages.ComputeRegionDisksInsertRequest( disk=disk, 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)
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = compute_holder.client self.show_unformated_message = not (args.IsSpecified('image') or args.IsSpecified('image_family') or args.IsSpecified('source_snapshot')) disk_refs = self.ValidateAndParseDiskRefs(args, compute_holder) from_image = self.GetFromImage(args) size_gb = self.GetDiskSizeGb(args, from_image) self.WarnAboutScopeDeprecationsAndMaintainance(disk_refs, client) project_to_source_image = self.GetProjectToSourceImageDict( args, disk_refs, compute_holder, from_image) snapshot_uri = self.GetSnapshotUri(args, compute_holder) # Those features are only exposed in alpha/beta, it would be nice to have # code supporting them only in alpha and beta versions of the command. labels = self.GetLabels(args, client) 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)) # end of alpha/beta features. guest_os_feature_messages = self.ParseGuestOsFeaturesToMessages( args, client.messages) requests = [] for disk_ref in disk_refs: type_uri = self.GetDiskTypeUri(args, disk_ref, compute_holder) # Those features are only exposed in alpha/beta, it would be nice to have # code supporting them only in alpha and beta versions of the command. # TODO(b/65161039): Stop checking release path in the middle of GA code. kwargs = {} 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 kwargs['sourceImageEncryptionKey'] = ( project_to_source_image[disk_ref.project].keys[0]) kwargs['sourceSnapshotEncryptionKey'] = ( project_to_source_image[disk_ref.project].keys[1]) if labels: kwargs['labels'] = labels kwargs['diskEncryptionKey'] = kms_utils.MaybeGetKmsKey( args, disk_ref.project, client.apitools_client, kwargs.get('diskEncryptionKey', None)) # end of alpha/beta features. disk = client.messages.Disk( name=disk_ref.Name(), description=args.description, sizeGb=size_gb, sourceSnapshot=snapshot_uri, type=type_uri, **kwargs) if guest_os_feature_messages: disk.guestOsFeatures = guest_os_feature_messages disk.licenses = self.ParseLicenses(args) if disk_ref.Collection() == 'compute.disks': request = client.messages.ComputeDisksInsertRequest( disk=disk, 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': disk.replicaZones = self.GetReplicaZones(args, compute_holder, disk_ref) request = client.messages.ComputeRegionDisksInsertRequest( disk=disk, 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)
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = compute_holder.client disk_refs = self.ValidateAndParse(args, compute_holder) 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 = [] # 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)) labels = None args_labels = getattr(args, 'labels', None) if args_labels: labels = client.messages.Disk.LabelsValue(additionalProperties=[ client.messages.Disk.LabelsValue.AdditionalProperty( key=key, value=value) for key, value in sorted(args.labels.iteritems()) ]) 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={ 'project': disk_ref.project, 'zone': disk_ref.zone }) elif disk_ref.Collection() == 'compute.regionDisks': type_ref = compute_holder.resources.Parse( args.type, collection='compute.regionDiskTypes', params={ 'project': disk_ref.project, '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) if labels: request.disk.labels = labels 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) if labels: request.disk.labels = labels request = (client.apitools_client.regionDisks, 'Insert', request) requests.append(request) return client.MakeRequests(requests)
def CreateRequests(self, args): """Returns a list of requests necessary for adding disks.""" 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 = disks_flags.DISKS_ARG.ResolveAsResource( args, self.resources, scope_lister=flags.GetDefaultScopeLister(self.compute_client, self.project)) # Check if the zone is deprecated or has maintenance coming. self.WarnForZonalCreation(disk_refs) if from_image: source_image_uri, _ = self.ExpandImageFlag( args, return_image_resource=False) else: source_image_uri = None snapshot_ref = disks_flags.SOURCE_SNAPSHOT_ARG.ResolveAsResource( args, self.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) image_key_message_or_none, snapshot_key_message_or_none = ( csek_utils.MaybeLookupKeyMessagesByUri( csek_keys, self.resources, [source_image_uri, snapshot_uri], self.compute)) for disk_ref in disk_refs: if args.type: type_ref = self.resources.Parse(args.type, collection='compute.diskTypes', params={'zone': disk_ref.zone}) 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, self.compute) kwargs = { 'diskEncryptionKey': disk_key_message_or_none, 'sourceImageEncryptionKey': image_key_message_or_none, 'sourceSnapshotEncryptionKey': snapshot_key_message_or_none } else: kwargs = {} request = self.messages.ComputeDisksInsertRequest( disk=self.messages.Disk(name=disk_ref.Name(), description=args.description, sizeGb=size_gb, sourceSnapshot=snapshot_uri, type=type_uri, **kwargs), project=self.project, sourceImage=source_image_uri, zone=disk_ref.zone) requests.append(request) return requests
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