感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:[email protected]
PS:最近没有登录博客,很多朋友的留言没有看见,这里道歉!还有就是本人较少上QQ,可以邮件交流。
ceilometer报警器服务的实现概览
ceilometer的报警系统包括比较多的内容,比如报警器状态的评估判定方式有两种,即联合报警器状态评估和单一报警器状态评估,而报警器系统的实现也有两种,即单例报警系统和分布式报警系统。而ceilometer的报警器实现都包含在/ceilometer/alarm中,在这篇博客中,我们先来分析/ceilometer/alarm/service.py,来从整体的高度把握报警系统的内容。
在/ceilometer/alarm/service.py中实现了四个类:
类AlarmService:报警服务实现的基类;
类SingletonAlarmService:单例报警系统服务;
类PartitionedAlarmService:分布式报警器系统服务;
类AlarmNotifierService:报警器被触发的通知服务实现;
1 类AlarmService:报警服务实现的基类
这个类是报警系统实现的基类,来看看其中实现的比较重要的方法;
1.1 def_evaluate_assigned_alarms(self)
def _evaluate_assigned_alarms(self): """ 获取当前部分的所有报警器,对每一个报警器进行报警触发的评估判定; 1.获取当前部分的所有报警器; 2.针对每一个报警器,实现根据报警器模式的类型(threshold和combination), 来实现单一报警器模式或者联合报警器模式的评估判定; """ try: # 获取所有报警器列表; # 对于单例报警器:通过指定客户端通过http协议发送GET请求获取分配给当前部分的报警器; alarms = self._assigned_alarms() LOG.info(_('initiating evaluation cycle on %d alarms') % len(alarms)) # 遍历所有的报警器; # 针对每一个报警器,实现根据报警器的类型(threshold和combination),来实现单一报警器模式或者联合报警器模式的评估判定; for alarm in alarms: self._evaluate_alarm(alarm) except Exception: LOG.exception(_('alarm evaluation cycle failed'))
方法小结:
获取当前部分的所有报警器,对每一个报警器进行报警触发的评估判定;
1.获取当前部分的所有报警器;
2.针对每一个报警器,实现根据报警器模式的类型(threshold和combination),来实现单一报警器模式或者联合报警器模式的评估判定;
1.2 def _evaluate_alarm(self, alarm)
def _evaluate_alarm(self, alarm): """ 根据alarm的type,将alarm分配给对应的evaluator进行处理; 单一报警器状态的评估判定; 联合报警器状态的评估判定; """ # self.supported_evaluators = [threshold,combination] if alarm.type not in self.supported_evaluators: LOG.debug(_('skipping alarm %s: type unsupported') % alarm.alarm_id) return LOG.debug(_('evaluating alarm %s') % alarm.alarm_id) # 两种类型报警器ThresholdEvaluator和CombinationEvaluator的evaluate实现; # 单一报警器状态的评估判定; # 联合报警器状态的评估判定; self.evaluators[alarm.type].obj.evaluate(alarm)
2 类SingletonAlarmService:单例的报警服务
这个类是单例报警系统服务的启动实现,主要实现了单例报警系统服务的启动操作;
2.1 def start(self)
def start(self): """ 单例报警器服务SingletonAlarmService的启动操作; 按照一定时间间隔实现循环执行方法self._evaluate_assigned_alarms; 获取alarm集合,针对每一个报警器,实现根据报警器模式的类型(threshold和combination),来实现单一报警器模式或者联合报警器模式的评估判定; """ super(SingletonAlarmService, self).start() if self.evaluators: """ 评估周期60s; """ interval = cfg.CONF.alarm.evaluation_interval # 按照一定时间间隔实现循环执行方法self._evaluate_assigned_alarms; # _evaluate_assigned_alarms: # 先获取alarm集合,对每一个alarm,调用_evaluate_alarm方法; # 针对每一个报警器,实现根据报警器模式的类型(threshold和combination),来实现单一报警器模式或者联合报警器模式的评估判定; self.tg.add_timer( interval, self._evaluate_assigned_alarms, 0) # Add a dummy thread to have wait() working self.tg.add_timer(604800, lambda: None)方法小结:
单例报警器服务SingletonAlarmService的启动操作;
按照一定时间间隔实现循环执行方法self._evaluate_assigned_alarms;
获取alarm集合,针对每一个报警器,实现根据报警器模式的类型(threshold和combination),来实现单一报警器模式或者联合报警器模式的评估判定;
2.2 def _assigned_alarms(self)
def _assigned_alarms(self): """ 通过指定客户端通过http协议发送GET请求获取分配给当前部分的报警器; """ return self._client.alarms.list(q=[{'field': 'enabled', 'value': True}])
这个类是分布式报警系统服务的实现,主要实现了分布式报警系统服务的启动和其他操作;
3.1 def start(self)
def start(self): """ 分布式报警器系统服务分布式报警器系统服务的启动和运行; 按照一定的时间间隔周期性的执行以下操作: 1.实现广播当前partition的存在性的存在性到所有的partition (包括uuid和优先级信息); 2.实现定期检测主控权角色;确定当前的partition是否是主控角色; 如果为拥有主控权的partition,则根据不同的情况实现不同形式的报警器分配操作; 情况1:所有报警器都要实现重新分配操作; 情况2:只有新建立的报警器需要实现分配操作; 3.获取alarm集合,对每一个alarm,调用_evaluate_alarm方法; 针对每一个报警器,实现根据报警器的类型(threshold和combination),来实现: 单一报警器模式或者联合报警器模式的评估判定; """ # 启动PartitionedAlarmService服务; super(PartitionedAlarmService, self).start() if self.evaluators: """ 报警评估周期60s; """ eval_interval = cfg.CONF.alarm.evaluation_interval """ self.tg = threadgroup.ThreadGroup(1000) 按照一定时间间隔实现循环执行方法self.partition_coordinator.report_presence; 通过方法fanout_cast实现广播当前partition的存在性的存在性到所有的partition(包括uuid和优先级信息); """ self.tg.add_timer( eval_interval / 4, # 15s self.partition_coordinator.report_presence, 0) """ 按照一定时间间隔实现循环执行方法self.partition_coordinator.check_mastership; self.partition_coordinator.check_mastership: 实现定期检测主控权角色; 确定当前的partition是否是主控角色; 如果为拥有主控权的partition,则根据不同情况实现不同形式的报警器分配操作; """ self.tg.add_timer( eval_interval / 2, # 30s self.partition_coordinator.check_mastership, eval_interval, # 60s # _client:构建或重新使用一个经过验证的API客户端; *[eval_interval, self._client]) """ add_timer:按照一定时间间隔实现循环执行方法self._evaluate_assigned_alarms; self._evaluate_assigned_alarms: 先获取alarm集合,对每一个alarm,调用_evaluate_alarm方法; 针对每一个报警器,实现根据报警器类型(threshold和combination),来实现: 单一报警器状态的评估判定; 联合报警器状态的评估判定; """ self.tg.add_timer( eval_interval, # 60s # 执行报警器的评估操作; self._evaluate_assigned_alarms, eval_interval) # Add a dummy thread to have wait() working self.tg.add_timer(604800, lambda: None)方法小结:
分布式报警器系统服务分布式报警器系统服务的启动和运行;
按照一定的时间间隔周期性的执行以下操作:
1.实现广播当前partition的存在性的存在性到所有的partition
(包括uuid和优先级信息);
2.实现定期检测主控权角色;确定当前的partition是否是主控角色;
如果为拥有主控权的partition,则根据不同的情况实现不同形式的报警器分配操作;
情况1:所有报警器都要实现重新分配操作;
情况2:只有新建立的报警器需要实现分配操作;
3.获取alarm集合,对每一个alarm,调用_evaluate_alarm方法;
针对每一个报警器,实现根据报警器的类型(threshold和combination),来实现:
单一报警器模式或者联合报警器模式的评估判定;
3.2 def _assigned_alarms(self)
def _assigned_alarms(self): """ 通过指定客户端获取分配给当前部分的报警器; """ return self.partition_coordinator.assigned_alarms(self._client)3.3 def assign(self, context, data)
def assign(self, context, data): """ 接收所收到的报警器ID值,如果uuid和本Partition的uuid相匹配, 则接收报警器ID值,则赋值给assignment; 用于全部报警器的分配操作; """ self.partition_coordinator.assign(data.get('uuid'), data.get('alarms'))3.4 def allocate(self, context, data)
def allocate(self, context, data):
"""
接收所收到的报警器ID值,如果uuid和本Partition的uuid相匹配,
则接收报警器ID值,则存储到assignment中;
用于部分报警器的分配操作;
"""
self.partition_coordinator.allocate(data.get('uuid'),
data.get('alarms'))
4 类AlarmNotifierService:报警器被触发的通知服务实现
这个类所描述的是当报警器被触之后,进行一个报警器报警的通知操作的实现,来看看具体的方法;
4.1 def start(self)
def start(self): """ 服务的启动; 为RPC通信建立到信息总线的连接; 建立指定类型的消息消费者; 启动协程实现等待并消费处理队列中的消息; """ super(AlarmNotifierService, self).start() # Add a dummy thread to have wait() working self.tg.add_timer(604800, lambda: None)
4.2 def _handle_action(self, action, alarm_id, previous, current, reason, reason_data)
def _handle_action(self, action, alarm_id, previous, current, reason, reason_data): """ 获取系统所采用的消息通信方式; 通过HTTPS协议POST方法实现发送相关报警器被触发的通知(or)通过日志记录相关报警器被触发的通知; 采用两种方式之一实现相关报警器的通知: 通过HTTPS协议POST方法实现发送相关报警器的通知; 通过日志记录相关报警器的通知; # action:要通知的action的URL; # alarm_id:被触发的报警器的ID; # previous:报警器(触发)之前的状态; # current:报警器被触发后转换到的新状态; # reason:改变报警器状态的原因; """ try: action = network_utils.urlsplit(action) except Exception: LOG.error( _("Unable to parse action %(action)s for alarm %(alarm_id)s"), {'action': action, 'alarm_id': alarm_id}) return """ 获取系统所采用的消息通信方式; ceilometer.alarm.notifier = log = ceilometer.alarm.notifier.log:LogAlarmNotifier test = ceilometer.alarm.notifier.test:TestAlarmNotifier http = ceilometer.alarm.notifier.rest:RestAlarmNotifier https = ceilometer.alarm.notifier.rest:RestAlarmNotifier """ try: notifier = self.notifiers[action.scheme].obj except KeyError: scheme = action.scheme LOG.error( _("Action %(scheme)s for alarm %(alarm_id)s is unknown, " "cannot notify"), {'scheme': scheme, 'alarm_id': alarm_id}) return """ 通过HTTPS协议POST方法实现发送相关报警器被触发的通知(到action指定的URL),或者是通过日志记录相关报警器的通知; """ try: LOG.debug(_("Notifying alarm %(id)s with action %(act)s") % ( {'id': alarm_id, 'act': action})) notifier.notify(action, alarm_id, previous, current, reason, reason_data) except Exception: LOG.exception(_("Unable to notify alarm %s"), alarm_id) return方法小结:
获取系统所采用的消息通信方式;
通过HTTPS协议POST方法实现发送相关报警器被触发的通知(or)通过日志记录相关报警器被触发的通知;
4.3 def notify_alarm(self, context, data)
def notify_alarm(self, context, data): """ 遍历所有要通知报警器被触发的URL,针对每个要通知的URL地址,实现: 获取系统所采用的消息通信方式; 通过HTTPS协议POST方法实现发送相关报警器被触发的通知(到action指定的URL),(or)通过日志记录相关报警器被触发的通知; 通知内容中包括: alarm_id:被触发的报警器的ID; previous:报警器(触发)之前的状态; current:报警器被触发后转换到的新状态; reason:改变报警器状态的原因; """ actions = data.get('actions') if not actions:def notify_alarm(self, context, data): """ 遍历所有要通知报警器被触发的URL,针对每个要通知的URL地址,实现: 获取系统所采用的消息通信方式; 通过HTTPS协议POST方法实现发送相关报警器被触发的通知(到action指定的URL),(or)通过日志记录相关报警器被触发的通知; 通知内容中包括: alarm_id:被触发的报警器的ID; previous:报警器(触发)之前的状态; current:报警器被触发后转换到的新状态; reason:改变报警器状态的原因; """ actions = data.get('actions') if not actions: LOG.error(_("Unable to notify for an alarm with no action")) return for action in actions: """ 获取系统所采用的消息通信方式; 通过HTTPS协议POST方法实现发送相关报警器被触发的通知(到action指定的URL),(or)通过日志记录相关报警器被触发的通知; """ self._handle_action(action, data.get('alarm_id'), data.get('previous'), data.get('current'), data.get('reason'), data.get('reason_data'))方法小结:
遍历所有要通知报警器被触发的URL,针对每个要通知的URL地址,实现:
获取系统所采用的消息通信方式;
通过HTTPS协议POST方法实现发送相关报警器被触发的通知(到action指定的URL),(or)通过日志记录相关报警器被触发的通知;