首页 技术与阅读 生活 关于我

OpenStack Ceilometer -- API调用流程分析

文档

本文在讲什么

本文的讲解是基于目前ceilometer最新的Liberty版本

Article About

在文章Ceilometer数据采集原理中曾提到(这也是来自于官方文档的说法)三种从Ceilometer获取数据的方式:

从这三种方式的描述来看,我们知道从Ceilometer获取数据的方式归根结底还是通过RESTful API来实现的。

本文就尝试讲述一下,通过python-ceilometerclient提供的ceilometer命令来获取数据的全过程,也就是命令ceilometer --debug meter-list来获取监控项列表的过程,也即上图中蓝色部分。

基础知识

下面这些基础知识在上面文档部分都可以找到相应的文档作为参考,理解了这些基础知识对理解ceilometer API的调用流程非常有帮助,我对这些也是处于一知半解的状态:)

什么是RESTful API、WSGI、pecan

RESTful API

REST的全称是Representational State Transfer(表征状态转移),是Roy Fielding在他的博士论文Architectural Styles and the Design of Network-based Software Architecture中提出的一种软件架构风格,而我们一般把满足这种设计风格的API称为RESTful API。

具体到使用Python来提供RESTful API时,又提出了一个WSGI的规范。

WSGI

WSGI

WSGI的全称是Web Server Gateway Interface(Web服务器网关接口),是python语言中所定义的Web服务器和Web应用程序或框架之间的通用接口标准,它对应于Java中的Servelet。

下面是一些学习资源:

Pecan

在OpenStack的项目中实现RESTful API的Web框架主要有两种方式:

在OpenStack早期的项目中(Nova, Nutron, Keystone)都是使用的Paste + PasteDeploy + Routes + WebOb,这样的框架好处在于灵活性,但后来它的灵活性并没有抵消它的复杂性,于是在OpenStack后来的项目中也就不再使用这个框架了,但对于理解这些早期项目仍很有必要好好学习这种框架,尤其是这些早期项目都是OpenStack中最重要的一些项目。

Pecan是一个轻量级的Python的Web框架,OpenStack中的新项目全面的使用了此框架(如magnum),Pecan还可以和PasteDeploy一起使用,Ceilometer就是如此。

ceilometer --debug meter-list的调用流程分析

大概过程

python-ceilometerclient

python-ceilometerclient为我们提供了ceilometer命令,通过该命令我们可以很方面的调用ceilometer提供的API。 在搭建好的环境中执行ceilometer --debug meter-list,我们除了可以得到数据库中meter列表外,还可以看到如下的curl命令: curl -i -X GET -H 'X-Auth-Token: 968b7f741482416899f477a8e3aafba7' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'User-Agent: python-ceilometerclient' http://172.31.2.51:8777/v2/meters ,在这条命令中比较关键的是: http://172.31.2.51:8777/v2/meters ,下面我们就分析ceilometer收到这个HTTP请求后是如何解析,如何使用Python Application去查询MongoDB数据库的

讲解过程会先给出一段文字解说,然后再给出相应的源码,看文字解说一定要阅读相应的源码方能更好理解。

Python Application的创建过程

需要使用Python Application来接收HTTP请求,因此需要先创建Python Application。下面我们介绍使用Pecan+PasetDeploy创建Python Application的过程。

在配置文件api_pasete.ini中我们可以看到,PasteDeploy会调用ceilometer.api.app:app_factory。

下面我们再到../ceilometer/api/app.py中查看app_factory函数,可以看到app_factory函数返回的是一个VersionSelectorApplication类,VersionSelectorApplication是为了创建不同版本的Python Application,其中v1版本是不能用的,如果是v2版本则会去调用setup_app函数。

setup_app函数就是真正创建Python Application的函数,在此函数中最重要的就是调用了pecan.make_app函数,在此函数中最重要的就是指定了解析HTTP Request的RootController,是通过pecan_config.app.root参数指定的;另外一个重要的地方就是hoooks.DBHook,在这里面初始化了数据库的链接,关于这一点后面再做介绍。

在上面我们提到解析HTTP请求的RootController是通过pecan_config.app.root参数指定的,阅读代码可知pecan_config.app.root就是config.py中指定的,也就是ceilometer.api.controllers.root.RootController。这样Python Application就创建完成了,并且指定好了解析HTTP Request的RootController,也就是说/v2/meters/从RootController开始处理。

