예제 #1
0
    def init(cls, component: str, source: str):
        """
        Set the Event Message context

        Parameters:
        component       Component that generates the IEM. For e.g. 'S3', 'SSPL'
        source          Single character that indicates the type of component.
                        For e.g. H-Hardware, S-Software, F-Firmware, O-OS
        """

        cls._component = component
        cls._source = source

        try:
            Conf.load('cluster', cls._conf_file, skip_reload=True)
            ids = Conf.get('cluster', 'server_node')
            cls._site_id = ids['site_id']
            cls._rack_id = ids['rack_id']
            cls._node_id = ids['node_id']
            cls._cluster_id = ids['cluster_id']
        except Exception as e:
            raise EventMessageError(errno.EINVAL, "Invalid config in %s. %s", \
                cls._conf_file, e)

        if cls._component is None:
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
                cls._component)

        if cls._source not in cls._SOURCE.keys():
            raise EventMessageError(errno.EINVAL, "Invalid source type: %s", \
                cls._source)

        cls._producer = MessageProducer(producer_id='event_producer', \
            message_type='IEM', method='sync')
예제 #2
0
    def init(cls, component: str, source: str, cluster_id: str, \
         message_server_endpoints: str, **message_server_kwargs):
        """
        Set the Event Message context

        Parameters:
        component       Component that generates the IEM. For e.g. 'S3', 'SSPL'
        source          Single character that indicates the type of component.
                        For e.g. H-Hardware, S-Software, F-Firmware, O-OS
        """

        cls._component = component
        cls._source = source
        cls._site_id = 1
        cls._rack_id = 1
        cls._node_id = Conf.machine_id
        cls._cluster_id = cluster_id

        if cls._component is None:
            Log.error("Invalid component type: %s" % cls._component )
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
                cls._component)

        if cls._source not in cls._SOURCE.keys():
            Log.error("Invalid source type: %s" % cls._source)
            raise EventMessageError(errno.EINVAL, "Invalid source type: %s", \
                cls._source)
        MessageBus.init(message_server_endpoints, **message_server_kwargs)
        cls._producer = MessageProducer(producer_id='event_producer', \
            message_type='IEM', method='sync')
        Log.info("IEM Producer initialized for component %s and source %s" % \
             (cls._component, cls._source))
예제 #3
0
    def init(cls, component: str, source: str):
        """
        Set the Event Message context

        Parameters:
        component       Component that generates the IEM. For e.g. 'S3', 'SSPL'
        source          Single character that indicates the type of component.
                        For e.g. H-Hardware, S-Software, F-Firmware, O-OS
        """

        cls._component = component
        cls._source = source

        Conf.load('config_file', 'json:///etc/cortx/cortx.conf',
            skip_reload=True)
        # if Log.logger is already initialized by some parent process
        # the same file will be used to log all the messagebus related
        # logs, else standard iem.log will be used.
        if not Log.logger:
            LOG_DIR='/var/log'
            iem_log_dir = os.path.join(LOG_DIR, 'cortx/utils/iem')
            log_level = Conf.get('config_file', 'utils>log_level', 'INFO')
            Log.init('iem', iem_log_dir, level=log_level, \
                backup_count=5, file_size_in_mb=5)

        try:
            Conf.load('cluster', cls._conf_file, skip_reload=True)
            ids = Conf.get('cluster', 'server_node')
            cls._site_id = ids['site_id']
            cls._rack_id = ids['rack_id']
            cls._node_id = ids['node_id']
            cls._cluster_id = ids['cluster_id']
        except Exception as e:
            Log.error("Invalid config in %s." % cls._conf_file)
            raise EventMessageError(errno.EINVAL, "Invalid config in %s. %s", \
                cls._conf_file, e)

        if cls._component is None:
            Log.error("Invalid component type: %s" % cls._component )
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
                cls._component)

        if cls._source not in cls._SOURCE.keys():
            Log.error("Invalid source type: %s" % cls._source)
            raise EventMessageError(errno.EINVAL, "Invalid source type: %s", \
                cls._source)

        cls._producer = MessageProducer(producer_id='event_producer', \
            message_type='IEM', method='sync')
        Log.info("IEM Producer initialized for component %s and source %s" % \
             (cls._component, cls._source))
