Пример #1
0
    def _run(self, command, timeout, ignore_status, stdout, stderr,
                connect_timeout, env, options, stdin, args):
        """Helper function for run"""
        ssh_cmd = self.ssh_command(connect_timeout, options)
        if not env.strip():
            env = ""
        else:
            env = "export %s;" % env

        for arg in args:
            command += ' "%s"' % utils.sh_escape(arg)

        full_cmd = '%s "%s %s"' % (ssh_cmd, env, utils.sh_escape(command))
        result = utils.run(full_cmd, timeout, True, stdout, stderr,
                            verbose=False, stdin=stdin,
                            stderr_is_expected=ignore_status)
        # the error message will show up in band(indistinguishable from stuff
        # sent through the SSH connection). so we hace the remote computer
        # echo the message "Connected." before running any command.
        if result.exit_status == 255:
            if re.search(r'^ssh: connect to the host .* port .*: '
                         r'Connection timed out\r$', result.stderr):
                raise error.ServSSHTimeour("ssh timed out", result)
            if "Permission Denied." in result.stderr:
                msg = "ssh permission denied"
                raise error.ServSSHPemissionDenidError(msg, result)

        if not ignore_status and result.exit_status > 0:
            raise error.ServRunError("command execution error", result)

        return result
Пример #2
0
    def _run(self, command, timeout, ignore_status, stdout, stderr, connect_timeout,
                env, options, stdin, args):
        """Helper function for run"""
        ssh_cmd = self.ssh_command(connect_timeout, options)
        if not env.strip():
            env = ""
        else:
            env = "export %s;" % env

        for arg in args:
            command += ' "%s"' % utils.sh_escape(arg)

        full_cmd = '%s "%s %s"' % (ssh_cmd, env, utils.sh_escape(command))
        result = utils.run(full_cmd, timeout, True, stdout, stderr, verbose=False,
                            stdin=stdin, stderr_is_expected=ignore_status)  #have no utils.run, need to realize
        # the error message will show up in band(indistinguishable from stuff sent through the
        # SSH connection). so we hace the remote computer echo the message "Connected." before
        # running any command.
        if result.exit_status == 255:
            if re.search(r'^ssh: connect to the host .* port .*: '
                         r'Connection timed out\r$', result.stderr):
                raise error.ServSSHTimeour("ssh timed out", result)
            if "Permission Denied." in result.stderr:
                msg = "ssh permission denied"
                raise error.ServSSHPemissionDenidError(msg, result)

        if not ignore_status and result.exit_status > 0:
            raise error.ServRunError("command execution error", result)

        return result
Пример #3
0
    def run_async(self,
                  command,
                  stdout_tee=None,
                  stderr_tee=None,
                  args=(),
                  connect_timeout=30,
                  options='',
                  verbose=True,
                  stderr_level=utils.DEFAULT_STDERR_LEVEL,
                  cmd_outside_subshell=''):
        """
        Run a command on the remote host. Return an AsyncJob object to
        interact with the remote process.
        """
        if verbose:
            logging.debug("Running (async ssh) '%s'" % command)

        # start a master SSH connection if necessary
        self.start_master_ssh()

        self.send_file(
            os.path.join(self.job.clientdir, "shared", "hosts", "scripts",
                         "run_helper.py"),
            os.path.join(self.job.tmpdir, "run_helper.py"))

        env = " ".join("=".join(pair) for pair in self.env.iteritems())
        ssh_cmd = self.ssh_command(connect_timeout, options)
        if not env.strip():
            env = ""
        else:
            env = "export %s;" % env

        for arg in args:
            command += ' "%s"' % utils.sh_escape(arg)
        full_cmd = '{ssh_cmd} "{env} {cmd}"'.format(
            ssh_cmd=ssh_cmd,
            env=env,
            cmd=utils.sh_escape(
                "%s (%s '%s')" %
                (cmd_outside_subshell,
                 os.path.join(self.job.tmpdir,
                              "run_helper.py"), utils.sh_escape(command))))
        job = utils.AsyncJob(full_cmd,
                             stdout_tee=stdout_tee,
                             stderr_tee=stderr_tee,
                             verbose=verbose,
                             stderr_level=stderr_level,
                             stdin=subprocess.PIPE)

        def kill_func():
            utils.nuke_subprocess(job.sp)

        job.kill_func = kill_func

        return job
