示例#1
0
 def _log_report(self, fd, fd_name, issues, testcase):
     if testcase:
         raise tcfl.tc.error_e(
             "issues found on server's " + fd_name, {
                 "lines": " ".join(issues),
                 "server-" + fd_name: commonl.generator_factory_c(
                     open, fd.name)
             })
     else:
         print("issues found on server's %s: %s" \
             % (fd_name, " ".join(issues)), file=sys.stderr)
         fd.seek(0, 0)
         count = 0
         for line in fd:
             print("  %d: %s" % (count, line), file=sys.stderr, end="")
             count += 1
示例#2
0
    def run(self, cmd, nonzero_e=None):
        """
        Run a shell command over SSH, return exitcode and output

        Similar to :func:`subprocess.call`; note SSH is normally run
        in verbose mode (unless ``-q`` has been set in
        *_ssh_cmdline_options*, so the stderr will contain SSH
        debug information.

        :param str cmd: shell command to execute via SSH, substituting
          any ``%(KEYWORD)[ds]`` field from the target's keywords in
          :attr:`tcfl.tc.target_c.kws`

          See :ref:`how to find
          <finding_testcase_metadata>` which fields are available.

        :param tcfl.tc.exception nonzero_e: exception to raise in case of non
          zero exit code.  Must be a subclass of :class:`tcfl.tc.exception`
          (i.e.: :class:`tcfl.tc.failed_e`,  :class:`tcfl.tc.error_e`,
          :class:`tcfl.tc.skip_e`, :class:`tcfl.tc.blocked_e`) or
          *None* (default) to not raise anything and just return the
          exit code.

        :returns: tuple of ``exitcode, stdout, stderr``, the two later
          being two tempfile file descriptors containing the standard
          output and standard error of running the command.

          The stdout (or stderr) can be read with:

          >>> stdout.read()

        """
        assert nonzero_e == None or issubclass(nonzero_e, tc.exception)
        self._tunnel()
        _cmd = cmd % self.target.kws
        self.target.report_info("running SSH command '%s'" % _cmd, dlevel=1)
        log_stderr = commonl.logfile_open(
            tag="stderr", directory=self.target.testcase.tmpdir)
        log_stdout = commonl.logfile_open(
            tag="stdout", directory=self.target.testcase.tmpdir)
        # We always run check_output to capture the output and
        # display it inthe logs for later analysis
        # if not doing verbose to debug, add -q to avoid getting
        # spurious messages
        if '-v' not in self._ssh_cmdline_options:
            ql = ['-q']
        else:
            ql = []
        env = dict(os.environ)
        if self.password:
            cmdline = ['sshpass', "-e"]
            env['SSHPASS'] = self.password
        else:
            ql += ['-o', "BatchMode yes"]
            cmdline = []
        cmdline += [ "ssh", "-p", str(self._ssh_port) ] \
            + self._ssh_cmdline_options + ql \
            + [ self.login + "@" + self._ssh_host, "-t", _cmd ]
        self.target.report_info("running SSH command: %s" % " ".join(cmdline),
                                dlevel=2)
        self._known_hosts_wipe()
        returncode = subprocess.call(cmdline,
                                     stdin=None,
                                     shell=False,
                                     stdout=log_stdout,
                                     stderr=log_stderr,
                                     env=env,
                                     encoding='utf-8')
        log_stdout.seek(0, 0)
        log_stderr.seek(0, 0)
        if returncode != 0:
            self._returncode_eval(returncode)
            if nonzero_e:
                raise nonzero_e(
                    "failed SSH command '%s': %d" % (cmd, returncode),
                    dict(returncode=returncode,
                         stdout=commonl.generator_factory_c(
                             commonl.file_iterator, log_stdout.name),
                         stderr=commonl.generator_factory_c(
                             commonl.file_iterator, log_stderr.name),
                         ssh_cmd=" ".join(cmdline),
                         cmd=cmd,
                         target=self.target))
        self.target.report_info(
            "ran SSH command '%s': %d" % (_cmd, returncode),
            attachments=dict(
                returncode=returncode,
                stdout=commonl.generator_factory_c(commonl.file_iterator,
                                                   log_stdout.name),
                stderr=commonl.generator_factory_c(commonl.file_iterator,
                                                   log_stderr.name),
                ssh_cmd=" ".join(cmdline),
                cmd=cmd,
                target=self.target))
        log_stdout.seek(0, 0)
        log_stderr.seek(0, 0)
        return returncode, log_stdout, log_stderr