예제 #4
0
    def receive(cls):
        """ Receive IEM alert message """
        if cls._consumer is None:
            raise EventMessageError(errors.ERR_SERVICE_NOT_INITIALIZED, \
                "Consumer is not subscribed")

        alert = cls._consumer.receive()
        if alert is not None:
            try:
                return json.loads(alert.decode('utf-8'))
            except Exception as e:
                raise EventMessageError(
                    errno.EPERM, "Unable to load the json. \
                    %s", e)
        return alert
예제 #5
0
    def _parse_send_args(args) -> dict:
        """ Maps values from cmd line args to send_args dict """

        send_args = IemCli._get_empty_send_args()
        try:
            send_args['component'], send_args['module'] = args.source.split(
                ':')
            send_args['source_type'], send_args['severity'] \
                = args.info.split(':')
            if ':' in args.contents:
                send_args['event_id'], send_args['message'] \
                    = args.contents.split(':')
            elif args.file:
                send_args['event_id'] = args.contents
                with open(args.file, 'r') as fd:
                    send_args['message'] = ''.join(fd.readlines())
        except ValueError:
            raise EventMessageError(errno.EINVAL, "Invalid send arguments!")

        if args.location:
            cluster_id, site_id, node_id, rack_id, host = \
                args.location.split(':')
            send_args['problem_cluster_id'] = cluster_id
            send_args['problem_site_id'] = site_id
            send_args['problem_node_id'] = node_id
            send_args['problem_rack_id'] = rack_id
            send_args['problem_host'] = host

        return send_args
예제 #6
0
 async def receive(request):
     Log.debug(f"Received GET request for component " \
         f"{request.rel_url.query['component']}")
     try:
         component = request.rel_url.query['component']
         EventMessage.subscribe(component=component)
         alert = EventMessage.receive()
     except EventMessageError as e:
         status_code = e.rc
         error_message = e.desc
         Log.error(f"Unable to receive event message for component: " \
             f"{component}, status code: {status_code}," \
             f" error: {error_message}")
         response_obj = {'error_code': status_code, 'exception': \
             ['EventMessageError', {'message': error_message}]}
     except Exception as e:
         exception_key = type(e).__name__
         exception = RestServerError(exception_key).http_error()
         status_code = exception[0]
         error_message = exception[1]
         Log.error(f"Internal error while receiving event messages for " \
             f"component: {component}, status code: " \
             f"{status_code}, error: {error_message}")
         response_obj = {'error_code': status_code, 'exception': \
             [exception_key, {'message': error_message}]}
         raise EventMessageError(status_code, error_message) from e
     else:
         status_code = 200  # No exception, Success
         response_obj = {'alert': alert}
         Log.debug(f"GET method finished with status code: {status_code}" \
             f"for component {component} and received event message " \
             f"alert info. - {alert['iem']['info']}.")
     finally:
         return web.Response(text=json.dumps(response_obj), \
             status=status_code)
예제 #7
0
 def __init__(cls):
     try:
         Conf.load('cluster', cls._conf_file)
         ids = Conf.get('cluster', 'server_node')
         cls._site_id = int(ids['site_id'])
         cls._rack_id = int(ids['rack_id'])
         cls._node_id = int(ids['node_id'])
     except Exception as e:
         raise EventMessageError(errno.EINVAL, "Invalid config in %s. %s", \
             cls._conf_file, e)
예제 #8
0
 def receive(cls):
     """ Receive IEM alert message """
     alert = cls._client.receive()
     if alert is not None:
         try:
             return json.loads(alert.decode('utf-8'))
         except Exception as e:
             raise EventMessageError(errno.EPERM, "Unable to load the json. \
                 %s", e)
     return alert
예제 #9
0
    def receive(cls):
        """Receive IEM alert message."""
        if cls._consumer is None:
            Log.error("IEM Consumer is not subscribed")
            raise EventMessageError(errors.ERR_SERVICE_NOT_INITIALIZED,\
                "Consumer is not subscribed")

        alert = cls._consumer.receive()
        Log.debug("Recieved alert: %s" % alert)

        if alert is not None:
            try:
                return json.loads(alert.decode('utf-8'))
            except Exception as e:
                Log.error("unable to parse alert json")
                raise EventMessageError(
                    errno.EPERM, "Unable to load the json. \
                    %s", e)
        return alert
