OpenStack ironic发送物理机SEL信息到Ceilometer,openstackceilometer


前一段时间参加了一个比赛,大体是应用和扩展OpenStack,需求如下图所示:


Ironic管理和控制物理机,通过周期性的在物理机上执行ipmitool命令获取物理机的SEL(system event log)信息,Ironic通过AMQP协议将收集的SEL信息发送到Ceilometer,Ceilometer将收集的SEL信息持久化,并在Horizon中显示SEL信息。

这里简单介绍一下在Ironic端发送SEL信息、在Ceilometer端接收SEL信息的实现。

Ironic发送SEL信息代码如下,在ironic.conductor.manager.py中修改:

    @periodic_task.periodic_task(
            spacing=CONF.conductor.send_sel_data_interval)
    def _send_sel_data(self, context):
        # do nothing if send_sel_data option is False
        if not CONF.conductor.send_sel_data:
            return
        
        columns = ['uuid', 'driver']
        node_list = self.dbapi.get_nodeinfo_list(columns=columns)

        for (node_uuid, driver) in node_list:
            try:
                with task_manager.acquire(context,node_uuid,shared=True) as task:
                    task.driver.management.validate(task)
                    sel_data = task.driver.management.get_sel_data(task)
                    for one_sel in sel_data:
                        message = {'record_id':one_sel[0],'record_type':one_sel[1],
                                   'timestamp':one_sel[2],'level':one_sel[3],
                                   'description':one_sel[4],'info':str(one_sel[5]),
                                   'node_uuid':node_uuid,'event_type':'hardware.sel.update'}
                        self.notifier.info(context, "hardware.sel.metric",message)
            except NotImplementedError:
                LOG.warn(_LW('get_sel_data is not implemented for driver'
                    ' %(driver)s, node_uuid is %(node)s'),
                    {'node': node_uuid, 'driver': driver})
            except exception.NodeNotFound:
                LOG.warn(_LW("During send_sel_data, node %(node)s was not "
                           "found and presumed deleted by another process."),
                           {'node': node_uuid})
            except Exception as e:
                LOG.warn(_LW("Failed to get sel data for node %(node)s. "
                    "Error: %(error)s"), {'node': node_uuid, 'error': str(e)})

在Ceilometer端每收到一次消息就往数据库中添加一条sample记录,这个sample记录不管消息重复不重复都添加到sample中,但一条SEL记录还包括其他数据,这些其他数据是sample的resource数据,这些resource数据在数据库中不存在重复,在插入数据库之前首先进行查询操作,如果存在就不插入;resource数据按key-value的形式存放在数据库中,并按照key值类型的不同(int, string等),分布在四个不同的表中。在Ceilometer接收和存储代码如下:

class SelNotification(plugin.NotificationBase):

    event_types = ['hardware.sel.metric']

    @staticmethod
    def get_targets(conf):
        """oslo.messaging.TargetS for this plugin."""
        return [messaging.Target(topic=topic,
                                 exchange=conf.ironic_exchange)
                for topic in conf.notification_topics]

    def process_notification(self, message):
        logger.info('received SEL message: '+str(message))
        
        yield sample.Sample.from_notification(
            name='hardware.sel',
            type=sample.TYPE_GAUGE,
            unit='SEL',
            volume='1',
            resource_id=message['payload']['node_uuid'],
            message=message['payload'],
            user_id=None,
            project_id=None)


相关内容