def _do_check_mk_remote_automation_in_background_job_serialized( site_id: SiteId, automation_request: CheckmkAutomationRequest) -> SerializedResult: """Execute the automation in a background job on the remote site It starts the background job using one call. It then polls the remote site, waiting for completion of the job.""" site_config = get_site_config(site_id) job_id = _start_remote_automation_job(site_config, automation_request) auto_logger.info("Waiting for job completion") result = None while True: raw_response = do_remote_automation( site_config, "checkmk-remote-automation-get-status", [ ("request", repr(job_id)), ], ) response = CheckmkAutomationGetStatusResponse(*raw_response) auto_logger.debug("Job status: %r", response) if not response.job_status["is_active"]: result = response.result auto_logger.debug( "Job is not active anymore. Return the result: %s", result) break assert isinstance(result, str) return SerializedResult(result)
def check_mk_remote_automation_serialized( *, site_id: SiteId, command: str, args: Optional[Sequence[str]], indata: Any, stdin_data: Optional[str] = None, timeout: Optional[int] = None, sync: bool = True, non_blocking_http: bool = False, ) -> SerializedResult: site = get_site_config(site_id) if "secret" not in site: raise MKGeneralException( _('Cannot connect to site "%s": The site is not logged in') % site.get("alias", site_id)) if not site.get("replication"): raise MKGeneralException( _('Cannot connect to site "%s": The replication is disabled') % site.get("alias", site_id)) if sync: sync_changes_before_remote_automation(site_id) if non_blocking_http: # This will start a background job process on the remote site to execute the automation # asynchronously. It then polls the remote site, waiting for completion of the job. return _do_check_mk_remote_automation_in_background_job_serialized( site_id, CheckmkAutomationRequest(command, args, indata, stdin_data, timeout)) # Synchronous execution of the actual remote command in a single blocking HTTP request return SerializedResult( _do_remote_automation_serialized( site=get_site_config(site_id), command="checkmk-automation", vars_=[ ("automation", command), # The Checkmk automation command ("arguments", mk_repr(args)), # The arguments for the command ("indata", mk_repr(indata)), # The input data ("stdin_data", mk_repr(stdin_data)), # The input data for stdin ("timeout", mk_repr(timeout)), # The timeout ], ))
def _execute_cmk_automation(self): cmk_command = request.get_str_input_mandatory("automation") args = watolib.mk_eval(request.get_str_input_mandatory("arguments")) indata = watolib.mk_eval(request.get_str_input_mandatory("indata")) stdin_data = watolib.mk_eval( request.get_str_input_mandatory("stdin_data")) timeout = watolib.mk_eval(request.get_str_input_mandatory("timeout")) cmdline_cmd, serialized_result = watolib.check_mk_local_automation_serialized( command=cmk_command, args=args, indata=indata, stdin_data=stdin_data, timeout=timeout, ) # Don't use write_text() here (not needed, because no HTML document is rendered) response.set_data( self._format_cmk_automation_result( serialized_result=SerializedResult(serialized_result), cmk_command=cmk_command, cmdline_cmd=cmdline_cmd, ))
def check_mk_local_automation_serialized( *, command: str, args: Optional[Sequence[str]] = None, indata: Any = "", stdin_data: Optional[str] = None, timeout: Optional[int] = None, ) -> Tuple[Sequence[str], SerializedResult]: if args is None: args = [] new_args = list(args) if stdin_data is None: stdin_data = repr(indata) if timeout: new_args = ["--timeout", "%d" % timeout] + new_args cmd = ["check_mk"] if auto_logger.isEnabledFor(logging.DEBUG): cmd.append("-vv") elif auto_logger.isEnabledFor(VERBOSE): cmd.append("-v") cmd += ["--automation", command] + new_args if command in ["restart", "reload"]: call_hook_pre_activate_changes() # This debug output makes problems when doing bulk inventory, because # it garbles the non-HTML response output # if config.debug: # html.write_text("<div class=message>Running <tt>%s</tt></div>\n" % subprocess.list2cmdline(cmd)) auto_logger.info("RUN: %s" % subprocess.list2cmdline(cmd)) auto_logger.info("STDIN: %r" % stdin_data) try: completed_process = subprocess.run( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, encoding="utf-8", input=stdin_data, check=False, ) except Exception as e: raise local_automation_failure(command=command, cmdline=cmd, exc=e) auto_logger.info("FINISHED: %d" % completed_process.returncode) auto_logger.debug("OUTPUT: %r" % completed_process.stdout) if completed_process.stderr: auto_logger.warning("'%s' returned '%s'" % ( " ".join(cmd), completed_process.stderr, )) if completed_process.returncode: auto_logger.error("Error running %r (exit code %d)" % ( subprocess.list2cmdline(cmd), completed_process.returncode, )) raise local_automation_failure( command=command, cmdline=cmd, code=completed_process.returncode, out=completed_process.stdout, err=completed_process.stderr, ) # On successful "restart" command execute the activate changes hook if command in ["restart", "reload"]: call_hook_activate_changes() return cmd, SerializedResult(completed_process.stdout)