Пример #4
0
    def _make_rsync_compatible_globs(self, path, is_local):
        """
        given an rsync-style path, returns a list of globbed paths that will
        hopefully provide equivalent behaviour for scp. Does not support the
        full range of rsync pattern matching behaviour, only that exposed in
        the get/send_file interface.
        """
        if len(path) == 0 or path[-1] != "/":
            return [path]

        if is_local:
            def glob_matches_files(path, pattern):
                return len(glob.glob(path + pattern)) > 0
        else:
            def glob_matches_files(path, pattern):
                result = self.run("ls \"%s\"%s" %
                            (utils.sh_escape(path), pattern),
                            stdout_tee=None, ignore_status=True)
                return result.exit_status == 0
        patterns = ["*", ".[!.]*"]
        patterns = [p for p in patterns if glob_matches_files(path, p)]

        # convert them into a set of paths suitable for the commandline
        if is_local:
            return ["\"%s\"%s" % (utils.sh_escape(path), pattern)
                    for pattern in patterns]
        else:
            return [utils.scp_remote_escape(path) + pattern
                    for pattern in patterns]
Пример #5
0
    def _make_rsync_compatible_globs(self, path, is_local):
        """
        given an rsync-style path, returns a list of globbed paths that will hopefully
        provide equivalent behaviour for scp. Does not support the full range of rsync
        pattern matching behaviour, only that exposed in the get/send_file interface.
        """
        if len(path)==0 or path[-1]!= "/":
            return [path]

        if is_local:
            def glob_matches_files(path, pattern):
                return len(glob.glob(path + pattern)) > 0
        else:
            def glob_matches_files(path, pattern):
                result = self.run("ls \"%s\"%s" % (utils.sh_escape(path), pattern),
                            stdout_tee=None, ignore_status=True)
                return result.exit_status == 0
        patterns = ["*", ".[!.]*"]
        patterns = [p for p in patterns if glob_matches_files(path, p)]

        # convert them into a set of paths suitable for the commandline
        if is_local:
            return ["\"%s\"%s" % (utils.sh_escape(path), pattern) for pattern in patterns]
        else:
            return [utils.scp_remote_escape(path) + pattern for pattern in patterns]
Пример #6
0
    def close():
        super(RemoteHost, self).close()
        self.stop_loggers()

        if hasattr(self, "tmp_dirs"):
            for dir in self.tmp_dirs:
                try:
                    self.run('rm -fr "%s"' % utils.sh_escape(dir))
                except error.AutoError:
                    pass
Пример #7
0
    def close():
        super(RemoteHost, self).close()
        self.stop_loggers()

        if hasattr(self, 'tmp_dirs'):
            for dir in self.tmp_dirs:
                try:
                    self.run('rm -fr "%s"' % utils.sh_escape(dir))
                except error.AutoError:
                    pass
Пример #8
0
    def run_async(self, command, stdout_tee=None, stderr_tee=None, args=(),
                    connect_timeout=30, options='', verbose=True,
                    stderr_level=utils.DEFAULT_STDERR_LEVEL,
                    cmd_outside_subshell=''):
        """
        Run a command on the remote host. Return an AsyncJob object to
        interact with the remote process.
        """
        if verbose:
            logging.debug("Running (async ssh) '%s'" % command)

        # start a master SSH connection if necessary
        self.start_master_ssh()

        self.send_file(os.path.join(self.job.clientdir, "shared", "hosts",
                                        "scripts", "run_helper.py"),
                        os.path.join(self.job.tmpdir, "run_helper.py"))

        env = " ".join("=".join(pair) for pair in self.env.iteritems())
        ssh_cmd = self.ssh_command(connect_timeout, options)
        if not env.strip():
            env = ""
        else:
            env = "export %s;" % env

        for arg in args:
            command += ' "%s"' % utils.sh_escape(arg)
        full_cmd = '{ssh_cmd} "{env} {cmd}"'.format(ssh_cmd=ssh_cmd, env=env,
                cmd=utils.sh_escape("%s (%s '%s')" % (cmd_outside_subshell,
                                os.path.join(self.job.tmpdir, "run_helper.py"),
                                utils.sh_escape(command))))
        job = utils.AsyncJob(full_cmd, stdout_tee=stdout_tee,
                                stderr_tee=stderr_tee, verbose=verbose,
                                stderr_level=stderr_level,
                                stdin=subprocess.PIPE)

        def kill_func():
            utils.nuke_subprocess(job.sp)

        job.kill_func = kill_func

        return job
