def _init_log(log_name: str): """ Log initalize """ log_path = Conf.get(const.HA_GLOBAL_INDEX, f"LOG{_DELIM}path") log_level = Conf.get(const.HA_GLOBAL_INDEX, f"LOG{_DELIM}level") Log.init(service_name=log_name, log_path=log_path, level=log_level)
def __init__(self, version="2.0", default_log_enable=True): """ Manage cluster operation """ self._version = version # TODO: Update Config manager if log utility changes.(reference EOS-17614) if default_log_enable is True: ConfigManager.init("cluster_manager") else: ConfigManager.init(None) self._cluster_type = Conf.get(const.HA_GLOBAL_INDEX, f"CLUSTER_MANAGER{_DELIM}cluster_type") self._env = Conf.get(const.HA_GLOBAL_INDEX, f"CLUSTER_MANAGER{_DELIM}env") self._confstore = ConfigManager.get_confstore() # Raise exception if user does not have proper permissions self._validate_permissions() ConfigManager.load_controller_schema() self._controllers = ElementControllerFactory.init_controller( self._env, self._cluster_type) for controller in self._controllers.keys(): Log.info(f"Adding {controller} property to cluster manager.") # Add property method for controller # Example: cm.cluster_controller.start() # Find more example in test case. self.__dict__[controller] = self._controllers[controller]
def init(log_name, log_path=None, level="INFO", backup_count=5, file_size_in_mb=10, syslog_server=None, syslog_port=None, console_output=True, config_file=None): """ Initialize ha conf and log Args: log_name (str): service_name for log init. """ # log_path will be piked from cluster config only # log_path can be updated for testing only ConfigManager._conf_init(config_file) if log_name: if not log_path: log_path = Conf.get(const.HA_GLOBAL_INDEX, f"LOG{_DELIM}path") level = Conf.get(const.HA_GLOBAL_INDEX, f"LOG{_DELIM}level") # console_output=True will redirect all log to console and log file both # TODO: CORTX-28795 filter redirect log for console and file Log.init(service_name=log_name, log_path=log_path, level=level, backup_count=backup_count, file_size_in_mb=file_size_in_mb, syslog_server=syslog_server, syslog_port=syslog_port, console_output=console_output) Log.info(f"Started logging for service {log_name}")
async def _get_bundle_status(command): """ Initializes the process for Displaying the Status for Support Bundle. command: Command Object :type: command return: None """ try: status = '' node_id = Conf.machine_id Conf.load(const.SB_INDEX, 'json://' + const.FILESTORE_PATH, skip_reload=True) bundle_id = command.options.get(const.SB_BUNDLE_ID) if not bundle_id: status = Conf.get(const.SB_INDEX, f'{node_id}') else: status = Conf.get(const.SB_INDEX, f'{node_id}>{bundle_id}>status') if not status: return Response(output=(f"No status found for bundle_id: {bundle_id}" \ "in input config. Please check if the Bundle ID is correct"), \ rc=ERR_OP_FAILED) return Response(output=status, rc=OPERATION_SUCESSFUL) except Exception as e: Log.error(f"Failed to get bundle status: {e}") return Response(output=(f"Support Bundle status is not available " \ f"Failed to get status of bundle. Related error - {e}"), \ rc=str(errno.ENOENT))
def __init__(self): """ Init method """ super().__init__() # Get filter type and resource types list from the alert monitor rule file self.alert_filter_components = Conf.get(ALERT_EVENT_INDEX, ALERTS.PK_ALERT_EVENT_COMPONENTS) self.alert_filter_modules = Conf.get(ALERT_EVENT_INDEX, ALERTS.PK_ALERT_EVENT_COMPONENT_MODULES) self.alert_filter_module_operations = Conf.get(ALERT_EVENT_INDEX, ALERTS.PK_ALERT_EVENT_OPERATIONS) Log.info("AlertEventFilter initialized.")
def __init__(self): """ Init method """ #Loads alert flter rules in the configuration ConfigManager.load_filter_rules() #Get filter type and resource types list from the alert rule file self.filter_type = Conf.get(const.ALERT_FILTER_INDEX, "alert.filter_type") self.resource_types_list = Conf.get(const.ALERT_FILTER_INDEX, "alert.resource_type")
def init(log_name) -> None: """ Initialize ha conf and log Args: log_name ([str]): service_name for log init. """ Conf.init(delim='.') Conf.load(const.HA_GLOBAL_INDEX, f"yaml://{const.HA_CONFIG_FILE}") Conf.load(const.RESOURCE_GLOBAL_INDEX, f"json://{const.RESOURCE_SCHEMA}") log_path = Conf.get(const.HA_GLOBAL_INDEX, "LOG.path") log_level = Conf.get(const.HA_GLOBAL_INDEX, "LOG.level") Log.init(service_name=log_name, log_path=log_path, level=log_level)
def _get_consumer(self): """ Return instace of message bus consumer. """ consumer_id = Conf.get(HA_GLOBAL_INDEX, f"EVENT_MANAGER{_DELIM}consumer_id") consumer_group = Conf.get(HA_GLOBAL_INDEX, f"EVENT_MANAGER{_DELIM}consumer_group") message_type = Conf.get(HA_GLOBAL_INDEX, f"EVENT_MANAGER{_DELIM}message_type") MessageBus.init() return MessageBus.get_consumer(consumer_id=consumer_id, consumer_group=consumer_group, message_type=message_type, callback=self.process_event)
def __init__(self): """ Init method """ super(AlertFilter, self).__init__() AlertFilter.validate_filter( const.AlertEventConstants.ALERT_FILTER_TYPE.value) # Get filter type and resource types list from the alert rule file self.filter_type = Conf.get( const.ALERT_FILTER_INDEX, const.AlertEventConstants.ALERT_FILTER_TYPE.value) self.resource_types_list = Conf.get( const.ALERT_FILTER_INDEX, const.AlertEventConstants.ALERT_RESOURCE_TYPE.value) Log.info("Alert Filter is initialized ...")
def validate_filter(message_type: str): """ Filter type should be one of INCLUSION or EXCLUSION """ filter_type = Conf.get(const.ALERT_FILTER_INDEX, message_type) if filter_type not in [const.INCLUSION, const.EXCLUSION]: raise InvalidFilterRules(f"Invalid filter type {filter_type}")
def filter_event(self, msg: str) -> bool: """ Filter event. Args: msg (str): Msg """ try: resource_alert_required = False message = json.dumps(ast.literal_eval(msg)) message = json.loads(message) Log.debug('Received alert from fault tolerance') event_resource_type = message.get( EventAttr.EVENT_PAYLOAD.value).get( HealthAttr.RESOURCE_TYPE.value) required_resource_type_list = Conf.get( const.HA_GLOBAL_INDEX, f"CLUSTER{_DELIM}resource_type") if event_resource_type in required_resource_type_list: resource_alert_required = True Log.info( f'This alert needs an attention: resource_type: {event_resource_type}' ) return resource_alert_required except Exception as e: raise EventFilterException( f"Failed to filter cluster resource event. Message: {msg}, Error: {e}" )
def init(): """ Initialize utils MessageBus Library with kafka endpoints once per service. In future utils will throw error if init done multiple times. If any new service will come which uses MessageBus then init should be done there. """ message_server_endpoints = Conf.get( const.HA_GLOBAL_INDEX, f"kafka_config{const._DELIM}endpoints") utils_message_bus.init(message_server_endpoints)
def __init__(self): """ Init method """ super(IEMFilter, self).__init__() IEMFilter.validate_filter( const.AlertEventConstants.IEM_FILTER_TYPE.value) # Get filter type and resource types list from the IEM rule file self.filter_type = Conf.get( const.ALERT_FILTER_INDEX, const.AlertEventConstants.IEM_FILTER_TYPE.value) self.components_list = Conf.get( const.ALERT_FILTER_INDEX, const.AlertEventConstants.IEM_COMPONENTS.value) self.modules_dict = Conf.get( const.ALERT_FILTER_INDEX, const.AlertEventConstants.IEM_MODULES.value) Log.info("IEM Filter is initialized ...")
def get_major_version(): """ Get product version Returns: [int]: Return version """ version = Conf.get(const.HA_GLOBAL_INDEX, f"VERSION{_DELIM}version") major_version = version.split('.') return major_version[0]
def get_confstore(): """ Initalize and get confstore if not _cluster_confstore is None. Used by config manager methods to check and initalize confstore if needed. """ if ConfigManager._cluster_confstore is None: consul_endpoint = Conf.get(const.HA_GLOBAL_INDEX, f'consul_config{_DELIM}endpoint') consul_host = consul_endpoint.split(":")[1].strip("//") consul_port = consul_endpoint.split(":")[-1] ConfigManager._cluster_confstore = ConsulKvStore(prefix=const.CLUSTER_CONFSTORE_PREFIX, host=consul_host, port=consul_port) return ConfigManager._cluster_confstore
def __init__(self, default_log_enable=True): """ Manage cluster operation """ # TODO: Update Config manager if log utility changes.(reference EOS-17614) if default_log_enable is True: ConfigManager.init("cluster_manager") else: ConfigManager.init(None) self._cluster_type = Conf.get(const.HA_GLOBAL_INDEX, "CLUSTER_MANAGER.cluster_type") self._env = Conf.get(const.HA_GLOBAL_INDEX, "CLUSTER_MANAGER.env") ConfigManager.load_controller_schema() self._controllers = ElementControllerFactory.init_controller( self._env, self._cluster_type) for controller in self._controllers.keys(): Log.info(f"Adding {controller} property to cluster manager.") # Add property method for controller # Example: cm.cluster_controller.start() # Find more example in test case. self.__dict__[controller] = self._controllers[controller]
async def get_active_nodes(): """ This Method is for reading hostnames, node_list information. :return: hostnames : List of Hostname :type: List :return: node_list : : List of Node Name :type: List """ Log.info("Reading hostnames, node_list information") Conf.load('cortx_cluster', 'json:///etc/cortx/cluster.conf') node_hostname_map = Conf.get('cortx_cluster', 'cluster') if not node_hostname_map: response_msg = "Node list and hostname not found." return Response(output=response_msg, rc=errno.ENODATA), None return node_hostname_map
def enable_stonith(self): """ Enable stonith for HW Returns: """ # enable the stonith here env_type = Conf.get(const.HA_GLOBAL_INDEX, f"CLUSTER_MANAGER{const._DELIM}env") if env_type.lower() == const.INSTALLATION_TYPE.HW.value.lower(): Log.info("Enabling the stonith.") self._execute.run_cmd(const.PCS_STONITH_ENABLE) Log.info("Stonith enabled successfully.") else: Log.warn(f"Stonith is not enabled, detected {env_type} env")
async def _get_active_nodes() -> dict: """This Method is for reading hostnames, node_list information Returns: dict: hosts in cluster eg {node1:fqd1} Response: Response object if no host found in config file """ Log.info("Reading hostnames, node_list information") Conf.load('cortx_cluster', 'json:///etc/cortx/cluster.conf', \ skip_reload=True) node_hostname_map = Conf.get('cortx_cluster', 'cluster') if not node_hostname_map: response_msg = "Node list and hostname not found." return Response(output=response_msg, rc=errno.ENODATA), None return node_hostname_map
def _bootstrap_in_progress(self): """ Check if we are in intial bootstrap time Return: True: if bootstrp happening and initial health status being collected for all pods else return False """ init_health_in_progress = False init_health = self.healthmanager.get_key("init_system_health") if (init_health != None) and (init_health == 0): init_health_in_progress = False return init_health_in_progress if init_health == None: # Create key and set value to 1 self.healthmanager.set_key("init_system_health", "1") curr_time = str(int(time.time())) # Timeout counting starts form the time first event is received by system health self.healthmanager.set_key("inital_time", curr_time) timeout = Conf.get( const.HA_GLOBAL_INDEX, f"SYSTEM_HEALTH{_DELIM}sys_health_bootstrap_timeout") self.healthmanager.set_key("sys_health_bootstrap_timeout", timeout) init_health_in_progress = True else: # TBD Following logic can be added after EOS-26597 is resolved. # Once total number of pods and service types of the pods are avilable in the config, # use the same to expediate bootstrap process i.e. to exit bootstrap mode before timeout # check if within timeout period curr_time = int(time.time()) init_time = int(self.healthmanager.get_key("inital_time")) timeout = int( self.healthmanager.get_key("sys_health_bootstrap_timeout")) if curr_time - init_time <= timeout: init_health_in_progress = True else: self.healthmanager.set_key("init_system_health", "0") init_health_in_progress = False return init_health_in_progress
def init_controller(env: str, cluster_type: str) -> dict: """ Get specific controller instance to perform operation. Args: env (str): Detect controller as per env. cluster_type (str): Cluster type depend on cluster running on system. """ controllers: dict = Conf.get(const.CM_CONTROLLER_INDEX, f"{env}{_DELIM}{cluster_type}") for controller in controllers: Log.info(f"Initalizing controller api {controller['interface']}") class_path_list: list = controller["interface"].split('.')[:-1] module = import_module(f"{'.'.join(class_path_list)}") element_instace = getattr(module, controller["interface"].split('.')[-1])() ElementControllerFactory._controllers[controller["element"]] = element_instace # Pass the controllers instance list to each controller. So, dependent controller can use interface if needed for controller in ElementControllerFactory._controllers.keys(): ElementControllerFactory._controllers[controller].initialize(ElementControllerFactory._controllers) return ElementControllerFactory._controllers
def _initalize_watcher(self, system_health: SystemHealth) -> dict: """ Initalize watcher. Args: system_health (SystemHealth): Instance of systemhealth. Returns: dict: mapping of wather_type -> watcher_instance """ watchers = Conf.get(const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher") watcher_list: dict = {} for watcher in watchers: Log.info(f"Initializing watcher {watcher}....") event_filter_class = Conf.get( const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher{_DELIM}{watcher}{_DELIM}event_filter" ) event_filter_instance = EventAnalyzerService.get_class( event_filter_class)() event_parser_class = Conf.get( const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher{_DELIM}{watcher}{_DELIM}event_parser" ) event_parser_instance = EventAnalyzerService.get_class( event_parser_class)() watcher_list[watcher] = Watcher( consumer_id=Conf.get( const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher{_DELIM}{watcher}{_DELIM}consumer_id" ), message_type=Conf.get( const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher{_DELIM}{watcher}{_DELIM}message_type" ), consumer_group=Conf.get( const.HA_GLOBAL_INDEX, f"EVENT_ANALYZER{_DELIM}watcher{_DELIM}{watcher}{_DELIM}consumer_group" ), event_filter=event_filter_instance, event_parser=event_parser_instance, subscriber=system_health) return watcher_list
async def _generate_bundle(command): """ Initializes the process for Generating Support Bundle on Each CORTX Node. command: Command Object :type: command return: None. """ bundle_id = SupportBundle._generate_bundle_id() provisioner = ProvisionerServices() if not provisioner: return Response(output="Provisioner package not found.", \ rc=errno.ENOENT) # Get Arguments From Command comment = command.options.get(const.SB_COMMENT) components = command.options.get(const.SB_COMPONENTS) if not components: components = [] if command.options.get(const.SOS_COMP, False) == 'true': components.append('os') Conf.load('cortx_conf', 'json:///etc/cortx/cortx.conf', \ skip_reload=True) # Get HostNames and Node Names. node_hostname_map = await SupportBundle._get_active_nodes() if not isinstance(node_hostname_map, dict): return node_hostname_map shared_path = Storage.get_path(name='support_bundle') path = shared_path if shared_path else Conf.get('cortx_conf',\ 'support>local_path') bundle_path = os.path.join(path, bundle_id) os.makedirs(bundle_path) bundle_obj = Bundle(bundle_id=bundle_id, bundle_path=path, \ comment=comment,is_shared=True if shared_path else False) support_bundle_file = os.path.join(Conf.get('cortx_conf', 'install_path'),\ 'cortx/utils/conf/support_bundle.yaml') Conf.load('sb_yaml', f'yaml://{support_bundle_file}', skip_reload=True) all_components = Conf.get('sb_yaml', 'COMPONENTS') invalid_comps = [ component for component in components if component not in all_components.keys() ] if invalid_comps: components = list(set(components) - set(invalid_comps)) ComponentsBundle._publish_log(f"""Invalid components - '{", ".join(invalid_comps)}'""", \ 'error', bundle_id, '', comment) if invalid_comps and not components: return bundle_obj comp_list = SupportBundle._get_components(components) # Start SB Generation on all Nodes. for nodename, hostname in node_hostname_map.items(): Log.debug(f"Connect to {hostname}") try: # TODO: pass bundle_path to bundle_generation when args implemented await provisioner.begin_bundle_generation( f"bundle_generate '{bundle_id}' '{comment}' " f"'{hostname}' {comp_list}", nodename) except BundleError as be: Log.error(f"Bundle generation failed.{be}") ComponentsBundle._publish_log(f"Bundle generation failed.{be}", \ 'error', bundle_id, nodename, comment) except Exception as e: Log.error(f"Internal error, bundle generation failed {e}") ComponentsBundle._publish_log( f"Internal error, bundle generation failed \ {e}", 'error', bundle_id, nodename, comment) # Create common tar. #if bundle_obj.is_shared: # tar_dest_file = f"{bundle_id}.tar.gz" # Log.debug(f"Merging all bundle to {bundle_path}/{tar_dest_file}") # try: # Tar(os.path.join(bundle_path, tar_dest_file)).dump([bundle_path]) # except: # Log.debug("Merging of node support bundle failed") # return Response(output="Bundle Generation Failed in merging", # rc=errno.EINVAL) if command.sub_command_name == 'generate': display_string_len = len(bundle_obj.bundle_id) + 4 response_msg = ( f"Please use the below bundle id for checking the status of support bundle." f"\n{'-' * display_string_len}" f"\n| {bundle_obj.bundle_id} |" f"\n{'-' * display_string_len}" f"\nPlease Find the file on -> {bundle_obj.bundle_path} .\n") return Response(output=response_msg, rc=OPERATION_SUCESSFUL) return bundle_obj
"enclosure-id": 0, "durable-id": "fan_module_0.4", "fans": [], "health-reason": "The fan module is not installed.", "health": "Fault", "location": "Enclosure 0 - Right", "position": "Indexed", "health-recommendation": "Install the missing fan module." }, "alert_id": "15740759091a4e14bca51d46908ac3e9102605d560", "host_id": "s3node-host-1" } } Expected_result = False filter_type = Conf.get(const.ALERT_FILTER_INDEX, "alert.filter_type") resource_types_list = Conf.get(const.ALERT_FILTER_INDEX, "alert.resource_type") if "actuator_response_type" not in TestMsg.keys(): if filter_type == const.INCLUSION: if resource_type in resource_types_list: Expected_result = True elif filter_type == const.EXCLUSION: if resource_type not in resource_types_list: Expected_result = True else: print("Invalid filter type") if Expected_result == AlertFilter.filter_event(json.dumps(TestMsg)): print("Alert filter test pass successfully") else:
"enclosure-id": 0, "durable-id": "fan_module_0.4", "fans": [], "health-reason": "The fan module is not installed.", "health": "Fault", "location": "Enclosure 0 - Right", "position": "Indexed", "health-recommendation": "Install the missing fan module." }, "alert_id": "15740759091a4e14bca51d46908ac3e9102605d560", "host_id": "s3node-host-1" } } Expected_result = False filter_type = Conf.get(const.ALERT_FILTER_INDEX, f"alert{_DELIM}filter_type") resource_types_list = Conf.get(const.ALERT_FILTER_INDEX, f"alert{_DELIM}resource_type") if const.ACTUATOR_RESPONSE_TYPE not in TestMsg.keys(): if filter_type == const.INCLUSION: if resource_type in resource_types_list: Expected_result = True elif filter_type == const.EXCLUSION: if resource_type not in resource_types_list: Expected_result = True else: print("Invalid filter type") if Expected_result == AlertFilter.filter_event(json.dumps(TestMsg)): print("Alert filter test pass successfully") else:
def get_hw_env() -> str: """ Get if system is running on VM or actual h/w. """ return Conf.get(const.HA_GLOBAL_INDEX, f"CLUSTER_MANAGER{_DELIM}env")
def get_local_node() -> str: """ Get local node name. """ return Conf.get(const.HA_GLOBAL_INDEX, f"CLUSTER_MANAGER{_DELIM}local_node")
async def init(command: List): """ Initializes the Process of Support Bundle Generation for Every Component. :param command: Csm_cli Command Object :type: command :return: """ # Fetch Command Arguments. Log.init("support_bundle", syslog_server="localhost", syslog_port=514, log_path=Conf.get("cortx_conf", "support>support_bundle_path"), level="INFO") bundle_id = command.options.get(const.SB_BUNDLE_ID, "") node_name = command.options.get(const.SB_NODE_NAME, "") comment = command.options.get(const.SB_COMMENT, "") components = command.options.get(const.SB_COMPONENTS, []) Log.debug(( f"{const.SB_BUNDLE_ID}: {bundle_id}, {const.SB_NODE_NAME}: {node_name}, " f" {const.SB_COMMENT}: {comment}, {const.SB_COMPONENTS}: {components}," f" {const.SOS_COMP}")) # Read Commands.Yaml and Check's If It Exists. cmd_setup_file = os.path.join(Conf.get("cortx_conf", "install_path"), "cortx/utils/conf/support_bundle.yaml") support_bundle_config = Yaml(cmd_setup_file).load() if not support_bundle_config: ComponentsBundle._publish_log(f"No such file {cmd_setup_file}", ERROR, bundle_id, node_name, comment) return None # Path Location for creating Support Bundle. path = os.path.join( Conf.get("cortx_conf", "support>support_bundle_path")) if os.path.isdir(path): try: shutil.rmtree(path) except PermissionError: Log.warn(f"Incorrect permissions for path:{path}") bundle_path = os.path.join(path, bundle_id) os.makedirs(bundle_path) # Start Execution for each Component Command. threads = [] command_files_info = support_bundle_config.get("COMPONENTS") # OS Logs are specifically generated hence here Even When All is Selected O.S. Logs Will Be Skipped. if components: if "all" not in components: components_list = list( set(command_files_info.keys()).intersection( set(components))) else: components_list = list(command_files_info.keys()) components_list.remove(const.SOS_COMP) Log.debug( f"Generating for {const.SB_COMPONENTS} {' '.join(components_list)}" ) for each_component in components_list: components_commands = [] components_files = command_files_info[each_component] for file_path in components_files: file_data = Yaml(file_path).load() if file_data: components_commands = file_data.get( const.SUPPORT_BUNDLE.lower(), []) if components_commands: thread_obj = threading.Thread( ComponentsBundle._exc_components_cmd( components_commands, bundle_id, f"{bundle_path}{os.sep}", each_component, node_name, comment)) thread_obj.start() Log.debug( f"Started thread -> {thread_obj.ident} Component -> {each_component}" ) threads.append(thread_obj) directory_path = Conf.get("cortx_conf", "support>support_bundle_path") tar_file_name = os.path.join(directory_path, f"{bundle_id}_{node_name}.tar.gz") ComponentsBundle._create_summary_file(bundle_id, node_name, comment, bundle_path) symlink_path = const.SYMLINK_PATH if os.path.exists(symlink_path): try: shutil.rmtree(symlink_path) except PermissionError: Log.warn(const.PERMISSION_ERROR_MSG.format(path=symlink_path)) os.makedirs(symlink_path, exist_ok=True) # Wait Until all the Threads Execution is not Complete. for each_thread in threads: Log.debug( f"Waiting for thread - {each_thread.ident} to complete process" ) each_thread.join(timeout=1800) try: Log.debug( f"Generating tar.gz file on path {tar_file_name} from {bundle_path}" ) Tar(tar_file_name).dump([bundle_path]) except Exception as e: ComponentsBundle._publish_log(f"Could not generate tar file {e}", ERROR, bundle_id, node_name, comment) return None try: Log.debug("Create soft-link for generated tar.") os.symlink( tar_file_name, os.path.join(symlink_path, f"{const.SUPPORT_BUNDLE}.{bundle_id}")) ComponentsBundle._publish_log( f"Tar file linked at location - {symlink_path}", INFO, bundle_id, node_name, comment) except Exception as e: ComponentsBundle._publish_log(f"Linking failed {e}", ERROR, bundle_id, node_name, comment) finally: if os.path.isdir(bundle_path): shutil.rmtree(bundle_path) msg = "Support bundle generation completed." ComponentsBundle._publish_log(msg, INFO, bundle_id, node_name, comment)
def _get_producer(self): message_type = Conf.get(const.HA_GLOBAL_INDEX, f"EVENT_MANAGER{_DELIM}message_type") producer_id = Conf.get(const.HA_GLOBAL_INDEX, f"EVENT_MANAGER{_DELIM}producer_id") return MessageBus.get_producer(producer_id, message_type)
async def init(command: List): """ Initializes the Process of Support Bundle Generation for Every Component. command: cli Command Object :type: command return: None """ bundle_id = command.options.get(const.SB_BUNDLE_ID, '') node_name = command.options.get(const.SB_NODE_NAME, '') comment = command.options.get(const.SB_COMMENT, '') components = command.options.get(const.SB_COMPONENTS, []) Log.debug((f"{const.SB_BUNDLE_ID}: {bundle_id}, {const.SB_NODE_NAME}: " f"{node_name}, {const.SB_COMMENT}: {comment}, " f"{const.SB_COMPONENTS}: {components}, {const.SOS_COMP}")) # Read Commands.Yaml and Check's If It Exists. Conf.load('cortx_conf', 'json:///etc/cortx/cortx.conf', \ skip_reload=True) cmd_setup_file = os.path.join(Conf.get('cortx_conf', 'install_path'),\ 'cortx/utils/conf/support_bundle.yaml') try: support_bundle_config = Yaml(cmd_setup_file).load() except Exception as e: Log.error( f"Internal error while parsing YAML file {cmd_setup_file}{e}") ComponentsBundle._publish_log(f"Internal error while parsing YAML file " \ f"{cmd_setup_file}{e}", ERROR, bundle_id, node_name, comment) if not support_bundle_config: ComponentsBundle._publish_log(f"No such file {cmd_setup_file}", \ ERROR, bundle_id, node_name, comment) # Shared/Local path Location for creating Support Bundle. from cortx.utils.shared_storage import Storage path = Storage.get_path('support_bundle') if not path: path = Conf.get('cortx_conf', 'support>local_path') bundle_path = os.path.join(path, bundle_id, node_name) try: os.makedirs(bundle_path, exist_ok=True) except PermissionError as e: Log.error(f"Incorrect permissions for path:{bundle_path} - {e}") ComponentsBundle._publish_log(f"Incorrect permissions for path: {bundle_path} - {e}", \ ERROR, bundle_id, node_name, comment) # Start Execution for each Component Command. threads = [] command_files_info = support_bundle_config.get('COMPONENTS') # OS Logs are specifically generated hence here Even # When All is Selected O.S. Logs Will Be Skipped. if components: if 'all' not in components: components_list = list(set(command_files_info.keys()\ ).intersection(set(components))) else: components_list = list(command_files_info.keys()) components_list.remove(const.SOS_COMP) Log.debug( f"Generating for manifest and {const.SB_COMPONENTS} {' '.join(components_list)}" ) thread_que = Queue() # Manifest component supportbundle generation try: thread_obj = threading.Thread( ManifestSupportBundle.generate(f'{bundle_id}_manifiest', f'{bundle_path}{os.sep}')) thread_obj.start() Log.debug(f"Started thread -> {thread_obj.ident} " \ f"Component -> manifest") threads.append(thread_obj) except Exception as e: Log.error(f"Internal error while calling ManifestSupportBundle"\ f" generate api {e}") ComponentsBundle._publish_log(f"Internal error at while bundling"\ f" Manifest component: {bundle_path} - {e}", ERROR, bundle_id, node_name, comment) for each_component in components_list: components_commands = [] components_files = command_files_info[each_component] for file_path in components_files: if not os.path.exists(file_path): ComponentsBundle._publish_log(f"'{file_path}' file does not exist!", \ ERROR, bundle_id, node_name, comment) continue try: file_data = Yaml(file_path).load() except Exception as e: Log.error( f"Internal error while parsing YAML file {file_path}{e}" ) file_data = None ComponentsBundle._publish_log(f"Internal error while parsing YAML file: " \ f"{file_path} - {e}", ERROR, bundle_id, node_name, comment) break if file_data: components_commands = file_data.get( const.SUPPORT_BUNDLE.lower(), []) else: ComponentsBundle._publish_log(f"Support.yaml file is empty: " \ f"{file_path}", ERROR, bundle_id, node_name, comment) break if components_commands: thread_obj = threading.Thread(\ ComponentsBundle._exc_components_cmd(\ components_commands, f'{bundle_id}_{each_component}', f'{bundle_path}{os.sep}', each_component, node_name, comment, thread_que)) thread_obj.start() Log.debug(f"Started thread -> {thread_obj.ident} " \ f"Component -> {each_component}") threads.append(thread_obj) # directory_path = Conf.get('cortx_conf', 'support') tar_file_name = os.path.join(bundle_path, \ f'{bundle_id}_{node_name}.tar.gz') ComponentsBundle._create_summary_file(bundle_id, node_name, \ comment, bundle_path) # Wait Until all the Threads Execution is not Complete. for each_thread in threads: Log.debug( f"Waiting for thread - {each_thread.ident} to complete process" ) each_thread.join(timeout=1800) if not thread_que.empty(): component, return_code = thread_que.get() if return_code != 0: ComponentsBundle._publish_log( f"Bundle generation failed for component - '{component}'", ERROR, bundle_id, node_name, comment) else: ComponentsBundle._publish_log( f"Bundle generation started for component - '{component}'", INFO, bundle_id, node_name, comment) try: Log.debug(f"Generating tar.gz file on path {tar_file_name} " f"from {bundle_path}") Tar(tar_file_name).dump([bundle_path]) except Exception as e: ComponentsBundle._publish_log(f"Could not generate tar file {e}", \ ERROR, bundle_id, node_name, comment) finally: if os.path.exists(bundle_path): for each_dir in os.listdir(bundle_path): comp_dir = os.path.join(bundle_path, each_dir) if os.path.isdir(comp_dir): shutil.rmtree(comp_dir) msg = "Support bundle generation completed." ComponentsBundle._publish_log(msg, INFO, bundle_id, node_name, comment)