예제 #10
0
    def init(cls, component: str, source: str, receiver: bool = False):
        """ Set the Event Message context """
        cls._component = component
        cls._source = source
        cls()

        if cls._component is None:
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
                cls._component)

        if cls._source not in cls._SOURCE.keys():
            raise EventMessageError(errno.EINVAL, "Invalid source type: %s", \
                cls._source)

        if receiver:
            cls._client = MessageConsumer(consumer_id='event_consumer', \
                consumer_group=cls._component, message_types=['IEM'], \
                auto_ack=True, offset='earliest')
        else:
            cls._client = MessageProducer(producer_id='event_producer', \
                message_type='IEM', method='sync')
예제 #11
0
    def send(cls, module: str, event_id: str, severity: str, message: str, \
        *params):
        """ Sends IEM alert message """

        # Validate attributes before sending
        for attribute in [module, event_id, message]:
            if attribute is None:
                raise EventMessageError(errno.EINVAL, "Invalid IEM attributes \
                    %s", attribute)

        if severity not in cls._SEVERITY_LEVELS:
            raise EventMessageError(errno.EINVAL, "Invalid severity level: %s" \
                , severity)

        alert = json.dumps({
            'iem': {
                'version': '1',
                'info': {
                    'severity': cls._SEVERITY_LEVELS[severity],
                    'type': cls._SOURCE[cls._source],
                    'event_time': time.time()
                    },
                'location': {
                    'site_id': cls._site_id,
                    'node_id': cls._node_id,
                    'rack_id': cls._rack_id
                    },
                'source': {
                    'component': cls._component,
                    'module': module
                    },
                'contents': {
                    'event': event_id,
                    'message': message,
                    'params': params,
                }
            }
        })

        cls._client.send([alert])
예제 #12
0
    def subscribe(cls, component: str, **filters):
        """
        Subscribe to IEM alerts

        Parameters:
        component       Component that generates the IEM. For e.g. 'S3', 'SSPL'
        """
        if component is None:
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
               component)

        cls._consumer = MessageConsumer(consumer_id='event_consumer', \
            consumer_group=component, message_types=['IEM'], \
            auto_ack=True, offset='earliest')
예제 #13
0
    def subscribe(cls, component: str,  message_server_endpoints: str, \
        **message_server_kwargs):
        """
        Subscribe to IEM alerts

        Parameters:
        component       Component that generates the IEM. For e.g. 'S3', 'SSPL'
        """
        if component is None:
            Log.error("Invalid component type: %s" % component)
            raise EventMessageError(errno.EINVAL, "Invalid component type: %s", \
               component)
        MessageBus.init(message_server_endpoints, **message_server_kwargs)
        cls._consumer = MessageConsumer(consumer_id='event_consumer', \
            consumer_group=component, message_types=['IEM'], \
            auto_ack=True, offset='earliest')
        Log.info("IEM Consumer initialized for component: %s" % component)
예제 #14
0
    async def send(request):
        try:
            payload = await request.json()

            component = payload['component']
            source = payload['source']
            EventMessage.init(component=component, source=source,\
                cluster_id=IemRequestHandler.cluster_id,\
                message_server_endpoints=IemRequestHandler.message_server_endpoints)

            del payload['component']
            del payload['source']
            EventMessage.send(**payload)
        except EventMessageError as e:
            status_code = e.rc
            error_message = e.desc
            Log.error(f"Unable to send event message for component: " \
                      f"{component}, status code: {status_code}," \
                      f" error: {error_message}")
            response_obj = {'error_code': status_code, 'exception': \
                ['EventMessageError', {'message': error_message}]}
        except Exception as e:
            exception_key = type(e).__name__
            exception = RestServerError(exception_key).http_error()
            status_code = exception[0]
            error_message = exception[1]
            Log.error(f"Internal error while sending event messages for " \
                f"component: {component}, status code: " \
                f"{status_code}, error: {error_message}")
            response_obj = {'error_code': status_code, 'exception': \
                [exception_key, {'message': error_message}]}
            raise EventMessageError(status_code, error_message) from e
        else:
            status_code = 200  # No exception, Success
            response_obj = {'status_code': status_code, 'status': 'success'}
            Log.debug(f"POST method finished for component: {component} "
                      f"and source: {source}, with status code: {status_code}")
        finally:
            return web.Response(text=json.dumps(response_obj), \
                status=status_code)
