def GetUserAndInstance(user_host, use_accounts_service, http): """Returns pair consiting of user name and instance name.""" parts = user_host.split('@') if len(parts) == 1: if use_accounts_service: # Using Account Service. user = gaia.GetDefaultAccountName(http) else: # Uploading keys through metadata. user = ssh.GetDefaultSshUsername(warn_on_account_user=True) instance = parts[0] return user, instance if len(parts) == 2: return parts raise exceptions.ToolException( 'Expected argument of the form [USER@]INSTANCE; received [{0}].'. format(user_host))
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.GetDefaultAccountName(self.http) else: # Uploading keys through metadata. user = ssh.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.env.ssh] if not args.plain: ssh_args.extend(ssh.GetDefaultFlags(self.keys.key_file)) # 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) host_key_alias = self.HostKeyAlias(instance) ssh_args.extend( ssh.GetHostKeyArgs(host_key_alias, args.plain, args.strict_host_key_checking)) ssh_args.append(ssh.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) # TODO(b/33467618): Change this implementation to use ssh.SCPCommand and # ssh.FileReference objects. file_specs = [] # Parses the positional arguments. for arg in args.sources + [args.destination]: if ssh.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.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], compute_scope.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.env.scp] if not args.plain: scp_args.extend(ssh.GetDefaultFlags(self.keys.key_file)) host_key_alias = self.HostKeyAlias(source_instance) scp_args.extend( ssh.GetHostKeyArgs(host_key_alias, args.plain, args.strict_host_key_checking)) 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.UserHost(file_spec.user, external_ip_address), file_spec.file_path)) self.ActuallyRun(args, scp_args, user, source_instance, source_instance_ref.project)
def Run(self, args): """Connect to a running flex instance. Args: args: argparse.Namespace, the args the command was invoked with. Raises: InvalidInstanceTypeError: The instance is not supported for SSH. MissingVersionError: The version specified does not exist. MissingInstanceError: The instance specified does not exist. UnattendedPromptError: Not running in a tty. OperationCancelledError: User cancelled the operation. ssh.CommandError: The SSH command exited with SSH exit code, which usually implies that a connection problem occurred. Returns: int, The exit code of the SSH command. """ api_client = appengine_api_client.GetApiClient() env = ssh.Environment.Current() env.RequireSSH() keys = ssh.Keys.FromFilename() keys.EnsureKeysExist(overwrite=False) try: version = api_client.GetVersionResource(service=args.service, version=args.version) except api_exceptions.NotFoundError: raise command_exceptions.MissingVersionError('{}/{}'.format( args.service, args.version)) version = version_util.Version.FromVersionResource(version, None) if version.environment is not util.Environment.FLEX: if version.environment is util.Environment.MANAGED_VMS: environment = 'Managed VMs' msg = 'Use `gcloud compute ssh` for Managed VMs instances.' else: environment = 'Standard' msg = None raise command_exceptions.InvalidInstanceTypeError(environment, msg) res = resources.REGISTRY.Parse( args.instance, params={ 'appsId': properties.VALUES.core.project.GetOrFail, 'versionsId': args.version, 'instancesId': args.instance, 'servicesId': args.service, }, collection='appengine.apps.services.versions.instances') rel_name = res.RelativeName() try: instance = api_client.GetInstanceResource(res) except api_exceptions.NotFoundError: raise command_exceptions.MissingInstanceError(rel_name) if not instance.vmDebugEnabled: log.warn(ENABLE_DEBUG_WARNING) console_io.PromptContinue(cancel_on_no=True, throw_if_unattended=True) user = ssh.GetDefaultSshUsername() remote = ssh.Remote(instance.vmIp, user=user) public_key = keys.GetPublicKey().ToEntry() ssh_key = '{user}:{key} {user}'.format(user=user, key=public_key) log.status.Print( 'Sending public key to instance [{}].'.format(rel_name)) api_client.DebugInstance(res, ssh_key) options = { 'IdentitiesOnly': 'yes', # No ssh-agent as of yet 'UserKnownHostsFile': ssh.KnownHosts.DEFAULT_PATH, 'CheckHostIP': 'no', 'HostKeyAlias': HOST_KEY_ALIAS.format(project=api_client.project, instance_id=args.instance) } cmd = ssh.SSHCommand(remote, identity_file=keys.key_file, options=options) if args.container: cmd.tty = True cmd.remote_command = ['container_exec', args.container, '/bin/sh'] return cmd.Run(env)
def Run(self, args): super(Scp, self).Run(args) file_specs = [] # Parses the positional arguments. for arg in args.sources + [args.destination]: if ssh.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.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)) log.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 = 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) # Builds the scp command. scp_args = [self.scp_executable] if not args.plain: scp_args.extend(self.GetDefaultFlags()) host_key_alias = self.HostKeyAlias(instance) scp_args.extend(self.GetHostKeyArgs(args, host_key_alias)) # 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.UserHost(file_spec.user, external_ip_address), file_spec.file_path)) self.ActuallyRun(args, scp_args, user, instance, instance_ref.project)