def Run(self, args): instances_flags.ValidateDiskFlags( args, enable_kms=self.ReleaseTrack() in [base.ReleaseTrack.ALPHA]) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) if self._support_network_tier: instances_flags.ValidateNetworkTierArgs(args) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources instance_refs = instances_flags.INSTANCES_ARG.ResolveAsResource( args, resource_parser, scope_lister=flags.GetDefaultScopeLister(compute_client)) requests = self._CreateRequests(args, instance_refs, compute_client, resource_parser) if not args.async: # TODO(b/63664449): Replace this with poller + progress tracker. try: # Using legacy MakeRequests (which also does polling) here until # replaced by api_lib.utils.waiter. return compute_client.MakeRequests(requests) except exceptions.ToolException as e: invalid_machine_type_message_regex = ( r'Invalid value for field \'resource.machineType\': .+. ' r'Machine type with name \'.+\' does not exist in zone \'.+\'\.') if re.search(invalid_machine_type_message_regex, e.message): raise exceptions.ToolException( e.message + '\nUse `gcloud compute machine-types list --zones` to see the ' 'available machine types.') raise errors_to_collect = [] responses = compute_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] for instance_ref, operation_ref in zip(instance_refs, operation_refs): log.status.Print('Instance creation in progress for [{}]: {}' .format(instance_ref.instance, operation_ref.SelfLink())) log.status.Print('Use [gcloud compute operations describe URI] command ' 'to check the status of the operation(s).') if not args.IsSpecified('format'): # For async output we need a separate format. Since we already printed in # the status messages information about operations there is nothing else # needs to be printed. args.format = 'disable' return responses
def _ValidateArgs(self, args, compute_client): self._ValidateInstanceName(args) self._CheckForExistingInstances(args.instance_name, compute_client) instances_flags.ValidateNicFlags(args) instances_flags.ValidateNetworkTierArgs(args) daisy_utils.ValidateZone(args, compute_client)
def _ValidateInstancesFlags( args, support_kms=False, support_max_run_duration=False ): """Validate flags for instance template that affects instance creation. Args: args: argparse.Namespace, An object that contains the values for the arguments specified in the .Args() method. support_kms: If KMS is supported. support_max_run_duration: max-run-durrations is supported in instance scheduling. """ instances_flags.ValidateDiskCommonFlags(args) instances_flags.ValidateDiskBootFlags(args, enable_kms=support_kms) instances_flags.ValidateCreateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateReservationAffinityGroup(args) instances_flags.ValidateNetworkPerformanceConfigsArgs(args) instances_flags.ValidateInstanceScheduling( args, support_max_run_duration=support_max_run_duration)
def Run(self, args): instances_flags.ValidateBulkDiskFlags( args, enable_snapshots=True, enable_source_snapshot_csek=self._support_source_snapshot_csek, enable_image_csek=self._support_image_csek) instances_flags.ValidateImageFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateNetworkTierArgs(args) instances_flags.ValidateReservationAffinityGroup(args) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources project = properties.VALUES.core.project.GetOrFail() location = None scope = None if args.IsSpecified('zone'): location = args.zone scope = compute_scopes.ScopeEnum.ZONE elif args.IsSpecified('region'): location = args.region scope = compute_scopes.ScopeEnum.REGION instances_service, request = self._CreateRequests( args, holder, compute_client, resource_parser, project, location, scope) self._errors = [] self._log_async = False self._status_message = None if args.async_: self._log_async = True try: response = instances_service.BulkInsert(request) self._operation_selflink = response.selfLink return except exceptions.HttpError as error: raise error errors_to_collect = [] response = compute_client.MakeRequests( [(instances_service, 'BulkInsert', request)], errors_to_collect=errors_to_collect, log_result=False, always_return_operation=True, no_followup=True) self._errors = errors_to_collect if response: self._status_message = response[0].statusMessage return
def _ValidateArgs(self, args): instances_flags.ValidateKonletArgs(args) instances_flags.ValidateDiskCommonFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateNicFlags(args) if instance_utils.UseExistingBootDisk(args.disk or []): raise exceptions.InvalidArgumentException( '--disk', 'Boot disk specified for containerized VM.')
def _ValidateArgs(self, args, compute_client): instances_flags.ValidateNicFlags(args) instances_flags.ValidateNetworkTierArgs(args) daisy_utils.ValidateZone(args, compute_client) try: args.source_uri = daisy_utils.MakeGcsUri(args.source_uri) except resources.UnknownCollectionException: raise exceptions.InvalidArgumentException( 'source-uri', 'must be a path to an object or a directory in Cloud Storage')
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) self._ValidateInstanceName(args) self._CheckForExistingInstances(args.instance_name, compute_holder.client) instances_flags.ValidateNicFlags(args) instances_flags.ValidateNetworkTierArgs(args) log.warning('Importing OVF. This may take 40 minutes for smaller OVFs ' 'and up to a couple of hours for larger OVFs.') machine_type = None if args.machine_type or args.custom_cpu or args.custom_memory: machine_type = instance_utils.InterpretMachineType( machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory, ext=getattr(args, 'custom_extensions', None), vm_type=getattr(args, 'custom_vm_type', None)) try: source_uri = daisy_utils.MakeGcsObjectOrPathUri(args.source_uri) except storage_util.InvalidObjectNameError: raise exceptions.InvalidArgumentException( 'source-uri', 'must be a path to an object or a directory in Google Cloud Storage' ) return daisy_utils.RunOVFImportBuild( args=args, compute_client=compute_holder.client, instance_name=args.instance_name, source_uri=source_uri, no_guest_environment=not args.guest_environment, can_ip_forward=args.can_ip_forward, deletion_protection=args.deletion_protection, description=args.description, labels=args.labels, machine_type=machine_type, network=args.network, network_tier=args.network_tier, subnet=args.subnet, private_network_ip=args.private_network_ip, no_restart_on_failure=not args.restart_on_failure, os=args.os, tags=args.tags, zone=properties.VALUES.compute.zone.Get(), project=args.project, output_filter=_OUTPUT_FILTER, compute_release_track=self.ReleaseTrack().id.lower() if self.ReleaseTrack() else None)
def Run(self, args): instances_flags.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources requests = self._CreateRequests(args, compute_client, resource_parser) return compute_client.MakeRequests(requests)
def _ValidateArgs(self, args): self._ValidateTrackSpecificArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateNetworkTierArgs(args) instances_flags.ValidateKonletArgs(args) instances_flags.ValidateDiskCommonFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidatePublicPtrFlags(args) instances_flags.ValidateNetworkPerformanceConfigsArgs(args) instances_flags.ValidateInstanceScheduling(args) if instance_utils.UseExistingBootDisk(args.disk or []): raise exceptions.InvalidArgumentException( '--disk', 'Boot disk specified for containerized VM.')
def _ValidateInstancesFlags(args): """Validate flags for instance template that affects instance creation. Args: args: argparse.Namespace, An object that contains the values for the arguments specified in the .Args() method. """ instances_flags.ValidateDiskCommonFlags(args) instances_flags.ValidateDiskBootFlags(args) instances_flags.ValidateCreateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args)
def _ValidateInstancesFlags(args, support_kms=False,): """Validate flags for instance template that affects instance creation. Args: args: argparse.Namespace, An object that contains the values for the arguments specified in the .Args() method. support_kms: If KMS is supported. """ instances_flags.ValidateDiskCommonFlags(args) instances_flags.ValidateDiskBootFlags(args, enable_kms=support_kms) instances_flags.ValidateCreateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateReservationAffinityGroup(args)
def Run(self, args): compute_holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) self._ValidateInstanceNames(args) self._CheckForExistingInstances(args.instance_names, compute_holder.client) instances_flags.ValidateNicFlags(args) instances_flags.ValidateNetworkTierArgs(args) log.warning('Importing OVF. This may take 40 minutes for smaller OVFs ' 'and up to a couple of hours for larger OVFs.') machine_type = instance_utils.InterpretMachineType( machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory, ext=getattr(args, 'custom_extensions', None)) return daisy_utils.RunOVFImportBuild( args=args, instance_names=args.instance_names, source_uri=daisy_utils.MakeGcsUri(args.source_uri), no_guest_environment=not args.guest_environment, can_ip_forward=args.can_ip_forward, deletion_protection=args.deletion_protection, description=args.description, labels=args.labels, machine_type=machine_type, network=args.network, network_tier=args.network_tier, subnet=args.subnet, private_network_ip=args.private_network_ip, no_restart_on_failure=not args.restart_on_failure, os=args.os, tags=args.tags, zone=properties.VALUES.compute.zone.Get(), project=args.project, output_filter=_OUTPUT_FILTER)
def Run(self, args): instances_flags.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources requests = self._CreateRequests(args, compute_client, resource_parser) try: return compute_client.MakeRequests(requests) except exceptions.ToolException as e: invalid_machine_type_message_regex = ( r'Invalid value for field \'resource.machineType\': .+. ' r'Machine type with name \'.+\' does not exist in zone \'.+\'\.') if re.search(invalid_machine_type_message_regex, e.message): raise exceptions.ToolException( e.message + '\nUse `gcloud compute machine-types list --zones` to see the ' 'available machine types.') raise
def CreateRequests(self, args): """Creates and returns an InstanceTemplates.Insert request. Args: args: the argparse arguments that this command was invoked with. Returns: request: a ComputeInstanceTemplatesInsertRequest message object """ self.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size) utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type) instance_template_ref = ( instance_templates_flags.INSTANCE_TEMPLATE_ARG.ResolveAsResource( args, self.resources)) metadata = metadata_utils.ConstructMetadataMessage( self.messages, metadata=args.metadata, metadata_from_file=args.metadata_from_file) if hasattr(args, 'network_interface') and args.network_interface: network_interfaces = ( instance_template_utils.CreateNetworkInterfaceMessages)( scope_prompter=self, messages=self.messages, network_interface_arg=args.network_interface, region=args.region) else: network_interfaces = [ instance_template_utils.CreateNetworkInterfaceMessage( scope_prompter=self, messages=self.messages, network=args.network, region=args.region, subnet=args.subnet, address=(instance_template_utils.EPHEMERAL_ADDRESS if not args.no_address and not args.address else args.address)) ] scheduling = instance_utils.CreateSchedulingMessage( messages=self.messages, maintenance_policy=args.maintenance_policy, preemptible=args.preemptible, restart_on_failure=args.restart_on_failure) service_accounts = instance_utils.CreateServiceAccountMessages( messages=self.messages, scopes=([] if args.no_scopes else args.scopes)) create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or []) if create_boot_disk: image_uri, _ = self.ExpandImageFlag( image=args.image, image_family=args.image_family, image_project=args.image_project, return_image_resource=True) else: image_uri = None if args.tags: tags = self.messages.Tags(items=args.tags) else: tags = None persistent_disks = ( instance_template_utils.CreatePersistentAttachedDiskMessages( self.messages, args.disk or [])) persistent_create_disks = ( instance_template_utils.CreatePersistentCreateDiskMessages( self, self.messages, getattr(args, 'create_disk', []))) if create_boot_disk: boot_disk_list = [ instance_template_utils.CreateDefaultBootAttachedDiskMessage( messages=self.messages, disk_type=args.boot_disk_type, disk_device_name=args.boot_disk_device_name, disk_auto_delete=args.boot_disk_auto_delete, disk_size_gb=boot_disk_size_gb, image_uri=image_uri) ] else: boot_disk_list = [] local_ssds = [] for x in args.local_ssd or []: local_ssd = instance_utils.CreateLocalSsdMessage( self.resources, self.messages, x.get('device-name'), x.get('interface')) local_ssds.append(local_ssd) disks = (boot_disk_list + persistent_disks + persistent_create_disks + local_ssds) machine_type = instance_utils.InterpretMachineType( machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory) request = self.messages.ComputeInstanceTemplatesInsertRequest( instanceTemplate=self.messages.InstanceTemplate( properties=self.messages.InstanceProperties( machineType=machine_type, disks=disks, canIpForward=args.can_ip_forward, metadata=metadata, networkInterfaces=network_interfaces, serviceAccounts=service_accounts, scheduling=scheduling, tags=tags, ), description=args.description, name=instance_template_ref.Name(), ), project=self.project) return [request]
def _CreateRequests(self, args): instances_flags.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) # This feature is only exposed in alpha/beta allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA] self.csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted) scheduling = instance_utils.CreateSchedulingMessage( messages=self.messages, maintenance_policy=args.maintenance_policy, preemptible=args.preemptible, restart_on_failure=args.restart_on_failure) if args.tags: tags = self.messages.Tags(items=args.tags) else: tags = None metadata = metadata_utils.ConstructMetadataMessage( self.messages, metadata=args.metadata, metadata_from_file=args.metadata_from_file) # If the user already provided an initial Windows password and # username through metadata, then there is no need to check # whether the image or the boot disk is Windows. boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size) utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type) instance_refs = instances_flags.INSTANCES_ARG.ResolveAsResource( args, self.resources, scope_lister=flags.GetDefaultScopeLister( self.compute_client, self.project)) # Check if the zone is deprecated or has maintenance coming. zone_resource_fetcher = zone_utils.ZoneResourceFetcher(self.compute_client) zone_resource_fetcher.WarnForZonalCreation(instance_refs) network_interface_arg = getattr(args, 'network_interface', None) if network_interface_arg: network_interfaces = instance_utils.CreateNetworkInterfaceMessages( resources=self.resources, compute_client=self.compute_client, network_interface_arg=network_interface_arg, instance_refs=instance_refs, support_network_tier=self._support_network_tier) else: if self._support_public_dns is True: instances_flags.ValidatePublicDnsFlags(args) network_tier = getattr(args, 'network_tier', None) network_interfaces = [ instance_utils.CreateNetworkInterfaceMessage( resources=self.resources, compute_client=self.compute_client, network=args.network, subnet=args.subnet, private_network_ip=args.private_network_ip, no_address=args.no_address, address=args.address, instance_refs=instance_refs, network_tier=network_tier, no_public_dns=getattr(args, 'no_public_dns', None), public_dns=getattr(args, 'public_dns', None), no_public_ptr=getattr(args, 'no_public_ptr', None), public_ptr=getattr(args, 'public_ptr', None), no_public_ptr_domain=getattr(args, 'no_public_ptr_domain', None), public_ptr_domain=getattr(args, 'public_ptr_domain', None)) ] machine_type_uris = instance_utils.CreateMachineTypeUris( resources=self.resources, compute_client=self.compute_client, project=self.project, machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory, ext=getattr(args, 'custom_extensions', None), instance_refs=instance_refs) create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or []) if create_boot_disk: image_expander = image_utils.ImageExpander(self.compute_client, self.resources) image_uri, _ = image_expander.ExpandImageFlag( user_project=self.project, image=args.image, image_family=args.image_family, image_project=args.image_project, return_image_resource=False) else: image_uri = None # A list of lists where the element at index i contains a list of # disk messages that should be set for the instance at index i. disks_messages = [] # A mapping of zone to boot disk references for all existing boot # disks that are being attached. # TODO(user): Simplify this once resources.Resource becomes # hashable. existing_boot_disks = {} for instance_ref in instance_refs: persistent_disks, boot_disk_ref = ( instance_utils.CreatePersistentAttachedDiskMessages( self.resources, self.compute_client, self.csek_keys, args.disk or [], instance_ref)) persistent_create_disks = ( instance_utils.CreatePersistentCreateDiskMessages( self, self.compute_client, self.resources, self.csek_keys, getattr(args, 'create_disk', []), instance_ref)) local_ssds = [] for x in args.local_ssd or []: local_ssds.append( instance_utils.CreateLocalSsdMessage( self.resources, self.messages, x.get('device-name'), x.get('interface'), instance_ref.zone) ) if create_boot_disk: boot_disk = instance_utils.CreateDefaultBootAttachedDiskMessage( self.compute_client, self.resources, disk_type=args.boot_disk_type, disk_device_name=args.boot_disk_device_name, disk_auto_delete=args.boot_disk_auto_delete, disk_size_gb=boot_disk_size_gb, require_csek_key_create=( args.require_csek_key_create if self.csek_keys else None), image_uri=image_uri, instance_ref=instance_ref, csek_keys=self.csek_keys) persistent_disks = [boot_disk] + persistent_disks else: existing_boot_disks[boot_disk_ref.zone] = boot_disk_ref disks_messages.append(persistent_disks + persistent_create_disks + local_ssds) accelerator_args = getattr(args, 'accelerator', None) project_to_sa = {} requests = [] for instance_ref, machine_type_uri, disks in zip( instance_refs, machine_type_uris, disks_messages): if instance_ref.project not in project_to_sa: scopes = None if not args.no_scopes and not args.scopes: # User didn't provide any input on scopes. If project has no default # service account then we want to create a VM with no scopes request = (self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest( project=instance_ref.project)) errors = [] result = self.compute_client.MakeRequests([request], errors) if not errors: if not result[0].defaultServiceAccount: scopes = [] log.status.Print( 'There is no default service account for project {}. ' 'Instance {} will not have scopes.'.format( instance_ref.project, instance_ref.Name)) if scopes is None: scopes = [] if args.no_scopes else args.scopes if args.no_service_account: service_account = None else: service_account = args.service_account service_accounts = instance_utils.CreateServiceAccountMessages( messages=self.messages, scopes=scopes, service_account=service_account) project_to_sa[instance_ref.project] = service_accounts instance = self.messages.Instance( canIpForward=args.can_ip_forward, disks=disks, description=args.description, machineType=machine_type_uri, metadata=metadata, name=instance_ref.Name(), networkInterfaces=network_interfaces, serviceAccounts=project_to_sa[instance_ref.project], scheduling=scheduling, tags=tags) if getattr(args, 'min_cpu_platform', None): instance.minCpuPlatform = args.min_cpu_platform if accelerator_args: accelerator_type_name = accelerator_args['type'] accelerator_type_ref = self.resources.Parse( accelerator_type_name, collection='compute.acceleratorTypes', params={'project': instance_ref.project, 'zone': instance_ref.zone}) # Accelerator count is default to 1. accelerator_count = int(accelerator_args.get('count', 1)) accelerators = instance_utils.CreateAcceleratorConfigMessages( self.compute_client.messages, accelerator_type_ref, accelerator_count) instance.guestAccelerators = accelerators request = self.messages.ComputeInstancesInsertRequest( instance=instance, project=instance_ref.project, zone=instance_ref.zone) sole_tenancy_host_arg = getattr(args, 'sole_tenancy_host', None) if sole_tenancy_host_arg: sole_tenancy_host_ref = self.resources.Parse( sole_tenancy_host_arg, collection='compute.hosts', params={'zone': instance_ref.zone}) request.instance.host = sole_tenancy_host_ref.SelfLink() requests.append((self.compute.instances, 'Insert', request)) return requests
def Run(self, args): """Creates and runs an InstanceTemplates.Insert request. Args: args: argparse.Namespace, An object that contains the values for the arguments specified in the .Args() method. Returns: A resource object dispatched by display.Displayer(). """ holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client self.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size) utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type) instance_template_ref = (Create.InstanceTemplateArg.ResolveAsResource( args, holder.resources)) metadata = metadata_utils.ConstructMetadataMessage( client.messages, metadata=args.metadata, metadata_from_file=args.metadata_from_file) if hasattr(args, 'network_interface') and args.network_interface: network_interfaces = ( instance_template_utils.CreateNetworkInterfaceMessages)( resources=holder.resources, scope_lister=flags.GetDefaultScopeLister(client), messages=client.messages, network_interface_arg=args.network_interface, region=args.region) else: network_interfaces = [ instance_template_utils.CreateNetworkInterfaceMessage( resources=holder.resources, scope_lister=flags.GetDefaultScopeLister(client), messages=client.messages, network=args.network, region=args.region, subnet=args.subnet, address=(instance_template_utils.EPHEMERAL_ADDRESS if not args.no_address and not args.address else args.address)) ] scheduling = instance_utils.CreateSchedulingMessage( messages=client.messages, maintenance_policy=args.maintenance_policy, preemptible=args.preemptible, restart_on_failure=args.restart_on_failure) if args.no_service_account: service_account = None else: service_account = args.service_account service_accounts = instance_utils.CreateServiceAccountMessages( messages=client.messages, scopes=[] if args.no_scopes else args.scopes, service_account=service_account) create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or []) if create_boot_disk: image_expander = image_utils.ImageExpander(client, holder.resources) image_uri, _ = image_expander.ExpandImageFlag( user_project=instance_template_ref.project, image=args.image, image_family=args.image_family, image_project=args.image_project, return_image_resource=True) else: image_uri = None if args.tags: tags = client.messages.Tags(items=args.tags) else: tags = None persistent_disks = ( instance_template_utils.CreatePersistentAttachedDiskMessages( client.messages, args.disk or [])) persistent_create_disks = ( instance_template_utils.CreatePersistentCreateDiskMessages( client, holder.resources, instance_template_ref.project, getattr(args, 'create_disk', []))) if create_boot_disk: boot_disk_list = [ instance_template_utils.CreateDefaultBootAttachedDiskMessage( messages=client.messages, disk_type=args.boot_disk_type, disk_device_name=args.boot_disk_device_name, disk_auto_delete=args.boot_disk_auto_delete, disk_size_gb=boot_disk_size_gb, image_uri=image_uri) ] else: boot_disk_list = [] local_ssds = [] for x in args.local_ssd or []: local_ssd = instance_utils.CreateLocalSsdMessage( holder.resources, client.messages, x.get('device-name'), x.get('interface'), x.get('size')) local_ssds.append(local_ssd) disks = (boot_disk_list + persistent_disks + persistent_create_disks + local_ssds) machine_type = instance_utils.InterpretMachineType( machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory, ext=getattr(args, 'custom_extensions', None)) guest_accelerators = ( instance_template_utils.CreateAcceleratorConfigMessages( client.messages, getattr(args, 'accelerator', None))) instance_properties = client.messages.InstanceProperties( machineType=machine_type, disks=disks, canIpForward=args.can_ip_forward, metadata=metadata, networkInterfaces=network_interfaces, serviceAccounts=service_accounts, scheduling=scheduling, tags=tags, ) # TODO(b/36890961): Pass this directly into guestAccelerators once GA. if guest_accelerators: instance_properties.guestAccelerators = guest_accelerators request = client.messages.ComputeInstanceTemplatesInsertRequest( instanceTemplate=client.messages.InstanceTemplate( properties=instance_properties, description=args.description, name=instance_template_ref.Name(), ), project=instance_template_ref.project) if getattr(args, 'min_cpu_platform', None): request.instanceTemplate.properties.minCpuPlatform = args.min_cpu_platform return client.MakeRequests([(client.apitools_client.instanceTemplates, 'Insert', request)])
def CreateRequests(self, args): instances_flags.ValidateDiskFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) # This feature is only exposed in alpha/beta allow_rsa_encrypted = self.ReleaseTrack() in [base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA] self.csek_keys = csek_utils.CsekKeyStore.FromArgs(args, allow_rsa_encrypted) scheduling = instance_utils.CreateSchedulingMessage( messages=self.messages, maintenance_policy=args.maintenance_policy, preemptible=args.preemptible, restart_on_failure=args.restart_on_failure) service_accounts = instance_utils.CreateServiceAccountMessages( messages=self.messages, scopes=([] if args.no_scopes else args.scopes)) if args.tags: tags = self.messages.Tags(items=args.tags) else: tags = None metadata = metadata_utils.ConstructMetadataMessage( self.messages, metadata=args.metadata, metadata_from_file=args.metadata_from_file) # If the user already provided an initial Windows password and # username through metadata, then there is no need to check # whether the image or the boot disk is Windows. boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size) utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type) instance_refs = instances_flags.INSTANCES_ARG.ResolveAsResource( args, self.resources, scope_lister=flags.GetDefaultScopeLister( self.compute_client, self.project)) # Check if the zone is deprecated or has maintenance coming. self.WarnForZonalCreation(instance_refs) if hasattr(args, 'network_interface') and args.network_interface: network_interfaces = instance_utils.CreateNetworkInterfaceMessages( resources=self.resources, compute_client=self.compute_client, network_interface_arg=args.network_interface, instance_refs=instance_refs) else: network_interfaces = [ instance_utils.CreateNetworkInterfaceMessage( resources=self.resources, compute_client=self.compute_client, network=args.network, subnet=args.subnet, private_network_ip=args.private_network_ip, no_address=args.no_address, address=args.address, instance_refs=instance_refs) ] machine_type_uris = instance_utils.CreateMachineTypeUris( resources=self.resources, compute_client=self.compute_client, project=self.project, machine_type=args.machine_type, custom_cpu=args.custom_cpu, custom_memory=args.custom_memory, instance_refs=instance_refs) create_boot_disk = not instance_utils.UseExistingBootDisk(args.disk or []) if create_boot_disk: image_uri, _ = self.ExpandImageFlag( image=args.image, image_family=args.image_family, image_project=args.image_project, return_image_resource=False) else: image_uri = None # A list of lists where the element at index i contains a list of # disk messages that should be set for the instance at index i. disks_messages = [] # A mapping of zone to boot disk references for all existing boot # disks that are being attached. # TODO(user): Simplify this once resources.Resource becomes # hashable. existing_boot_disks = {} for instance_ref in instance_refs: persistent_disks, boot_disk_ref = ( instance_utils.CreatePersistentAttachedDiskMessages( self.resources, self.compute_client, self.csek_keys, args.disk or [], instance_ref)) persistent_create_disks = ( instance_utils.CreatePersistentCreateDiskMessages( self, self.compute_client, self.resources, self.csek_keys, getattr(args, 'create_disk', []), instance_ref)) local_ssds = [] for x in args.local_ssd or []: local_ssds.append( instance_utils.CreateLocalSsdMessage( self.resources, self.messages, x.get('device-name'), x.get('interface'), instance_ref.zone) ) if create_boot_disk: boot_disk = instance_utils.CreateDefaultBootAttachedDiskMessage( self.compute_client, self.resources, disk_type=args.boot_disk_type, disk_device_name=args.boot_disk_device_name, disk_auto_delete=args.boot_disk_auto_delete, disk_size_gb=boot_disk_size_gb, require_csek_key_create=( args.require_csek_key_create if self.csek_keys else None), image_uri=image_uri, instance_ref=instance_ref, csek_keys=self.csek_keys) persistent_disks = [boot_disk] + persistent_disks else: existing_boot_disks[boot_disk_ref.zone] = boot_disk_ref disks_messages.append(persistent_disks + persistent_create_disks + local_ssds) requests = [] for instance_ref, machine_type_uri, disks in zip( instance_refs, machine_type_uris, disks_messages): requests.append(self.messages.ComputeInstancesInsertRequest( instance=self.messages.Instance( canIpForward=args.can_ip_forward, disks=disks, description=args.description, machineType=machine_type_uri, metadata=metadata, name=instance_ref.Name(), networkInterfaces=network_interfaces, serviceAccounts=service_accounts, scheduling=scheduling, tags=tags, ), project=self.project, zone=instance_ref.zone)) return requests
def Run(self, args): """Runs bulk create command. Args: args: argparse.Namespace, An object that contains the values for the arguments specified in the .Args() method. Returns: A resource object dispatched by display.Displayer(). """ instances_flags.ValidateBulkCreateArgs(args) if self._support_enable_target_shape: instances_flags.ValidateBulkTargetShapeArgs(args) instances_flags.ValidateLocationPolicyArgs(args) instances_flags.ValidateBulkDiskFlags( args, enable_source_snapshot_csek=self._support_source_snapshot_csek, enable_image_csek=self._support_image_csek) instances_flags.ValidateImageFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateNetworkTierArgs(args) instances_flags.ValidateReservationAffinityGroup(args) instances_flags.ValidateNetworkPerformanceConfigsArgs(args) instances_flags.ValidateInstanceScheduling( args, support_max_run_duration=self._support_max_run_duration) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources project = properties.VALUES.core.project.GetOrFail() location = None scope = None if args.IsSpecified('zone'): location = args.zone scope = compute_scopes.ScopeEnum.ZONE elif args.IsSpecified('region'): location = args.region scope = compute_scopes.ScopeEnum.REGION instances_service, request = self._CreateRequests( args, holder, compute_client, resource_parser, project, location, scope) self._errors = [] self._log_async = False self._status_message = None if args.async_: self._log_async = True try: response = instances_service.BulkInsert(request) self._operation_selflink = response.selfLink return {'operationGroupId': response.operationGroupId} except exceptions.HttpException as error: raise error errors_to_collect = [] response = compute_client.MakeRequests( [(instances_service, 'BulkInsert', request)], errors_to_collect=errors_to_collect, log_result=False, always_return_operation=True, no_followup=True) self._errors = errors_to_collect if response: operation_group_id = response[0].operationGroupId result = _GetResult(compute_client, request, operation_group_id) if result['createdInstanceCount'] is not None and result[ 'failedInstanceCount'] is not None: self._status_message = 'VM instances created: {}, failed: {}.'.format( result['createdInstanceCount'], result['failedInstanceCount']) return result return
def Run(self, args): instances_flags.ValidateDiskFlags( args, enable_kms=self._support_kms, enable_snapshots=True, enable_source_snapshot_csek=self._support_source_snapshot_csek, enable_image_csek=self._support_image_csek) instances_flags.ValidateImageFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateNetworkTierArgs(args) instances_flags.ValidateReservationAffinityGroup(args) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources instance_refs = instance_utils.GetInstanceRefs(args, compute_client, holder) requests = self._CreateRequests(args, instance_refs, instance_refs[0].project, instance_refs[0].zone, compute_client, resource_parser, holder) if not args.async_: # TODO(b/63664449): Replace this with poller + progress tracker. try: # Using legacy MakeRequests (which also does polling) here until # replaced by api_lib.utils.waiter. return compute_client.MakeRequests(requests) except exceptions.ToolException as e: invalid_machine_type_message_regex = ( r'Invalid value for field \'resource.machineType\': .+. ' r'Machine type with name \'.+\' does not exist in zone \'.+\'\.' ) if re.search(invalid_machine_type_message_regex, six.text_type(e)): raise exceptions.ToolException( six.text_type(e) + '\nUse `gcloud compute machine-types list --zones` to see the ' 'available machine types.') raise errors_to_collect = [] responses = compute_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 ] log.status.Print( 'NOTE: The users will be charged for public IPs when VMs ' 'are created.') for instance_ref, operation_ref in zip(instance_refs, operation_refs): log.status.Print( 'Instance creation in progress for [{}]: {}'.format( instance_ref.instance, operation_ref.SelfLink())) log.status.Print( 'Use [gcloud compute operations describe URI] command ' 'to check the status of the operation(s).') if not args.IsSpecified('format'): # For async output we need a separate format. Since we already printed in # the status messages information about operations there is nothing else # needs to be printed. args.format = 'disable' return responses