HTTP请求的解析过程

在RootController我们可以看到它先创建了一个类属性:v2,于是所有的以/v2开头的HTTP Request都会由V2Controller来处理,/v2/meters/当然也不例外。

下面我们再去看V2Controller,我们可以看到它有类属性:event_types,events,capabilities,也就是说/v2/event_types会由EventTypesController来处理,/v2/events/会由EventsController来处理,/v2/capabilities/会由CapabilitiesController来处理,那/v2/meters/呢?往下看,在_lookup函数中我们可以看到/v2/meters/会由MetersController来处理,关于__lookup可以参看官方文档。

终于到了MetersController,这里就是最终处理HTTP请求:/v2/meters/的地方,貌似要结束了的样子。在这里最重要的就是最后那一行代码:return [Meter.from_db_model(m) for m in pecan.request.storage_conn.get_meters(limit=limit,**kwargs)],在这行代码中有两个重要的函数调用:pecan.request.storage_conn.get_meters 以及 Meter.from_db_model。所以还没结束,下面还得分析这两个函数是如何执行的。

pecan.request.storage_conn.get_meters的执行过程

要分析pecan.request.storage_conn.get_meters(limit=limit, **kwargs)的执行过程我们分两步:一是storage_conn是如何获得的,二是get_meters是如何执行的 。

stroage_conn的获得过程

storage_conn指的是数据库的链接,在DBHook.__init__中可以看出它是通过调用函数get_connection来获得的,而函数get_connection又调用了函数storage.get_connection_from_config。

下面再看storage.get_connection_from_config函数是如何执行的,函数storage.get_connection_from_config调用了函数storage.get_connection,而在函数storage.get_connection中重要的是: mgr = driver.DriverManger(namespace, engine_name),其中的driver为:from stevedore import driver,namespace为:ceilometer.meterings.storage,engine_name为:mongodb。于是stevedore会到setup.cfg中查找相应的设置。

在../setup.cfg中能看到storage_conn会被赋值为ceilometer.storage.impl_monogodb:Connection,然后就会调用该Connection的__init__函数进行初始化。

在ceilometer.storage.imple_mongodb.Connection类的初始化函数中会初始化数据库的连接,没有相应collection的情况下新建相应collection,设置ttl等。

get_meters的执行过程

这里有一个类的继承关系:object <-- storage.base.Connection <-- storage.pymongo_base.Connection <-- storage.impl_mongodb.Connection,关于storage.impl_mongodb.Connection需要讲的都在上面提到了。

在storage.base.Connection中给出了一些函数定义,但都没有具体的实现。

在storage.pymongo_base.Connection中给出了get_meters的定义,在这里我们就可以真正的看到查询数据库的语句了: self.db.resource.find(q),下面我们还要解释一下语句models.Meter。

这里又有一个类的继承关系:object <-- storage.base.Model <-- storage.models.Meter。 这里其实就是把查询到的值和键做个对应的设置。

Meter.from_db_model(m)的执行过程

pecan.request.storage_conn.get_meters的执行过程讲解完毕,终于要到最后一部分了:Meter.from_db_model(m)。

这里有个类的继承关系:wsme.types.Base <-- wsme.types.DynamicBase <-- api.controllers.v2.base.Base <-- api.v2.meters.Meter

后面api.v2.meters.Meter的初始化函数调用了wsme.types.Base.__init__函数。 对于wsme和pecan有的时候看源码比看文档来得快而准确。

函数Meter.from_db_model定义在ceilometer.api.controllers.v2.base:Base中,函数Meter.from_db_model是把返回的ceilometer.storage.models.Meter实例, 进一步做一些简单的处理。

Meter是在ceilometer.api.v2.meters中定义的,Meter中定义它的的类属性:name, type, unit, resource_id, project_id, user_id, source, meter_id;Meter中还定义了初始化函数__init__,该初始化函数主要是构造meter_id和调用wsme.types.Base的初始化函数__init__

最后

还是有很多细节问题没有弄清,需要继续研究

comments powered by Disqus

技术与阅读

生活

关于我