Esempio n. 1
0
  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)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
  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)
Esempio n. 5
0
    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)
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)