예제 #15
0
    def receive(args) -> str:
        """
        Receives IEM Message and returns to the caller, If file[-f] is passed,
        writes message to file and returns blank string to caller
        """

        IemCli.subscribe(component=args.source)
        rec_data = ''
        event = ' '
        while event:
            try:
                event = EventMessage.receive()
                rec_data += Format.dump(event,
                                        'json') + '\n' if event else '\n'
            except Exception:
                raise EventMessageError(
                    errno.EINVAL, "Error occurred while receiving IEM data")
        if args.file:
            with open(args.file, 'a') as fd:
                fd.write(rec_data)
                return ''

        return rec_data
예제 #16
0
    def send(cls, module: str, event_id: str, severity: str, message_blob: str,\
        problem_cluster_id: str = None, problem_site_id: int = None, \
        problem_rack_id: int = None, problem_node_id: int = None, \
        problem_host: str = None, event_time: float = None):
        """
        Sends IEM alert message

        Parameters:
        module              Indicates the sub module of a component that
                            generated the IEM. i.e SSPL submodule like HPI.
        event_id            A numerical value that uniquely identifies an event.
        severity            The degree of impact an event has on the operation
                            of a component.
        message_blob        Blob alert message.
        problem_cluster_id  A alpha numerical value that indicates cluster ID.
                            (Problem Location)
        problem_site_id     Uniquely identifies a single data center site.
                            (Problem Location)
        problem_rack_id     A numerical value that identifies a single Rack in a
                            single site. (Problem Location)
        problem_node_id     A numerical value that indicates node ID. (UUID)
                            (Problem Location)
        problem_host        A string that indicates the hostname.
                            (Problem Location)
        event_time          Time of the event
        """

        import socket
        sender_host = socket.gethostname()

        cls._initiate_logger()
        if cls._producer is None:
            Log.error("IEM Producer not initialized.")
            raise EventMessageError(errors.ERR_SERVICE_NOT_INITIALIZED, \
                "Producer is not initialised")

        site_id = problem_site_id if problem_site_id is not None else \
            cls._site_id
        rack_id = problem_rack_id if problem_rack_id is not None else \
            cls._rack_id
        node_id = problem_node_id if problem_node_id is not None else \
            cls._node_id
        cluster_id = problem_cluster_id if problem_cluster_id is not None else \
            cls._cluster_id
        host = problem_host if problem_host is not None else sender_host

        event_time = event_time if event_time is not None else time.time()
        Log.debug("site_id: %s, rack_id: %s, node_id: %s, cluster_id: %s,\
             host: %s" % (site_id, rack_id, node_id, cluster_id, host))

        # Validate attributes before sending
        for attribute in [module, event_id, message_blob, site_id, rack_id, \
            node_id, cluster_id]:
            if attribute is None:
                Log.error("Invalid IEM attributes %s.", attribute)
                raise EventMessageError(
                    errno.EINVAL, "Invalid IEM attributes \
                    %s", attribute)

        if severity not in cls._SEVERITY_LEVELS:
            Log.error("Invalid severity level: %s." % severity)
            raise EventMessageError(errno.EINVAL, "Invalid severity level: %s" \
                , severity)

        alert = json.dumps({
            'iem': {
                'version': '1',
                'info': {
                    'severity': cls._SEVERITY_LEVELS[severity],
                    'type': cls._SOURCE[cls._source],
                    'event_time': event_time
                },
                'location': {
                    'cluster_id': cluster_id,
                    'site_id': site_id,
                    'rack_id': rack_id,
                    'node_id': node_id,
                    'host': host
                },
                'source': {
                    'site_id': cls._site_id,
                    'rack_id': cls._rack_id,
                    'node_id': cls._node_id,
                    'component': cls._component,
                    'module': module
                },
                'contents': {
                    'event': event_id,
                    'message': message_blob
                }
            }
        })

        cls._producer.send([alert])
        Log.debug("alert sent: %s" % alert)