Пример #9
0
    def get_file(self,
                 source,
                 dest,
                 delete_dest=False,
                 preserve_perm=True,
                 preserve_symlinks=False):
        """
        Copy files from the remote host to a local path
        Directories will be copied recursively.
        Args:
            delete_dest: if it is true, the command will also clear out any
                        old files at dest that are not in the source
            preserve_perm: tells get_file() to try to preserve the sources
                            permissions on files and dirs
            preserve_symlinks: try to preserver symlinks instead of
                            transforming them into files/dirs on copy
        Raiseds:
            the scp command failed
        """
        self.start_master_ssh()
        if isinstance(source, basestring):
            source = [source]
        dest = os.path.abspath(dest)

        try_scp = True
        if try_scp:
            if delete_dest and os.path.isdir(dest):
                shutil.rmtree(dest)
                os.mkdir(dest)

            remote_source = self._make_rsync_compatible_source(source, False)
            if remote_source:
                remote_source = self._encode_remote_paths(remote_source,
                                                          escape=False)
                local_dest = utils.sh_escape(dest)
                scp = self._make_scp_cmd([remote_source], local_dest)
                try:
                    utils.run(scp)
                except error.CmdError, e:
                    raise error.ServeRunError(e.args[0], e.args[1])
Пример #10
0
    def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
                preserve_symlinks=False):
        """
        Copy files from the remote host to a local path
        Directories will be copied recursively.
        Args:
            delete_dest: if it is true, the command will also clear out any
                        old files at dest that are not in the source
            preserve_perm: tells get_file() to try to preserve the sources
                            permissions on files and dirs
            preserve_symlinks: try to preserver symlinks instead of
                            transforming them into files/dirs on copy
        Raiseds:
            the scp command failed
        """
        self.start_master_ssh()
        if isinstance(source, basestring):
            source = [source]
        dest = os.path.abspath(dest)

        try_scp = True
        if try_scp:
            if delete_dest and os.path.isdir(dest):
                shutil.rmtree(dest)
                os.mkdir(dest)

            remote_source = self._make_rsync_compatible_source(source, False)
            if remote_source:
                remote_source = self._encode_remote_paths(remote_source,
                                                escape=False)
                local_dest = utils.sh_escape(dest)
                scp = self._make_scp_cmd([remote_source], local_dest)
                try:
                    utils.run(scp)
                except error.CmdError, e:
                    raise error.ServeRunError(e.args[0], e.args[1])
Пример #11
0
 def _make_ssh_cmd(self, cmd):
     base_cmd = _make_ssh_cmd_default(user=self.user,
                                      port=self.port,
                                      opts=self.master_ssh_option,
                                      hosts_file=self.known_hosts_file)
     return '%s %s "%s"' % (base_cmd, self.hostname, utils.sh_escape(cmd))
Пример #12
0
 def glob_matches_files(path, pattern):
     result = self.run("ls \"%s\"%s" %
                       (utils.sh_escape(path), pattern),
                       stdout_tee=None,
                       ignore_status=True)
     return result.exit_status == 0
Пример #13
0
 def delete_tmp_dir(self, tmpdir):
     """
     delete the given temporary directory on the remote machine
     """
     self.run('rm -fr "%s"' % utils.sh_escape(tmpdir), ignore_status=True)
     self.tmp_dirs.remove(tmpdir)
Пример #14
0
 def delete_tmp_dir(self, tmpdir):
     """
     delete the given temporary directory on the remote machine
     """
     self.run('rm -fr "%s"' % utils.sh_escape(tmpdir), ignore_status=True)
     self.tmp_dirs.remove(tmpdir)
Пример #15
0
 def _make_ssh_cmd(self, cmd):
     base_cmd = _make_ssh_cmd_default(user=self.user, port=self.port,
                                 opts=self.master_ssh_option,
                                 hosts_file=self.known_hosts_file)
     return '%s %s "%s"' % (base_cmd, self.hostname, utils.sh_escape(cmd))
Пример #16
0
 def glob_matches_files(path, pattern):
     result = self.run("ls \"%s\"%s" %
                 (utils.sh_escape(path), pattern),
                 stdout_tee=None, ignore_status=True)
     return result.exit_status == 0