Exemplo n.º 1
0
def diff_cibs_xml(
    runner: CommandRunner, reporter: ReportProcessor, cib_old_xml, cib_new_xml,
):
    """
    Return xml diff of two CIBs

    runner
    reporter
    string cib_old_xml -- original CIB
    string cib_new_xml -- modified CIB
    """
    try:
        cib_old_tmp_file = write_tmpfile(cib_old_xml)
        reporter.report(
            ReportItem.debug(
                reports.messages.TmpFileWrite(
                    cib_old_tmp_file.name, cib_old_xml
                )
            )
        )
        cib_new_tmp_file = write_tmpfile(cib_new_xml)
        reporter.report(
            ReportItem.debug(
                reports.messages.TmpFileWrite(
                    cib_new_tmp_file.name, cib_new_xml
                )
            )
        )
    except EnvironmentError as e:
        raise LibraryError(
            ReportItem.error(reports.messages.CibSaveTmpError(str(e)))
        ) from e
    command = [
        __exec("crm_diff"),
        "--original",
        cib_old_tmp_file.name,
        "--new",
        cib_new_tmp_file.name,
        "--no-version",
    ]
    #  0 (CRM_EX_OK) - success with no difference
    #  1 (CRM_EX_ERROR) - success with difference
    # 64 (CRM_EX_USAGE) - usage error
    # 65 (CRM_EX_DATAERR) - XML fragments not parseable
    stdout, stderr, retval = runner.run(command)
    if retval == 0:
        return ""
    if retval > 1:
        raise LibraryError(
            ReportItem.error(
                reports.messages.CibDiffError(
                    stderr.strip(), cib_old_xml, cib_new_xml
                )
            )
        )
    return stdout.strip()
Exemplo n.º 2
0
Arquivo: env.py Projeto: nrwahl2/pcs
    def cmd_runner(self) -> CommandRunner:
        runner_env = {
            # make sure to get output of external processes in English and ASCII
            "LC_ALL": "C",
        }

        if self.user_login:
            runner_env["CIB_user"] = self.user_login

        if not self.is_cib_live:
            # Dump CIB data to a temporary file and set it up in the runner.
            # This way every called pacemaker tool can access the CIB and we
            # don't need to take care of it every time the runner is called.
            if not self._cib_data_tmp_file:
                try:
                    cib_data = self._cib_data
                    self._cib_data_tmp_file = write_tmpfile(cib_data)
                    self.report_processor.report(
                        ReportItem.debug(
                            reports.messages.TmpFileWrite(
                                self._cib_data_tmp_file.name, cib_data)))
                except EnvironmentError as e:
                    raise LibraryError(
                        ReportItem.error(
                            reports.messages.CibSaveTmpError(str(e))))
            runner_env["CIB_file"] = self._cib_data_tmp_file.name

        return CommandRunner(self.logger, self.report_processor, runner_env)
Exemplo n.º 3
0
 def _log_response_failure(self, response):
     msg = "Unable to connect to {node} ({reason})"
     self._logger.debug(
         msg.format(
             node=response.request.host_label, reason=response.error_msg
         )
     )
     self._reporter.report(
         ReportItem.debug(
             reports.messages.NodeCommunicationNotConnected(
                 response.request.host_label,
                 response.error_msg,
             )
         )
     )
     if is_proxy_set(os.environ):
         self._logger.warning("Proxy is set")
         self._reporter.report(
             ReportItem.warning(
                 reports.messages.NodeCommunicationProxyIsSet(
                     response.request.host_label,
                     response.request.dest.addr,
                 )
             )
         )
Exemplo n.º 4
0
 def log_request_start(self, request):
     msg = "Sending HTTP Request to: {url}"
     if request.data:
         msg += "\n--Debug Input Start--\n{data}\n--Debug Input End--"
     self._logger.debug(msg.format(url=request.url, data=request.data))
     self._reporter.report(
         ReportItem.debug(
             reports.messages.NodeCommunicationStarted(
                 request.url,
                 request.data,
             )))
Exemplo n.º 5
0
 def _log_debug(self, response):
     url = response.request.url
     debug_data = response.debug
     self._logger.debug(
         ("Communication debug info for calling: {url}\n"
          "--Debug Communication Info Start--\n"
          "{data}\n"
          "--Debug Communication Info End--").format(url=url,
                                                     data=debug_data))
     self._reporter.report(
         ReportItem.debug(
             reports.messages.NodeCommunicationDebugInfo(url, debug_data)))
Exemplo n.º 6
0
 def _log_response_successful(self, response):
     url = response.request.url
     msg = (
         "Finished calling: {url}\nResponse Code: {code}" +
         "\n--Debug Response Start--\n{response}\n--Debug Response End--")
     self._logger.debug(
         msg.format(url=url,
                    code=response.response_code,
                    response=response.data))
     self._reporter.report(
         ReportItem.debug(
             reports.messages.NodeCommunicationFinished(
                 url,
                 response.response_code,
                 response.data,
             )))
Exemplo n.º 7
0
    def run(
        self,
        args: Sequence[str],
        stdin_string: Optional[str] = None,
        env_extend: Optional[Mapping[str, str]] = None,
        binary_output: bool = False,
    ) -> Tuple[str, str, int]:
        # Allow overriding default settings. If a piece of code really wants to
        # set own PATH or CIB_file, we must allow it. I.e. it wants to run
        # a pacemaker tool on a CIB in a file but cannot afford the risk of
        # changing the CIB in the file specified by the user.
        env_vars = dict(self._env_vars)
        env_vars.update(dict(env_extend) if env_extend else {})

        log_args = " ".join([shell_quote(x) for x in args])
        self._logger.debug(
            "Running: {args}\nEnvironment:{env_vars}{stdin_string}".format(
                args=log_args,
                stdin_string=("" if not stdin_string else (
                    "\n--Debug Input Start--\n{0}\n--Debug Input End--"
                ).format(stdin_string)),
                env_vars=("" if not env_vars else ("\n" + "\n".join([
                    "  {0}={1}".format(key, val)
                    for key, val in sorted(env_vars.items())
                ]))),
            ))
        self._reporter.report(
            ReportItem.debug(
                reports.messages.RunExternalProcessStarted(
                    log_args,
                    stdin_string,
                    env_vars,
                )))

        try:
            # pylint: disable=subprocess-popen-preexec-fn, consider-using-with
            # this is OK as pcs is only single-threaded application
            process = subprocess.Popen(
                args,
                # Some commands react differently if they get anything via stdin
                stdin=(subprocess.PIPE
                       if stdin_string is not None else subprocess.DEVNULL),
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=(
                    lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)),
                close_fds=True,
                shell=False,
                env=env_vars,
                # decodes newlines and in python3 also converts bytes to str
                universal_newlines=(not binary_output),
            )
            out_std, out_err = process.communicate(stdin_string)
            retval = process.returncode
        except OSError as e:
            raise LibraryError(
                ReportItem.error(
                    reports.messages.RunExternalProcessError(
                        log_args,
                        e.strerror,
                    ))) from e

        self._logger.debug(
            ("Finished running: {args}\nReturn value: {retval}" +
             "\n--Debug Stdout Start--\n{out_std}\n--Debug Stdout End--" +
             "\n--Debug Stderr Start--\n{out_err}\n--Debug Stderr End--"
             ).format(args=log_args,
                      retval=retval,
                      out_std=out_std,
                      out_err=out_err))
        self._reporter.report(
            ReportItem.debug(
                reports.messages.RunExternalProcessFinished(
                    log_args,
                    retval,
                    out_std,
                    out_err,
                )))
        return out_std, out_err, retval