diff --git a/common/ssh_client/local_client.py b/common/ssh_client/local_client.py index 00e03e3e..71e55b6d 100644 --- a/common/ssh_client/local_client.py +++ b/common/ssh_client/local_client.py @@ -78,4 +78,4 @@ def get_name(self): return "local" def get_ip(self): - return self.client.get_ip() + return "127.0.0.1" diff --git a/common/ssh_client/remote_client.py b/common/ssh_client/remote_client.py index 537eebdc..cddea08d 100644 --- a/common/ssh_client/remote_client.py +++ b/common/ssh_client/remote_client.py @@ -151,3 +151,6 @@ def ssh_invoke_shell_switch_user(self, new_user, cmd, time_out): def get_name(self): return "remote_{0}".format(self.host_ip) + + def get_ip(self): + return self.host_ip diff --git a/common/ssh_client/ssh.py b/common/ssh_client/ssh.py index 8333039a..69486cdc 100644 --- a/common/ssh_client/ssh.py +++ b/common/ssh_client/ssh.py @@ -84,6 +84,7 @@ def exec_cmd(self, cmd): return self.client.exec_cmd(cmd).strip() def download(self, remote_path, local_path): + self.stdio.verbose("download file: {} to {}".format(remote_path, local_path)) return self.client.download(remote_path, local_path) def upload(self, remote_path, local_path): diff --git a/common/tool.py b/common/tool.py index aa12d4a2..4a8db907 100644 --- a/common/tool.py +++ b/common/tool.py @@ -31,6 +31,7 @@ import json import hashlib import datetime +import uuid import tabulate import tarfile import socket @@ -660,7 +661,7 @@ def write_append(filename, result, stdio=None): fileobj.write(u'{}'.format(result)) def tar_gz_to_zip(temp_dir, tar_gz_file, output_zip, password, stdio): - extract_dir = os.path.join(temp_dir, 'extracted_files') + extract_dir = os.path.join(temp_dir, 'extracted_files_{0}'.format(str(uuid.uuid4())[:6])) try: # 1. Extract the tar.gz file @@ -701,11 +702,6 @@ def tar_gz_to_zip(temp_dir, tar_gz_file, output_zip, password, stdio): if os.path.exists(extract_dir): shutil.rmtree(extract_dir) return False - except pyminizip.compress_error as ce: - stdio.exception("compression error: {0}".format(ce)) - if os.path.exists(extract_dir): - shutil.rmtree(extract_dir) - return False except Exception as e: stdio.exception("an error occurred: {0}".format(e)) if os.path.exists(extract_dir): diff --git a/core.py b/core.py index 902fd089..5fc52d72 100644 --- a/core.py +++ b/core.py @@ -24,6 +24,7 @@ from common.ssh_client.remote_client import dis_rsa_algorithms from handler.gather.gather_ash_report import GatherAshReportHandler +from handler.gather.gather_component_log import GatherComponentLogHandler from handler.rca.rca_handler import RCAHandler from handler.rca.rca_list import RcaScenesListHandler from common.ssh import SshClient, SshConfig @@ -39,9 +40,7 @@ from handler.analyzer.analyze_index_space import AnalyzeIndexSpaceHandler from handler.checker.check_handler import CheckHandler from handler.checker.check_list import CheckListHandler -from handler.gather.gather_log import GatherLogHandler from handler.gather.gather_awr import GatherAwrHandler -from handler.gather.gather_obproxy_log import GatherObProxyLogHandler from handler.gather.gather_sysstat import GatherOsInfoHandler from handler.gather.gather_obstack2 import GatherObstack2Handler from handler.gather.gather_obadmin import GatherObAdminHandler @@ -245,10 +244,24 @@ def gather_function(self, function_type, opt): self.stdio.print("{0} start ...".format(function_type)) self.update_obcluster_nodes(config) self.set_context(function_type, 'gather', config) + options = self.context.options timestamp = TimeUtils.get_current_us_timestamp() self.context.set_variable('gather_timestamp', timestamp) if function_type == 'gather_log': - handler = GatherLogHandler(self.context) + handler = GatherComponentLogHandler() + handler.init( + self.context, + target="observer", + from_option=Util.get_option(options, 'from'), + to_option=Util.get_option(options, 'to'), + since=Util.get_option(options, 'since'), + scope=Util.get_option(options, 'scope'), + grep=Util.get_option(options, 'grep'), + encrypt=Util.get_option(options, 'encrypt'), + store_dir=Util.get_option(options, 'store_dir'), + temp_dir=Util.get_option(options, 'temp_dir'), + redact=Util.get_option(options, 'redact'), + ) return handler.handle() elif function_type == 'gather_awr': handler = GatherAwrHandler(self.context) @@ -277,9 +290,35 @@ def gather_function(self, function_type, opt): handler_stack.handle() handler_perf = GatherPerfHandler(self.context) handler_perf.handle() - handler_log = GatherLogHandler(self.context) - handler_log.handle() - handler_obproxy = GatherObProxyLogHandler(self.context) + handler_observer_log = GatherComponentLogHandler() + handler_observer_log.init( + self.context, + target="observer", + from_option=Util.get_option(options, 'from'), + to_option=Util.get_option(options, 'to'), + since=Util.get_option(options, 'since'), + scope=Util.get_option(options, 'scope'), + grep=Util.get_option(options, 'grep'), + encrypt=Util.get_option(options, 'encrypt'), + store_dir=Util.get_option(options, 'store_dir'), + temp_dir=Util.get_option(options, 'temp_dir'), + redact=Util.get_option(options, 'redact'), + ) + handler_observer_log.handle() + handler_obproxy = GatherComponentLogHandler() + handler_obproxy.init( + self.context, + target="obproxy", + from_option=Util.get_option(options, 'from'), + to_option=Util.get_option(options, 'to'), + since=Util.get_option(options, 'since'), + scope=Util.get_option(options, 'scope'), + grep=Util.get_option(options, 'grep'), + encrypt=Util.get_option(options, 'encrypt'), + store_dir=Util.get_option(options, 'store_dir'), + temp_dir=Util.get_option(options, 'temp_dir'), + redact=Util.get_option(options, 'redact'), + ) return handler_obproxy.handle() elif function_type == 'gather_sysstat': handler = GatherOsInfoHandler(self.context) @@ -310,7 +349,21 @@ def gather_obproxy_log(self, opt): return ObdiagResult(ObdiagResult.INPUT_ERROR_CODE, error_data='No such custum config') else: self.set_context_skip_cluster_conn('gather_obproxy_log', 'gather', config) - handler = GatherObProxyLogHandler(self.context) + options = self.context.options + handler = GatherComponentLogHandler() + handler.init( + self.context, + target="obproxy", + from_option=Util.get_option(options, 'from'), + to_option=Util.get_option(options, 'to'), + since=Util.get_option(options, 'since'), + scope=Util.get_option(options, 'scope'), + grep=Util.get_option(options, 'grep'), + encrypt=Util.get_option(options, 'encrypt'), + store_dir=Util.get_option(options, 'store_dir'), + temp_dir=Util.get_option(options, 'temp_dir'), + redact=Util.get_option(options, 'redact'), + ) return handler.handle() def gather_scenes_list(self, opt): @@ -401,31 +454,34 @@ def check(self, opts): self._call_stdio('error', 'No such custum config') return ObdiagResult(ObdiagResult.INPUT_ERROR_CODE, error_data='No such custum config') else: - self.stdio.print("check start ...") - self.update_obcluster_nodes(config) - self.set_context('check', 'check', config) - obproxy_check_handler = None - observer_check_handler = None - result_data = {} - if self.context.obproxy_config.get("servers") is not None and len(self.context.obproxy_config.get("servers")) > 0: - obproxy_check_handler = CheckHandler(self.context, check_target_type="obproxy") - obproxy_check_handler.handle() - obproxy_result = obproxy_check_handler.execute() - result_data['obproxy'] = obproxy_result - if self.context.cluster_config.get("servers") is not None and len(self.context.cluster_config.get("servers")) > 0: - observer_check_handler = CheckHandler(self.context, check_target_type="observer") - observer_check_handler.handle() - observer_result = observer_check_handler.execute() - result_data['observer'] = observer_result - if obproxy_check_handler is not None: - obproxy_report_path = os.path.expanduser(obproxy_check_handler.report.get_report_path()) - if os.path.exists(obproxy_report_path): - self.stdio.print("Check obproxy finished. For more details, please run cmd '" + Fore.YELLOW + " cat {0} ".format(obproxy_check_handler.report.get_report_path()) + Style.RESET_ALL + "'") - if observer_check_handler is not None: - observer_report_path = os.path.expanduser(observer_check_handler.report.get_report_path()) - if os.path.exists(observer_report_path): - self.stdio.print("Check observer finished. For more details, please run cmd'" + Fore.YELLOW + " cat {0} ".format(observer_check_handler.report.get_report_path()) + Style.RESET_ALL + "'") - return ObdiagResult(ObdiagResult.SUCCESS_CODE, data=result_data) + try: + self.stdio.print("check start ...") + self.update_obcluster_nodes(config) + self.set_context('check', 'check', config) + obproxy_check_handler = None + observer_check_handler = None + result_data = {} + if self.context.obproxy_config.get("servers") is not None and len(self.context.obproxy_config.get("servers")) > 0: + obproxy_check_handler = CheckHandler(self.context, check_target_type="obproxy") + obproxy_result = obproxy_check_handler.handle() + result_data['obproxy'] = obproxy_result + if self.context.cluster_config.get("servers") is not None and len(self.context.cluster_config.get("servers")) > 0: + observer_check_handler = CheckHandler(self.context, check_target_type="observer") + observer_result = observer_check_handler.handle() + result_data['observer'] = observer_result + if obproxy_check_handler is not None: + obproxy_report_path = os.path.expanduser(obproxy_check_handler.report.get_report_path()) + if os.path.exists(obproxy_report_path): + self.stdio.print("Check obproxy finished. For more details, please run cmd '" + Fore.YELLOW + " cat {0} ".format(obproxy_check_handler.report.get_report_path()) + Style.RESET_ALL + "'") + if observer_check_handler is not None: + observer_report_path = os.path.expanduser(observer_check_handler.report.get_report_path()) + if os.path.exists(observer_report_path): + self.stdio.print("Check observer finished. For more details, please run cmd'" + Fore.YELLOW + " cat {0} ".format(observer_check_handler.report.get_report_path()) + Style.RESET_ALL + "'") + return ObdiagResult(ObdiagResult.SUCCESS_CODE, data=result_data) + except Exception as e: + self.stdio.error("check Exception: {0}".format(e)) + self.stdio.verbose(traceback.format_exc()) + return ObdiagResult(ObdiagResult.SERVER_ERROR_CODE, error_data="check Exception: {0}".format(e)) def check_list(self, opts): config = self.config_manager diff --git a/handler/checker/check_handler.py b/handler/checker/check_handler.py index 9fcd3d04..aced1a8e 100644 --- a/handler/checker/check_handler.py +++ b/handler/checker/check_handler.py @@ -30,7 +30,6 @@ from handler.checker.check_task import TaskBase import re from common.tool import Util -from common.tool import YamlUtils from common.tool import StringUtils @@ -171,11 +170,11 @@ def handle(self): new_tasks[task_name] = task_value self.tasks = new_tasks self.stdio.verbose("tasks is {0}".format(self.tasks.keys())) - return True + return self.__execute() except Exception as e: self.stdio.error("Get package tasks failed. Error info is {0}".format(e)) self.stdio.verbose(traceback.format_exc()) - return False + raise CheckException("Internal error :{0}".format(e)) # get all tasks def get_all_tasks(self): @@ -213,7 +212,7 @@ def get_package_tasks(self, package_name): return packege_tasks[package_name].get("tasks") # execute task - def execute_one(self, task_name): + def __execute_one(self, task_name): try: self.stdio.verbose("execute tasks is {0}".format(task_name)) # Verify if the version is within a reasonable range @@ -236,22 +235,21 @@ def execute_one(self, task_name): self.stdio.error("execute_one Exception : {0}".format(e)) raise CheckException("execute_one Exception : {0}".format(e)) - def execute(self): + def __execute(self): try: self.stdio.verbose("execute_all_tasks. the number of tasks is {0} ,tasks is {1}".format(len(self.tasks.keys()), self.tasks.keys())) self.report = CheckReport(self.context, export_report_path=self.export_report_path, export_report_type=self.export_report_type, report_target=self.check_target_type) # one of tasks to execute for task in self.tasks: - t_report = self.execute_one(task) + t_report = self.__execute_one(task) self.report.add_task_report(t_report) self.report.export_report() return self.report.report_tobeMap() except CheckrReportException as e: self.stdio.error("Report error :{0}".format(e)) - self.stdio.verbose(traceback.format_exc()) + raise CheckException("Report error :{0}".format(e)) except Exception as e: - self.stdio.error("Internal error :{0}".format(e)) - self.stdio.verbose(traceback.format_exc()) + raise CheckException("Internal error :{0}".format(e)) class checkOBConnectorPool: diff --git a/handler/checker/check_list.py b/handler/checker/check_list.py index 8a5d6451..fc016939 100644 --- a/handler/checker/check_list.py +++ b/handler/checker/check_list.py @@ -82,4 +82,5 @@ def handle(self): Util.print_scene(cases_map, stdio=self.stdio) return ObdiagResult(ObdiagResult.SUCCESS_CODE, data=result_map) except Exception as e: + return ObdiagResult(ObdiagResult.SERVER_ERROR_CODE, error_data=str(e)) diff --git a/handler/gather/gather_component_log.py b/handler/gather/gather_component_log.py new file mode 100644 index 00000000..a662837d --- /dev/null +++ b/handler/gather/gather_component_log.py @@ -0,0 +1,487 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -* +# Copyright (c) 2022 OceanBase +# OceanBase Diagnostic Tool is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +import datetime +import os +import traceback +import uuid +import multiprocessing as mp + +from prettytable import PrettyTable +from common.command import get_file_start_time, get_file_size, is_empty_dir +from common.constant import const +from common.ssh_client.ssh import SshClient +from common.tool import FileUtil, TimeUtils, Util +from handler.base_shell_handler import BaseShellHandler +from handler.gather.plugins.redact import Redact +from result_type import ObdiagResult + + +class GatherComponentLogHandler(BaseShellHandler): + # log_scope_list + log_scope_list = {"observer": ["observer", "rootservice", "election"], "obproxy": ["obproxy", "obproxy_digest", "obproxy_stat", "obproxy_slow", "obproxy_limit"], "oms": ["connector", "error"]} + + def __init__(self, *args, **kwargs): + super().__init__() + self.oms_module_id = None + self.redact_dir = None + self.gather_log_conf_dict = None + self.thread_nums = None + self.oms_log_path = None + self.is_scene = None + self.inner_config = None + self.stdio = None + self.context = None + self.target = None + self.from_option = None + self.to_option = None + self.since_option = None + self.scope = None + self.grep = None + self.encrypt = None + self.store_dir = None + self.temp_dir = None + self.redact = None + self.nodes = None + self.zip_password = None + self.result = ObdiagResult(ObdiagResult.SUCCESS_CODE, data={}) + + def init(self, context, *args, **kwargs): + try: + self.context = context + self.stdio = self.context.stdio + self.inner_config = self.context.inner_config + self.target = kwargs.get('target', None) + self.from_option = kwargs.get('from_option', None) + self.to_option = kwargs.get('to_option', None) + self.since_option = kwargs.get('since', None) + self.scope = kwargs.get('scope', None) + self.grep = kwargs.get('grep', None) + self.encrypt = kwargs.get('encrypt', None) + self.store_dir = kwargs.get('store_dir', None) + self.temp_dir = kwargs.get('temp_dir', None) + self.redact = kwargs.get('redact', None) + self.nodes = kwargs.get('nodes', None) + self.is_scene = kwargs.get('is_scene', False) + self.oms_log_path = kwargs.get('oms_log_path', None) + self.thread_nums = kwargs.get('thread_nums', 3) + self.oms_module_id = kwargs.get('oms_module_id', None) + self.__check_option() + if self.oms_module_id: + self.gather_log_conf_dict["oms_module_id"] = self.oms_module_id + # build config dict for gather log on node + self.gather_log_conf_dict = { + "target": self.target, + "tmp_dir": const.GATHER_LOG_TEMPORARY_DIR_DEFAULT, + "zip_password": self.zip_password, + "scope": self.scope, + "grep": self.grep, + "encrypt": self.encrypt, + "store_dir": self.store_dir, + "from_time": self.from_time_str, + "to_time": self.to_time_str, + "file_number_limit": self.file_number_limit, + "file_size_limit": self.file_size_limit, + "oms_module_id": self.oms_module_id, + } + + except Exception as e: + self.stdio.error("init GatherComponentLogHandler failed, error: {0}".format(str(e))) + self.result = ObdiagResult(ObdiagResult.INPUT_ERROR_CODE, error_data="init GatherComponentLogHandler failed, error: {0}".format(str(e))) + + def __check_option(self): + # target check + if self.target is None or self.target == "": + self.target = 'observer' + else: + self.target = self.target.lower().strip() + if not isinstance(self.target, str): + raise Exception("target option can only be string") + self.target = self.target.lower().strip() + if self.target != 'observer' and self.target != 'obproxy' and self.target != 'oms': + raise Exception("target option can only be observer or obproxy or oms") + + # check store_dir + if not os.path.exists(self.store_dir): + raise Exception("store_dir: {0} is not exist".format(self.store_dir)) + if self.is_scene is False: + target_dir = os.path.join("obdiag_gather_pack_{0}".format(TimeUtils.timestamp_to_filename_time(TimeUtils.get_current_us_timestamp()))) + self.store_dir = os.path.join(self.store_dir or "./", target_dir) + if not os.path.exists(self.store_dir): + os.makedirs(self.store_dir) + self.stdio.verbose("store_dir rebase: {0}".format(self.store_dir)) + + # check nodes + if self.nodes is None or len(self.nodes) == 0: + # if self.nodes not input, use default nodes by self.target + if self.target == 'observer': + self.nodes = self.context.cluster_config.get("servers") + elif self.target == 'obproxy': + self.nodes = self.context.obproxy_config.get("servers") + elif self.target == 'oms': + self.nodes = self.context.oms_config.get("servers") + else: + raise Exception("can not get nodes by target: {0}".format(self.target)) + if len(self.nodes) == 0: + raise Exception("can not get nodes by target: {0}, nodes's len is 0.".format(self.target)) + # check scope + if self.scope is None or self.scope == "" or self.scope == "all": + self.scope = "all" + self.scope = self.log_scope_list[self.target] + else: + self.scope = self.scope.strip() + if self.scope not in self.log_scope_list[self.target]: + raise Exception("scope option can only be {0},the {1} just support {2}".format(self.scope, self.target, self.log_scope_list)) + # check since from_option and to_option + from_timestamp = None + to_timestamp = None + if self.from_option is not None and self.to_option is not None: + try: + from_timestamp = TimeUtils.parse_time_str(self.from_option) + to_timestamp = TimeUtils.parse_time_str(self.to_option) + self.from_time_str = self.from_option + self.to_time_str = self.to_option + except Exception as e: + raise Exception('Error: Datetime is invalid. Must be in format "yyyy-mm-dd hh:mm:ss". from_datetime={0}, to_datetime={1}'.format(self.from_option, self.to_option)) + if to_timestamp <= from_timestamp: + raise Exception('Error: from datetime is larger than to datetime, please check.') + elif (self.from_option is None or self.to_option is None) and self.since_option is not None: + now_time = datetime.datetime.now() + self.to_time_str = (now_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + self.from_time_str = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_length_to_sec(self.since_option))).strftime('%Y-%m-%d %H:%M:%S') + self.stdio.print('gather log from_time: {0}, to_time: {1}'.format(self.from_time_str, self.to_time_str)) + else: + self.stdio.print('No time option provided, default processing is based on the last 30 minutes') + now_time = datetime.datetime.now() + self.to_time_str = (now_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + if self.since_option: + self.from_time_str = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_length_to_sec(self.since_option))).strftime('%Y-%m-%d %H:%M:%S') + else: + self.from_time_str = (now_time - datetime.timedelta(minutes=30)).strftime('%Y-%m-%d %H:%M:%S') + self.stdio.print('gather log from_time: {0}, to_time: {1}'.format(self.from_time_str, self.to_time_str)) + # check encrypt + if self.encrypt: + if self.encrypt.strip().upper() == "TRUE": + self.encrypt = True + self.zip_password = Util.gen_password(16) + self.stdio.verbose("zip_encrypt is True, zip_password is {0}".format(self.zip_password)) + # check redact + if self.redact: + if self.redact != "" and len(self.redact) != 0: + if "," in self.redact and isinstance(self.redact, str): + self.redact = self.redact.split(",") + else: + self.redact = [self.redact] + + # check inner_config + if self.inner_config is None: + self.file_number_limit = 20 + self.file_size_limit = 2 * 1024 * 1024 * 1024 + else: + basic_config = self.inner_config['obdiag']['basic'] + self.file_number_limit = int(basic_config["file_number_limit"]) + self.file_size_limit = int(FileUtil.size(basic_config["file_size_limit"])) + self.config_path = basic_config['config_path'] + self.stdio.verbose("file_number_limit: {0}, file_size_limit: {1}, gather log config_path: {2}".format(self.file_number_limit, self.file_size_limit, self.config_path)) + + # check thread_nums + if self.thread_nums is None or not isinstance(self.thread_nums, int) or self.thread_nums <= 0: + self.thread_nums = int(self.context.inner_config.get("obdiag", {}).get("gather", {}).get("thread_nums") or 3) + self.stdio.verbose("thread_nums: {0}".format(self.thread_nums)) + + def handle(self): + try: + if not self.result.is_success(): + return self.result + + # run on every node + node_threads = [] + gather_tuples = [] + tasks = [] + self.stdio.start_loading("gather start") + semaphore = mp.Semaphore(self.thread_nums) + for node in self.nodes: + new_context = self.context + new_context.stdio = self.stdio.sub_io() + tasks.append(GatherLogOnNode(new_context, node, self.gather_log_conf_dict, semaphore)) + file_queue = [] + for task in tasks: + semaphore.acquire() + file_thread = mp.Process(target=task.handle()) + file_thread.start() + file_queue.append(file_thread) + for file_thread in file_queue: + file_thread.join() + for task in tasks: + gather_tuple = task.get_result() + gather_tuples.append(gather_tuple) + self.stdio.verbose("gather_tuples: {0}".format(gather_tuples)) + self.stdio.stop_loading("succeed") + # save result + summary_tuples = self.__get_overall_summary(gather_tuples) + self.stdio.print(summary_tuples) + with open(os.path.join(self.store_dir, "result_details.txt"), 'a', encoding='utf-8') as fileobj: + fileobj.write(summary_tuples.get_string()) + self.stdio.stop_loading("succeed") + + last_info = "For result details, please run cmd \033[32m' cat {0} '\033[0m\n".format(os.path.join(self.store_dir, "result_summary.txt")) + self.stdio.print(last_info) + if self.zip_password: + self.stdio.print("zip password is {0}".format(self.zip_password)) + try: + if self.redact and len(self.redact) > 0: + self.stdio.start_loading("gather redact start") + self.stdio.verbose("redact_option is {0}".format(self.redact)) + redact_dir = "{0}_redact".format(self.store_dir) + self.redact_dir = redact_dir + redact = Redact(self.context, self.store_dir, redact_dir, zip_password=self.zip_password) + redact.redact_files(self.redact) + self.stdio.print("redact success the log save on {0}".format(self.redact_dir)) + self.stdio.stop_loading("succeed") + return ObdiagResult(ObdiagResult.SUCCESS_CODE, data={"store_dir": redact_dir, "redact_dir": self.redact_dir}) + except Exception as e: + self.stdio.verbose(traceback.format_exc()) + self.stdio.error("redact failed {0}".format(e)) + return ObdiagResult(ObdiagResult.SERVER_ERROR_CODE, error_data="redact failed {0}".format(e)) + return ObdiagResult(ObdiagResult.SUCCESS_CODE, data={"store_dir": self.store_dir}) + except Exception as e: + self.stdio.verbose(traceback.format_exc()) + self.stdio.error("gather log failed: {0}".format(str(e))) + return ObdiagResult(ObdiagResult.SERVER_ERROR_CODE, error_data="gather log failed: {0}".format(str(e))) + + def __get_overall_summary(self, node_summary_tuple): + """ + generate overall summary from all node summary tuples + :param node_summary_tuple: (node, is_err, err_msg, size, consume_time, node_summary) for each node + :return: a string indicating the overall summary + """ + summary_tb = PrettyTable() + summary_tb.title = "{0} Gather Ob Log Summary on {1}".format(self.target, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.stdio.verbose("node_summary_tuple: {0}".format(node_summary_tuple)) + if self.zip_password: + summary_tb.field_names = ["Node", "Status", "Size", "info", "zip_password"] + else: + summary_tb.field_names = ["Node", "Status", "Size", "info"] + try: + for tup in node_summary_tuple: + if self.zip_password: + summary_tb.add_row([tup["node"], tup["success"], tup["file_size"], tup["info"], self.zip_password]) + else: + summary_tb.add_row([tup["node"], tup["success"], tup["file_size"], tup["info"]]) + except Exception as e: + self.stdio.error("gather log __get_overall_summary failed: {0}".format(str(e))) + return summary_tb + + +class GatherLogOnNode: + def __init__(self, context, node, config, semaphore): + self.context = context + self.ssh_client = SshClient(context, node) + self.stdio = context.stdio + self.config = config + self.node = node + self.target = self.config.get("target") + self.semaphore = semaphore + + # mkdir tmp_dir + self.tmp_dir = self.config.get("tmp_dir") + self.tmp_dir = os.path.join(self.tmp_dir, "obdiag_gather_{0}".format(str(uuid.uuid4()))) + self.ssh_client.exec_cmd("mkdir -p {0}".format(self.tmp_dir)) + + self.scope = self.config.get("scope") + # todo log_path for oms + self.oms_module_id = self.config.get("oms_module_id") + if self.target == "oms": + if self.oms_module_id is None: + raise Exception("gather log on oms, but oms_module_id is None") + self.log_path = os.path.join(node.get("run_path"), self.oms_module_id, "logs") + else: + self.log_path = os.path.join(node.get("home_path"), "log") + + self.from_time_str = self.config.get("from_time") + self.to_time_str = self.config.get("to_time") + self.grep_option = self.config.get("grep_option") + self.store_dir = self.config.get("store_dir") + self.zip_password = self.config.get("zip_password") or None + # + self.file_number_limit = self.config.get("file_number_limit") + self.file_size_limit = self.config.get("file_size_limit") + self.gather_tuple = { + "node": self.ssh_client.get_name(), + "success": "Fail", + "info": "", + "file_size": 0, + } + + def get_result(self): + return self.gather_tuple + + def handle(self): + + from_datetime_timestamp = TimeUtils.timestamp_to_filename_time(TimeUtils.datetime_to_timestamp(self.from_time_str)) + to_datetime_timestamp = TimeUtils.timestamp_to_filename_time(TimeUtils.datetime_to_timestamp(self.to_time_str)) + + tmp_log_dir = os.path.join(self.tmp_dir, "{4}_log_{0}_{1}_{2}_{3}".format(self.ssh_client.get_name(), from_datetime_timestamp, to_datetime_timestamp, str(uuid.uuid4())[:6], self.target)) + # mkdir tmp_log_dir + self.ssh_client.exec_cmd("mkdir -p {0}".format(tmp_log_dir)) + self.stdio.verbose("gather_log_on_node {0} tmp_log_dir: {1}".format(self.ssh_client.get_ip(), tmp_log_dir)) + try: + # find logs + logs_name = self.__find_logs_name() + if logs_name is None or len(logs_name) == 0: + self.stdio.error("gather_log_on_node {0} failed: no log found".format(self.ssh_client.get_ip())) + self.gather_tuple["info"] = "no log found" + return + elif len(logs_name) > self.file_number_limit: + self.stdio.error('{0} The number of log files is {1}, out of range (0,{2}], ' "Please adjust the query limit".format(self.ssh_client.get_name(), len(logs_name), self.file_number_limit)) + self.gather_tuple["info"] = "too many files {0} > {1}".format(len(logs_name), self.file_number_limit) + return + + # gather log to remote tmp_dir ,if grep is exit, with grep + self.__grep_log_to_tmp(logs_name, tmp_log_dir) + + # build tar file + if is_empty_dir(self.ssh_client, tmp_log_dir, self.stdio): + # if remote tmp_log_dir is empty, rm the dir and return + self.ssh_client.exec_cmd("rm -rf {0}".format(tmp_log_dir)) + self.stdio.error("gather_log_on_node {0} failed: tmp_log_dir({1}) no log found".format(self.ssh_client.get_name(), tmp_log_dir)) + self.gather_tuple["info"] = "tmp_log_dir({0}) no log found".format(tmp_log_dir) + return + + tar_file = os.path.join(self.tmp_dir, "{0}.tar.gz".format(tmp_log_dir)) + tar_cmd = "cd {0} && tar -czf {1}.tar.gz {1}/*".format(self.tmp_dir, tmp_log_dir) + self.stdio.verbose("gather_log_on_node {0} tar_cmd: {1}".format(self.ssh_client.get_ip(), tar_cmd)) + self.ssh_client.exec_cmd(tar_cmd) + + # download log to local store_dir + tar_file_size = int(get_file_size(self.ssh_client, tar_file)) + if tar_file_size > self.file_size_limit: + self.stdio.error("gather_log_on_node {0} failed: File too large over gather.file_size_limit".format(self.ssh_client.get_ip())) + self.gather_tuple["info"] = "File too large over gather.file_size_limit" + return + else: + self.stdio.verbose("gather_log_on_node {0} download log to local store_dir: {1}".format(self.ssh_client.get_ip(), self.store_dir)) + self.ssh_client.download(tar_file, os.path.join(self.store_dir, os.path.basename("{0}".format(tar_file)))) + # tar to zip + tar_file_name = os.path.basename("{0}".format(tar_file)) + self.stdio.verbose("tar_file_name: {0}".format(tar_file_name)) + local_tar_file_path = os.path.join(self.store_dir, tar_file_name) + local_zip_store_path = os.path.join(self.store_dir, os.path.basename("{0}.zip".format(tmp_log_dir))) + self.stdio.verbose("local_tar_file_path: {0}; local_zip_store_path: {1}".format(local_tar_file_path, local_zip_store_path)) + FileUtil.tar_gz_to_zip(self.store_dir, local_tar_file_path, local_zip_store_path, self.zip_password, self.stdio) + self.gather_tuple["file_size"] = FileUtil.size_format(num=int(os.path.getsize(local_zip_store_path) or 0), output_str=True) + self.gather_tuple["info"] = "file save in {0}".format(local_zip_store_path) + self.gather_tuple["success"] = "Success" + except Exception as e: + self.stdio.verbose(traceback.format_exc()) + self.stdio.error("gather_log_on_node {0} failed: {1}".format(self.ssh_client.get_ip(), str(e))) + self.gather_tuple["info"] = str(e) + finally: + self.stdio.verbose("clear tmp_log_dir: {0}".format(tmp_log_dir)) + self.ssh_client.exec_cmd("rm -rf {0}".format(tmp_log_dir)) + self.stdio.verbose("gather_log_on_node {0} finished".format(self.ssh_client.get_ip())) + self.semaphore.release() + + def __grep_log_to_tmp(self, logs_name, tmp_log_dir): + grep_cmd = "" + if self.grep_option: + self.stdio.verbose("grep files, grep_option = [{0}]".format(self.grep_option)) + for grep_option in self.grep_option: + if grep_cmd == "": + grep_cmd = "grep -e '{0}' ".format(grep_option) + grep_cmd += "| grep -e '{0}'".format(grep_option) + for log_name in logs_name: + source_log_name = "{0}/{1}".format(self.log_path, log_name) + target_log_name = "{0}/{1}".format(tmp_log_dir, log_name) + self.stdio.verbose("grep files, source_log_name = [{0}], target_log_name = [{1}]".format(source_log_name, target_log_name)) + if log_name.endswith(".gz"): + log_grep_cmd = "cp {0} {1}".format(source_log_name, target_log_name) + self.stdio.verbose("grep files, run cmd = [{0}]".format(log_grep_cmd)) + self.ssh_client.exec_cmd(log_grep_cmd) + continue + log_grep_cmd = "" + if grep_cmd == "": + log_grep_cmd = "cp {0} {1}".format(source_log_name, target_log_name) + else: + log_grep_cmd = grep_cmd + " {0}".format(source_log_name) + log_grep_cmd += " > {0} ".format(target_log_name) + self.stdio.verbose("grep files, run cmd = [{0}]".format(log_grep_cmd)) + self.ssh_client.exec_cmd(log_grep_cmd) + + def __find_logs_name(self): + try: + logs_scope = "" + for scope in self.scope: + if logs_scope == "": + logs_scope = scope + continue + logs_scope = logs_scope + "|" + scope + self.stdio.verbose("gather_log_on_node {0} find logs scope: {1}".format(self.ssh_client.get_ip(), logs_scope)) + + find_cmd = "ls -1 -F {0} |grep -E '{1}'| awk -F '/' ".format(self.log_path, logs_scope) + "'{print $NF}'" + self.stdio.verbose("gather_log_on_node {0} find logs cmd: {1}".format(self.ssh_client.get_ip(), find_cmd)) + logs_name = self.ssh_client.exec_cmd(find_cmd) + if logs_name is not None and len(logs_name) != 0: + log_name_list = self.__get_logfile_name_list(self.from_time_str, self.to_time_str, self.log_path, logs_name) + return log_name_list + else: + self.stdio.warn("gather_log_on_node {0} failed: no log found".format(self.ssh_client.get_ip())) + return [] + except Exception as e: + raise Exception("gather_log_on_node {0} find logs failed: {1}".format(self.ssh_client.get_ip(), str(e))) + + def __get_logfile_name_list(self, from_time_str, to_time_str, log_dir, log_files): + # TODO oms get all log file name list + if self.target == "oms": + return log_files + self.stdio.verbose("get log file name list, from time {0}, to time {1}, log dir {2}, log files {3}".format(from_time_str, to_time_str, log_dir, log_files)) + log_name_list = [] + last_file_dict = {"prefix_file_name": "", "file_name": "", "file_end_time": ""} + for file_name in log_files.split('\n'): + if file_name == "": + self.stdio.verbose("existing file name is empty") + continue + if not file_name.endswith("log") and not file_name.endswith("wf"): + file_start_time_str = "" + prefix_name = file_name[:-14] if len(file_name) > 24 else "" + file_end_time_str = TimeUtils.filename_time_to_datetime(TimeUtils.extract_filename_time_from_log_name(file_name, self.stdio), self.stdio) + if last_file_dict["prefix_file_name"] != "" and last_file_dict["prefix_file_name"] == prefix_name: + file_start_time_str = last_file_dict["file_end_time"] + elif last_file_dict["prefix_file_name"] != "" and last_file_dict["prefix_file_name"] != prefix_name: + file_start_time_str = "" + file_end_time_str = "" + elif last_file_dict["prefix_file_name"] == "": + file_start_time_str = get_file_start_time(self.ssh_client, file_name, log_dir, self.stdio) + # When two time intervals overlap, need to add the file + if (file_end_time_str != "") and (file_start_time_str != "") and (file_start_time_str <= to_time_str) and (file_end_time_str >= from_time_str): + log_name_list.append(file_name) + last_file_dict = {"prefix_file_name": prefix_name, "file_name": file_name, "file_end_time": file_end_time_str} + elif file_name.endswith("log") or file_name.endswith("wf"): + # Get the first and last lines of text of the file. Here, use a command + get_first_line_cmd = "head -n 1 {0}/{1} && tail -n 1 {0}/{1}".format(log_dir, file_name) + first_and_last_line_text = self.ssh_client.exec_cmd(get_first_line_cmd) + # Split the first and last lines of text + first_and_last_line_text_list = str(first_and_last_line_text).splitlines() + if len(first_and_last_line_text_list) >= 2: + first_line_text = first_and_last_line_text_list[0] + last_line_text = first_and_last_line_text_list[-1] + # Time to parse the first and last lines of text + file_start_time_str = TimeUtils.extract_time_from_log_file_text(first_line_text, self.stdio) + file_end_time = TimeUtils.extract_time_from_log_file_text(last_line_text, self.stdio) + self.stdio.verbose("The log file {0} starts at {1} ends at {2}".format(file_name, file_start_time_str, file_end_time)) + self.stdio.verbose("to_time_str {0} from_time_str {1}".format(to_time_str, from_time_str)) + if (file_start_time_str <= to_time_str) and (file_end_time >= from_time_str): + log_name_list.append(file_name) + if len(log_name_list) > 0: + self.stdio.verbose("Find the qualified log file {0} on Server [{1}], " "wait for the next step".format(log_name_list, self.ssh_client.get_ip())) + else: + self.stdio.warn("No found the qualified log file on Server [{0}]".format(self.ssh_client.get_name())) + return log_name_list diff --git a/handler/gather/scenes/cpu_high.py b/handler/gather/scenes/cpu_high.py index abf52d2e..b6eaa752 100644 --- a/handler/gather/scenes/cpu_high.py +++ b/handler/gather/scenes/cpu_high.py @@ -18,10 +18,10 @@ import os from common.ssh_client.ssh import SshClient +from handler.gather.gather_component_log import GatherComponentLogHandler from stdio import SafeStdio from handler.gather.gather_obstack2 import GatherObstack2Handler from handler.gather.gather_perf import GatherPerfHandler -from handler.gather.gather_log import GatherLogHandler class CPUHighScene(SafeStdio): @@ -74,7 +74,8 @@ def __gather_current_clocksource(self): def __gather_log(self): try: self.stdio.print("gather observer log start") - handler = GatherLogHandler(self.context, self.report_path, is_scene=True) + handler = GatherComponentLogHandler() + handler.init(self.context, store_dir=self.report_path, target="observer", is_scene=True) handler.handle() self.stdio.print("gather observer log end") except Exception as e: diff --git a/handler/gather/scenes/px_collect_log.py b/handler/gather/scenes/px_collect_log.py index 437e04a7..1f70f28b 100644 --- a/handler/gather/scenes/px_collect_log.py +++ b/handler/gather/scenes/px_collect_log.py @@ -15,14 +15,17 @@ @file: px_collect_log.py @desc: """ +import os +import shutil + from common.ssh_client.ssh import SshClient -from handler.gather.gather_log import GatherLogHandler -from common.command import uzip_dir_local, analyze_log_get_sqc_addr, delete_file_in_folder, find_home_path_by_port +from handler.gather.gather_component_log import GatherComponentLogHandler +from common.command import uzip_dir_local, analyze_log_get_sqc_addr, find_home_path_by_port import datetime class SQLPXCollectLogScene(object): - def __init__(self, context, scene_name, report_path, task_variable_dict=None, env={}): + def __init__(self, context, scene_name, report_path, task_variable_dict=None, env=None): self.context = context self.stdio = context.stdio if task_variable_dict is None: @@ -31,6 +34,8 @@ def __init__(self, context, scene_name, report_path, task_variable_dict=None, en self.task_variable_dict = task_variable_dict self.report_path = report_path self.env = env + if self.env is None: + self.env = {} self.is_ssh = True self.scene_name = scene_name self.db_conn = {} @@ -56,7 +61,7 @@ def execute(self): # 否则不存在,则删除被解压的目录 if len(self.sql_task_node) != 0: self.stdio.verbose("delete file start") - delete_file_in_folder(False, None, self.report_path, self.stdio) + shutil.rmtree(self.report_path) self.stdio.verbose("delete file end") self.__gather_log() uzip_dir_local(self.report_path, self.stdio) @@ -64,14 +69,18 @@ def execute(self): def __gather_log(self): try: self.stdio.verbose("gather observer log start, trace id: {0}".format(self.trace_id)) - handler = GatherLogHandler(self.context, gather_pack_dir=self.report_path, is_scene=True) - self.context.set_variable('filter_nodes_list', self.sql_task_node) - self.context.set_variable('gather_grep', self.trace_id) - self.context.set_variable('gather_mode', 'trace_id_log') from_time_str = (self.search_time - datetime.timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') to_time_str = (self.search_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') - self.context.set_variable("gather_from", from_time_str) - self.context.set_variable("gather_to", to_time_str) + handler = GatherComponentLogHandler() + handler.init( + self.context, + target="observer", + from_option=from_time_str, + to_option=to_time_str, + grep=[self.trace_id], + is_scene=True, + store_dir=self.report_path, + ) handler.handle() self.stdio.verbose("gather observer log end") except Exception as e: diff --git a/handler/gather/scenes/sql_problem.py b/handler/gather/scenes/sql_problem.py index 8d9c43b2..804f0b1a 100644 --- a/handler/gather/scenes/sql_problem.py +++ b/handler/gather/scenes/sql_problem.py @@ -15,10 +15,8 @@ @file: sql_problem.py @desc: """ - +from handler.gather.gather_component_log import GatherComponentLogHandler from stdio import SafeStdio -from handler.gather.gather_log import GatherLogHandler -from handler.gather.gather_obproxy_log import GatherObProxyLogHandler from handler.gather.gather_plan_monitor import GatherPlanMonitorHandler from common.tool import StringUtils from common.ssh_client.ssh import SshClient @@ -76,9 +74,8 @@ def __gather_log(self): self.task_nodes.append(node) break self.stdio.verbose("gather observer log start") - handler = GatherLogHandler(self.context, self.report_path, is_scene=True) - self.context.set_variable('filter_nodes_list', self.task_nodes) - self.context.set_variable('gather_grep', self.trace_id) + handler = GatherComponentLogHandler() + handler.init(self.context, target="observer", grep=[self.trace_id], nodes=self.task_nodes, store_dir=self.report_path, is_scene=True) handler.handle() self.stdio.verbose("gather observer log end") except Exception as e: @@ -88,15 +85,15 @@ def __gather_log(self): def __gather_obproxy_log(self): try: self.stdio.verbose("gather obproxy log start") - handler = GatherObProxyLogHandler(self.context, gather_pack_dir=self.report_path, is_scene=True) + handler = GatherComponentLogHandler() if self.scene_name: if self.scene_name == "observer.sql_err" or self.scene_name == "observer.perf_sql": - self.context.set_variable('gather_grep', self.trace_id) + handler.init(self.context, target="obproxy", grep=[self.trace_id], store_dir=self.report_path, is_scene=True) + self.stdio.verbose("gather obproxy log end") + return handler.handle() else: self.stdio.warn("unsupported scene {0}".format(self.scene_name)) return - handler.handle() - self.stdio.verbose("gather obproxy log end") else: self.stdio.warn("scene is None") return diff --git a/handler/gather/step/base.py b/handler/gather/step/base.py index ee1bb9c2..d23dadae 100644 --- a/handler/gather/step/base.py +++ b/handler/gather/step/base.py @@ -16,16 +16,17 @@ @desc: """ from common.ssh_client.ssh import SshClient +from handler.gather.gather_component_log import GatherComponentLogHandler from stdio import SafeStdio from handler.gather.step.ssh import SshHandler from handler.gather.step.sql import StepSQLHandler -from handler.gather.gather_log import GatherLogHandler -from handler.gather.gather_obproxy_log import GatherObProxyLogHandler from handler.gather.gather_sysstat import GatherOsInfoHandler class Base(SafeStdio): - def __init__(self, context, step, node, cluster, report_path, task_variable_dict=None, env={}, node_number=1): + def __init__(self, context, step, node, cluster, report_path, task_variable_dict=None, env=None, node_number=1): + if env is None: + env = {} self.context = context self.stdio = context.stdio if task_variable_dict is None: @@ -67,17 +68,17 @@ def execute(self): handler.execute() elif self.step["type"] == "log" and (skip_type != "ssh"): if self.node.get("host_type") and self.node.get("host_type") == "OBSERVER": - handler = GatherLogHandler(self.context, gather_pack_dir=self.report_path, is_scene=True) - self.context.set_variable('filter_nodes_list', [self.node]) - self.context.set_variable('gather_grep', self.step.get("grep")) + handler = GatherComponentLogHandler() + handler.init(self.context, target="observer", grep=self.step.get("grep"), nodes=[self.node], store_dir=self.report_path, is_scene=True) handler.handle() else: self.stdio.verbose("node host_type is {0} not OBSERVER, skipping gather log".format(self.node.get("host_type"))) elif self.step["type"] == "obproxy_log" and (skip_type != "ssh"): if self.node.get("host_type") and self.node.get("host_type") == "OBPROXY": - handler = GatherObProxyLogHandler(self.context, gather_pack_dir=self.report_path, is_scene=True) self.context.set_variable('filter_nodes_list', [self.node]) self.context.set_variable('gather_grep', self.step.get("grep")) + handler = GatherComponentLogHandler() + handler.init(self.context, target="obproxy", grep=self.step.get("grep"), nodes=[self.node], store_dir=self.report_path, is_scene=True) handler.handle() else: self.stdio.verbose("node host_type is {0} not OBPROXY, skipping gather log".format(self.node.get("host_type"))) diff --git a/handler/rca/plugins/gather.py b/handler/rca/plugins/gather.py index 4a2ddec1..39e1a057 100644 --- a/handler/rca/plugins/gather.py +++ b/handler/rca/plugins/gather.py @@ -18,8 +18,7 @@ import os.path import zipfile -from handler.gather.gather_log import GatherLogHandler -from handler.gather.gather_obproxy_log import GatherObProxyLogHandler +from handler.gather.gather_component_log import GatherComponentLogHandler class Gather_log: @@ -66,15 +65,10 @@ def execute(self, save_path=""): if len(self.greps_key) == 0: self.stdio.error("The keyword cannot be empty!") raise Exception("The keyword cannot be empty!") - self.context.set_variable("gather_grep", self.greps_key) self.stdio.verbose("gather_grep is {0}".format(self.greps_key)) nodes_list = [] - if not self.conf_map["filter_nodes_list"] or len(self.conf_map["filter_nodes_list"]) == 0: - self.context.set_variable("filter_nodes_list", self.conf_map["filter_nodes_list"]) - # execute on all nodes_list - handle = None - for conf in self.conf_map: - self.context.set_variable(conf, self.conf_map[conf]) + # execute on all nodes_list + handler = None if self.conf_map["gather_target"] == 'observer': all_node = self.context.cluster_config.get("servers") if self.conf_map["filter_nodes_list"] and len(self.conf_map["filter_nodes_list"] > 0): @@ -85,7 +79,19 @@ def execute(self, save_path=""): nodes_list.append(node) self.stdio.verbose("{0} is in the nodes list".format(node.get("ip"))) self.conf_map["filter_nodes_list"] = nodes_list - handle = GatherLogHandler(self.context) + handler = GatherComponentLogHandler() + handler.init( + self.context, + target="observer", + nodes=nodes_list, + from_option=self.conf_map.get("gather_from"), + to_option=self.conf_map.get("gather_to"), + since=self.conf_map.get("gather_since"), + scope=self.conf_map.get("gather_scope"), + grep=self.greps_key, + store_dir=self.work_path, + ) + elif self.conf_map["gather_target"] == 'obproxy': all_node = self.context.get_variable('obproxy_nodes') if self.conf_map["filter_nodes_list"]: @@ -97,20 +103,30 @@ def execute(self, save_path=""): else: nodes_list.append(node) self.conf_map["filter_nodes_list"] = nodes_list - handle = GatherObProxyLogHandler(self.context) + handler = GatherComponentLogHandler() + handler.init( + self.context, + target="obproxy", + nodes=nodes_list, + from_option=self.conf_map.get("gather_from"), + to_option=self.conf_map.get("gather_to"), + since=self.conf_map.get("gather_since"), + scope=self.conf_map.get("gather_scope"), + grep=self.greps_key, + store_dir=self.work_path, + ) - if handle is None: + if handler is None: self.stdio.error("rca gather handle the target cannot be empty!") raise Exception("rca gather handle the target cannot be empty!") else: - handle.handle() - gather_result = handle.pack_dir_this_command + handler.handle() + gather_result = handler.store_dir zip_files = os.listdir(gather_result) result_log_files = [] for zip_file in zip_files: if "zip" not in zip_file: continue - # open zip file self.stdio.verbose("open zip file: {0}".format(os.path.join(gather_result, zip_file))) with zipfile.ZipFile(os.path.join(gather_result, zip_file), 'r') as zip_ref: @@ -122,7 +138,6 @@ def execute(self, save_path=""): for log_file in os.listdir(log_dir): result_log_files.append(os.path.join(log_dir, log_file)) self.stdio.verbose("result_log_files add {0}".format(os.path.join(log_dir, log_file))) - self.reset() return result_log_files diff --git a/handler/rca/rca_handler.py b/handler/rca/rca_handler.py index 86b6dc12..5036416b 100644 --- a/handler/rca/rca_handler.py +++ b/handler/rca/rca_handler.py @@ -165,11 +165,13 @@ def handle(self): except Exception as e: raise Exception("rca_scene.init err: {0}".format(e)) self.stdio.verbose("{0} init success".format(scene_name)) + return self.__execute() else: + self.stdio.error("rca_scene :{0} is not exist or not input".format(scene_name)) raise Exception("rca_scene :{0} is not exist or not input".format(scene_name)) # get all tasks - def execute(self): + def __execute(self): try: self.rca_scene.execute() except RCANotNeedExecuteException as e: diff --git a/result_type.py b/result_type.py index 71f30b01..fd84f82b 100644 --- a/result_type.py +++ b/result_type.py @@ -43,3 +43,6 @@ def get_result(self): def get_code(self): return self.code + + def is_success(self): + return self.code == self.SUCCESS_CODE