def Run(self, args): super(ConnectToSerialPort, self).Run(args) parts = args.user_host.split('@') if len(parts) == 1: user = getpass.getuser() instance = parts[0] elif len(parts) == 2: user, instance = parts else: raise exceptions.ToolException( 'Expected argument of the form [USER@]INSTANCE; received [{0}].' .format(args.user_host)) instance_ref = self.CreateZonalReference(instance, args.zone) instance = self.GetInstance(instance_ref) ssh_args = [self.ssh_executable] ssh_args.extend(['-i', self.ssh_key_file]) ssh_args.extend(['-o', 'IdentitiesOnly=yes']) ssh_args.extend(['-p', CONNECTION_PORT]) if args.port: port = 'port={0}'.format(args.port) else: port = 'port=1' constructed_username_list = [instance_ref.project, instance_ref.zone, instance_ref.Name(), user, port] if args.extra_args: for k, v in args.extra_args.items(): constructed_username_list.append('{0}={1}'.format(k, v)) ssh_args.append(ssh_utils.UserHost('.'.join(constructed_username_list), args.serial_port_gateway)) log.info('ssh command: {0}'.format(' '.join(ssh_args))) # Don't wait for the instance to become SSHable. We are not connecting to # the instance itself through SSH, so the instance doesn't need to have # fully booted to connect to the serial port. return_code = self.ActuallyRun( args, ssh_args, user, instance, strict_error_checking=False, use_account_service=False, wait_for_sshable=False) if return_code: sys.exit(return_code)
def Run(self, args): super(SshGA, self).Run(args) parts = args.user_host.split('@') if len(parts) == 1: if self._use_accounts_service: # Using Account Service. user = gaia_utils.GetDefaultAccountName(self.http) else: # Uploading keys through metadata. user = getpass.getuser() instance = parts[0] elif len(parts) == 2: user, instance = parts else: raise exceptions.ToolException( 'Expected argument of the form [USER@]INSTANCE; received [{0}].' .format(args.user_host)) instance_ref = self.CreateZonalReference(instance, args.zone) external_ip_address = self.GetInstanceExternalIpAddress(instance_ref) ssh_args = [self.ssh_executable] if not args.plain: ssh_args.extend(self.GetDefaultFlags()) # Allocates a tty if no command was provided and a container was provided. if args.container and not args.command: ssh_args.append('-t') if args.ssh_flag: for flag in args.ssh_flag: dereferenced_flag = (flag.replace('%USER%', user).replace( '%INSTANCE%', external_ip_address)) ssh_args.append(dereferenced_flag) ssh_args.append(ssh_utils.UserHost(user, external_ip_address)) if args.implementation_args: ssh_args.extend(args.implementation_args) if args.container: ssh_args.append('--') ssh_args.append('container_exec') ssh_args.append(args.container) # Runs the given command inside the given container if --command was # specified, otherwise runs /bin/sh. if args.command: ssh_args.append(args.command) else: ssh_args.append('/bin/sh') elif args.command: ssh_args.append('--') ssh_args.append(args.command) # Don't use strict error checking for ssh: if the executed command fails, we # don't want to consider it an error. We do, however, want to propagate its # return code. return_code = self.ActuallyRun( args, ssh_args, user, external_ip_address, strict_error_checking=False, use_account_service=self._use_accounts_service) if return_code: # Can't raise an exception because we don't want any "ERROR" message # printed; the output from `ssh` will be enough. sys.exit(return_code)
def Run(self, args): super(ConnectToSerialPort, self).Run(args) parts = args.user_host.split('@') if len(parts) == 1: user = getpass.getuser() instance = parts[0] elif len(parts) == 2: user, instance = parts else: raise exceptions.ToolException( 'Expected argument of the form [USER@]INSTANCE; received [{0}].' .format(args.user_host)) # Update google_compute_known_hosts file with published host key if args.serial_port_gateway == SERIAL_PORT_GATEWAY: http_client = http.Http() http_response = http_client.request(HOST_KEY_URL) hostname = '[{0}]:{1}'.format(SERIAL_PORT_GATEWAY, CONNECTION_PORT) if http_response[0]['status'] == '200': host_key = http_response[1].strip() ssh_utils.UpdateKnownHostsFile(self.known_hosts_file, hostname, host_key, overwrite_keys=True) elif self.IsHostKeyAliasInKnownHosts(hostname): log.warn( 'Unable to download and update Host Key for [{0}] from [{1}]. ' 'Attempting to connect using existing Host Key in [{2}]. If ' 'the connection fails, please try again to update the Host ' 'Key.'.format(SERIAL_PORT_GATEWAY, HOST_KEY_URL, self.known_hosts_file)) else: ssh_utils.UpdateKnownHostsFile(self.known_hosts_file, hostname, DEFAULT_HOST_KEY) log.warn( 'Unable to download Host Key for [{0}] from [{1}]. To ensure ' 'the security of the SSH connetion, gcloud will attempt to ' 'connect using a hard-coded Host Key value. If the connection ' 'fails, please try again. If the problem persists, try ' 'updating gcloud and connecting again.'.format( SERIAL_PORT_GATEWAY, HOST_KEY_URL)) instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources( [instance], compute_scope.ScopeEnum.ZONE, args.zone, self.resources, scope_lister=flags.GetDefaultScopeLister(self.compute_client, self.project))[0] instance = self.GetInstance(instance_ref) ssh_args = [self.ssh_executable] ssh_args.extend(self.GetDefaultFlags()) if args.serial_port_gateway == SERIAL_PORT_GATEWAY: ssh_args.extend(['-o', 'StrictHostKeyChecking=yes']) ssh_args.extend(['-p', CONNECTION_PORT]) if args.port: port = 'port={0}'.format(args.port) else: port = 'port=1' constructed_username_list = [ instance_ref.project, instance_ref.zone, instance_ref.Name(), user, port ] if args.extra_args: for k, v in args.extra_args.items(): constructed_username_list.append('{0}={1}'.format(k, v)) ssh_args.append( ssh_utils.UserHost('.'.join(constructed_username_list), args.serial_port_gateway)) log.info('ssh command: {0}'.format(' '.join(ssh_args))) # Don't wait for the instance to become SSHable. We are not connecting to # the instance itself through SSH, so the instance doesn't need to have # fully booted to connect to the serial port. return_code = self.ActuallyRun(args, ssh_args, user, instance, instance_ref.project, strict_error_checking=False, use_account_service=False, wait_for_sshable=False) if return_code: sys.exit(return_code)
def Run(self, args): super(Scp, self).Run(args) file_specs = [] # Parses the positional arguments. for arg in args.sources + [args.destination]: if ssh_utils.IsScpLocalPath(arg): file_specs.append(LocalFile(arg)) else: user_host, file_path = arg.split(':', 1) user_host_parts = user_host.split('@', 1) if len(user_host_parts) == 1: user = ssh_utils.GetDefaultSshUsername(warn_on_account_user=True) instance = user_host_parts[0] else: user, instance = user_host_parts file_specs.append(RemoteFile(user, instance, file_path)) logging.debug('Normalized arguments: %s', file_specs) # Validates the positional arguments. # TODO(b/21515495): Look into relaxing these conditions. sources = file_specs[:-1] destination = file_specs[-1] if isinstance(destination, LocalFile): for source in sources: if isinstance(source, LocalFile): raise exceptions.ToolException( 'All sources must be remote files when the destination ' 'is local.') else: # RemoteFile for source in sources: if isinstance(source, RemoteFile): raise exceptions.ToolException( 'All sources must be local files when the destination ' 'is remote.') instances = set() for file_spec in file_specs: if isinstance(file_spec, RemoteFile): instances.add(file_spec.instance_name) if len(instances) > 1: raise exceptions.ToolException( 'Copies must involve exactly one virtual machine instance; ' 'your invocation refers to [{0}] instances: [{1}].'.format( len(instances), ', '.join(sorted(instances)))) instance_ref = self.CreateZonalReference(instances.pop(), args.zone) instance = self.GetInstance(instance_ref) external_ip_address = ssh_utils.GetExternalIPAddress(instance) # Builds the scp command. scp_args = [self.scp_executable] if not args.plain: scp_args.extend(self.GetDefaultFlags()) # apply args if args.quiet: scp_args.append('-q') if args.port: scp_args.extend(['-P', args.port]) if args.recurse: scp_args.append('-r') if args.compress: scp_args.append('-C') if args.scp_flag: scp_args.extend(args.scp_flag) for file_spec in file_specs: if isinstance(file_spec, LocalFile): scp_args.append(file_spec.file_path) else: scp_args.append('{0}:{1}'.format( ssh_utils.UserHost(file_spec.user, external_ip_address), file_spec.file_path)) self.ActuallyRun(args, scp_args, user, instance)
def Run(self, args): super(Scp, self).Run(args) file_specs = [] # Parses the positional arguments. for arg in args.sources + [args.destination]: # If the argument begins with "./" or "/", then we are dealing # with a local file that can potentially contain colons, so we # avoid splitting on colons. The case of remote files containing # colons is handled below by splitting only on the first colon. if arg.startswith('./') or arg.startswith('/'): file_specs.append(LocalFile(arg)) continue host_file_parts = arg.split(':', 1) if len(host_file_parts) == 1: file_specs.append(LocalFile(host_file_parts[0])) else: user_host, file_path = host_file_parts user_host_parts = user_host.split('@', 1) if len(user_host_parts) == 1: user = getpass.getuser() instance = user_host_parts[0] else: user, instance = user_host_parts file_specs.append(RemoteFile(user, instance, file_path)) logging.debug('Normalized arguments: %s', file_specs) # Validates the positional arguments. # TODO(b/21515495): Look into relaxing these conditions. sources = file_specs[:-1] destination = file_specs[-1] if isinstance(destination, LocalFile): for source in sources: if isinstance(source, LocalFile): raise exceptions.ToolException( 'All sources must be remote files when the destination ' 'is local.') else: # RemoteFile for source in sources: if isinstance(source, RemoteFile): raise exceptions.ToolException( 'All sources must be local files when the destination ' 'is remote.') instances = set() for file_spec in file_specs: if isinstance(file_spec, RemoteFile): instances.add(file_spec.instance_name) if len(instances) > 1: raise exceptions.ToolException( 'Copies must involve exactly one virtual machine instance; ' 'your invocation refers to [{0}] instances: [{1}].'.format( len(instances), ', '.join(sorted(instances)))) instance_ref = self.CreateZonalReference(instances.pop(), args.zone) external_ip_address = self.GetInstanceExternalIpAddress(instance_ref) # Builds the scp command. scp_args = [self.scp_executable] if not args.plain: scp_args.extend(self.GetDefaultFlags()) # apply args if args.quiet: scp_args.append('-q') if args.port: scp_args.extend(['-P', args.port]) if args.recurse: scp_args.append('-r') if args.compress: scp_args.append('-C') if args.scp_flag: scp_args.extend(args.scp_flag) for file_spec in file_specs: if isinstance(file_spec, LocalFile): scp_args.append(file_spec.file_path) else: scp_args.append('{0}:{1}'.format( ssh_utils.UserHost(file_spec.user, external_ip_address), file_spec.file_path)) self.ActuallyRun(args, scp_args, user, external_ip_address)
def Run(self, args): super(SshGA, self).Run(args) parts = args.user_host.split('@') if len(parts) == 1: if self._use_accounts_service: # Using Account Service. user = gaia_utils.GetDefaultAccountName(self.http) else: # Uploading keys through metadata. user = ssh_utils.GetDefaultSshUsername( warn_on_account_user=True) instance = parts[0] elif len(parts) == 2: user, instance = parts else: raise exceptions.ToolException( 'Expected argument of the form [USER@]INSTANCE; received [{0}].' .format(args.user_host)) instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources( [instance], compute_scope.ScopeEnum.ZONE, args.zone, self.resources, scope_lister=flags.GetDefaultScopeLister(self.compute_client, self.project))[0] instance = self.GetInstance(instance_ref) external_ip_address = ssh_utils.GetExternalIPAddress(instance) ssh_args = [self.ssh_executable] if not args.plain: ssh_args.extend(self.GetDefaultFlags()) # Allocates a tty if no command was provided and a container was provided. if args.container and not args.command: ssh_args.append('-t') if args.ssh_flag: for flag in args.ssh_flag: for flag_part in flag.split(): # We want grouping here dereferenced_flag = (flag_part.replace( '%USER%', user).replace('%INSTANCE%', external_ip_address)) ssh_args.append(dereferenced_flag) ssh_args.extend(self.GetHostKeyArgs(args, instance)) ssh_args.append(ssh_utils.UserHost(user, external_ip_address)) if args.ssh_args: ssh_args.extend(args.ssh_args) if args.container: ssh_args.append('--') ssh_args.append('container_exec') ssh_args.append(args.container) # Runs the given command inside the given container if --command was # specified, otherwise runs /bin/sh. if args.command: ssh_args.append(args.command) else: ssh_args.append('/bin/sh') elif args.command: if not platforms.OperatingSystem.IsWindows(): ssh_args.append('--') ssh_args.append(args.command) # Don't use strict error checking for ssh: if the executed command fails, we # don't want to consider it an error. We do, however, want to propagate its # return code. return_code = self.ActuallyRun( args, ssh_args, user, instance, instance_ref.project, strict_error_checking=False, use_account_service=self._use_accounts_service) if return_code: # Can't raise an exception because we don't want any "ERROR" message # printed; the output from `ssh` will be enough. sys.exit(return_code)
def Run(self, args): super(CopyFiles, self).Run(args) file_specs = [] # Parses the positional arguments. for arg in args.sources + [args.destination]: if ssh_utils.IsScpLocalPath(arg): file_specs.append(LocalFile(arg)) else: user_host, file_path = arg.split(':', 1) user_host_parts = user_host.split('@', 1) if len(user_host_parts) == 1: user = ssh_utils.GetDefaultSshUsername( warn_on_account_user=True) source_instance = user_host_parts[0] else: user, source_instance = user_host_parts file_specs.append(RemoteFile(user, source_instance, file_path)) log.debug('Normalized arguments: %s', file_specs) # Validates the positional arguments. # TODO(user): Look into relaxing these conditions. sources = file_specs[:-1] destination = file_specs[-1] if isinstance(destination, LocalFile): for source in sources: if isinstance(source, LocalFile): raise exceptions.ToolException( 'All sources must be remote files when the destination ' 'is local.') else: # RemoteFile for source in sources: if isinstance(source, RemoteFile): raise exceptions.ToolException( 'All sources must be local files when the destination ' 'is remote.') destination_instances = set() for file_spec in file_specs: if isinstance(file_spec, RemoteFile): destination_instances.add(file_spec.instance_name) if len(destination_instances) > 1: raise exceptions.ToolException( 'Copies must involve exactly one virtual machine instance; ' 'your invocation refers to [{0}] instances: [{1}].'.format( len(destination_instances), ', '.join(sorted(destination_instances)))) source_instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources( [source_instance], flags.ScopeEnum.ZONE, args.zone, self.resources, scope_lister=flags.GetDefaultScopeLister(self.compute_client, self.project))[0] source_instance = self.GetInstance(source_instance_ref) external_ip_address = ssh_utils.GetExternalIPAddress(source_instance) # Builds the scp command. scp_args = [self.scp_executable] if not args.plain: scp_args.extend(self.GetDefaultFlags()) scp_args.extend(self.GetHostKeyArgs(args, source_instance)) scp_args.append('-r') for file_spec in file_specs: if isinstance(file_spec, LocalFile): scp_args.append(file_spec.file_path) else: scp_args.append('{0}:{1}'.format( ssh_utils.UserHost(file_spec.user, external_ip_address), file_spec.file_path)) self.ActuallyRun(args, scp_args, user, source_instance, source_instance_ref.project)