ceilometer polling agents源码分析

来源:互联网 发布:玛雅软件下载 编辑:程序博客网 时间:2024/06/06 07:07

ceilometer polling agents源码分析


ceilometer polling agents


ceilometer数据采集polling agents 和 notification agents完成; polling agents是主动轮询所关心的数据;notification agents则是由各个模块上报数据到notificaton队列,然后再由ceilometer notification agents抓取队列消息进行处理;经过polling agents和notification agents处理后的数据最后会发送到notification队列,由ceilometer collector收集写入数据库或做其它处理。



概述


polling agent分为compute、central和ipmi三部分,分别对应不同的服务,使用同一套代码;在启动服务时,传入不同的参数(compute/central/ipmi),以此来加载对应的entry_points,实现轮询不同的pollster数据。


tecs3.0(Openstack Mitaka)版本ceilometer总体架构


ceilometer收集数据示意图


ceilometer提供两种方式收集数据:

1、从notifications队列取消息转换为ceilometer samples



notification agents监听notification队列,除了ceilometer内部通信,nova/glance/neutron/cinder/swift/keystone/heat等都向该队列发送上报数据。Notification agents守护进程使用ceilometer.notification加载一个或多个listener插件。每一个插件可以监听任意topics,但默认监听notificaton.info。监听插件根据指定的topics抓取数据,并把它们重新发布到合适的插件(endpoints)以处理成events和samples。

2、polling agents 以固定时间间隔通过轮询其它模块API或其它工具收集数据



polling agent可以配置为轮询本地hypervisor或者APIs。
计算资源的轮询是由polling compute agent处理的,它在计算节点执行(访问hypervisor更有效)。polling 通过服务API轮询非计算资源的处理是由运行在控制节点的polling central agent完成的。

ceilometer-polling启动流程


通过启动service时传入的参数确认启动'compute', 'central', 'ipmi'中的一个。


pollster-list用于确认加载哪些entry_points;如果为[],则加载所有的entry_points,否则加载pollster-list对应的entry_points ceilometer\ceilometer\cmd\polling.pyCLI_OPTS = [    MultiChoicesOpt('polling-namespaces',                    default=['compute', 'central'],                    choices=['compute', 'central', 'ipmi'],                    ……),    MultiChoicesOpt('pollster-list',                    default=[],                    ……),

]


def main():    service.prepare_service()    os_service.launch(CONF, manager.AgentManager(CONF.polling_namespaces,                                                 CONF.pollster_list)).wait()
初始化操作主要实现了以下内容的操作:
1、先根据指定参数(compute/central/ipmi)获取命名空间ceilometer.poll.compute|central|ipmi,然后获取与该命名空间相匹配的所有插件,并加载;该命名空间所指定的插件描述了如何获取采样数据;
2、获取命名空间ceilometer.discover,获取与ceilometer.discover相匹配的所有插件,并加载;ceilometer.discover所指定的插件描述了如何发现主机上的需要监控的资源。
ceilometer\ceilometer\agent\manager.pyclass AgentManager(service_base.BaseService):     def __init__(self, namespaces=None, pollster_list=None):         namespaces = namespaces or ['compute', 'central']         pollster_list = pollster_list or []

         ……


         #加载entry_points.txt中namespace对应插件         extensions = (self._extensions('poll', namespace).extensions                       for namespace in namespaces)

         ……


         if pollster_list:             extensions = (moves.filter(_match, exts)                           for exts in extensions)

             ……


         self.extensions = list(itertools.chain(*list(extensions))) + list(             itertools.chain(*list(extensions_fb)))

         ……


         #获取用于polling agents处理后要发送数据的消息队列         self.notifier = oslo_messaging.Notifier(             messaging.get_transport(),             driver=cfg.CONF.publisher_notifier.telemetry_driver,             publisher_id="ceilometer.polling")

         ……


