前一段时间参加了一个比赛,大体是应用和扩展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)