Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
    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]
Ejemplo n.º 3
0
 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}")
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
    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.")
Ejemplo n.º 6
0
    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")
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
 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)
Ejemplo n.º 9
0
 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 ...")
Ejemplo n.º 10
0
 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}")
Ejemplo n.º 11
0
    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}"
            )
Ejemplo n.º 12
0
 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)
Ejemplo n.º 13
0
 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 ...")
Ejemplo n.º 14
0
    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]
Ejemplo n.º 15
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
Ejemplo n.º 16
0
 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]
Ejemplo n.º 17
0
    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
Ejemplo n.º 18
0
    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")
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
    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
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
                    "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:
Ejemplo n.º 25
0
                    "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:
Ejemplo n.º 26
0
 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")
Ejemplo n.º 27
0
 def get_local_node() -> str:
     """
     Get local node name.
     """
     return Conf.get(const.HA_GLOBAL_INDEX,
                     f"CLUSTER_MANAGER{_DELIM}local_node")
Ejemplo n.º 28
0
    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)
Ejemplo n.º 29
0
 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)
Ejemplo n.º 30
0
    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)