服务启动流程代码:
1、lanch(……) ->  ServiceLauncher -> Launcher. launch_service() -> Services.add(……)
2、ServiceLauncher.wait() -> Launcher.restart() -> Services.restart() -> Services.run_service()
3、调用ceilometer.agent.manager. AgentManager. start()oslo_service\service.pydef launch(conf, service, workers=1):

    ……


    if workers is None or workers == 1:        launcher = ServiceLauncher(conf)        launcher.launch_service(service)    else:        ……    return launcher……class Launcher(object):    ……    def launch_service(self, service):        ……        self.services.add(service)    ……    def restart(self):        self.conf.reload_config_files()        self.services.restart()class ServiceLauncher(Launcher):    def wait(self):        ……        while True:            ……            self.restart()        super(ServiceLauncher, self).wait()        return status……class Services(object):    def restart(self):        ……        for restart_service in self.services:            restart_service.reset()            self.tg.add_thread(self.run_service, restart_service, self.done)    @staticmethod    def run_service(service, done):        try:            service.start()

        ……


如下代码所做的处理:
1、读取配置文件pipeline.yaml,获取所有的sources配置。
2、以每个meter项的interval为key创建定时任务列表,并其添加到对应采集周期的定时任务列表中。
ceilometer\ceilometer\agent\manager.pyclass AgentManager(service_base.BaseService):

    def start(self):


        #加载pipeline.yaml文件,读取source信息        self.polling_manager = pipeline.setup_polling()

        ……


        #根据每个meter的interval创建PollingTask        self.pollster_timers = self.configure_polling_tasks()        self.init_pipeline_refresh()
注意:因pipeline.yaml里的meter_source项的默认配置是"\*",故entry_points.txt里定义的所有采集指标都会有对应一个采集并上报原始数据任务并加入600s的任务列表里。如果不想上报原始数据,则配置项应改为:"!*"
/etc/ceilometer/pipeline.yaml:sources:    - name: meter_source      interval: 600      meters:          - "*"      sinks:          - meter_sink

ceilometer-polling模块定时轮询流程


加载pipeline.yaml配置,通过interval分类创建timer,相同interval的pollster会同时触发。


ceilometer\ceilometer\agent\manager.pyclass AgentManager(service_base.BaseService):    def configure_polling_tasks(self):

        ……


        #以interval为key创建轮询任务        data = self.setup_polling_tasks()        for interval, polling_task in data.items():

            ……


            #创建定时轮询任务            pollster_timers.append(self.tg.add_timer(interval,                                   self.interval_task,                                   initial_delay=delay_time,                                   task=polling_task))        ……    def setup_polling_tasks(self):        ……                    #以interval为key创建轮询任务                    polling_task = polling_tasks.get(source.get_interval())                    if not polling_task:                        polling_task = self.create_polling_task()                        polling_tasks[source.get_interval()] = polling_task
                    #加入轮询数据调用的方法(函数),格式见下段entry_points.txt内容                    polling_task.add(pollster, source)        return polling_tasks    def interval_task(self, task):

        ……


        #开始轮询数据        task.poll_and_notify()class PollingTask(object):    def poll_and_notify(self):                ……                try:                    #轮询获取meter数据                    samples = pollster.obj.get_samples(                        manager=self.manager,                        cache=cache,                        resources=polling_resources                    )                    for sample in samples:

                        ……


                        #将samples送到notification消息队列,由notification agents做转换后再发布                        if self._batch:                            sample_batch.append(sample_dict)                        else:                            self._send_notification([sample_dict])                    if sample_batch:                        self._send_notification(sample_batch)                ……entry_points.txt...[ceilometer.poll.compute]cpu = ceilometer.compute.pollsters.cpu:CPUPollster... 举例:下面的代码的功能是获取对应虚机的cpu使用时间。
ceilometer\ceilometer\compute\pollsters\cpu.pyclass CPUPollster(pollsters.BaseComputePollster):    def get_samples(self, manager, cache, resources):        for instance in resources:

            try:


                #调用libvirt接口获取cpu使用时间                cpu_info = self.inspector.inspect_cpus(instance)

                cpu_num = {'cpu_number': cpu_info.number}


                #生成sample并返回                yield util.make_sample_from_instance(                    instance, name='cpu',                    type=sample.TYPE_CUMULATIVE,                    unit='ns', volume=cpu_info.time,                    additional_metadata=cpu_num,                )            ……
参考资料


https://github.com/openstack/ceilometer/tree/stable/mitaka

http://docs.openstack.org/developer/ceilometer/architecture.html?highlight=aodh

0 0
原创粉丝点击