码迷,mamicode.com
首页 > 其他好文 > 详细

Ceilometer RESTful框架

时间:2016-02-01 20:25:38      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

ceilometer-api使用pecan和flask来构建restful api,这里简单介绍一下pecan和flask的使用。

ceilomter-api服务启动流程

/usr/bin/ceilometer-api

...
from ceilometer.cli import api

if __name__ == "__main__":
    sys.exit(api())
...

 

/usr/lib/python2.6/site-packages/ceilometer/cli.py

...
def api(): service.prepare_service() srv = app.build_server() srv.serve_forever()
...

 

/usr/lib/python2.6/site-packages/ceilometer/api/app.py

...
def build_server(): # Build the WSGI app root = VersionSelectorApplication() # Create the WSGI server and start it host, port = cfg.CONF.api.host, cfg.CONF.api.port server_cls = get_server_cls(host) srv = simple_server.make_server(host, port, root, server_cls)
...
...
class VersionSelectorApplication(object): def __init__(self): pc = get_pecan_config() pc.app.debug = CONF.debug pc.app.enable_acl = (CONF.auth_strategy == ‘keystone‘) if cfg.CONF.enable_v1_api: from ceilometer.api.v1 import app as v1app self.v1 = v1app.make_app(cfg.CONF, enable_acl=pc.app.enable_acl) else: def not_found(environ, start_response): start_response(‘404 Not Found‘, []) return [] self.v1 = not_found self.v2 = setup_app(pecan_config=pc) def __call__(self, environ, start_response): if environ[‘PATH_INFO‘].startswith(‘/v1/‘): return self.v1(environ, start_response) return self.v2(environ, start_response)
...

如上图所示,ceilometer-api有两种版本即V1和V2,分别使用Flask和Pecan来构建RESTful api,其中V1在Havana已deprecated。

 

Pecan 是轻量的web框架,主页http://pecan.readthedocs.org/ ,其中URL Mapping如下图:

技术分享

ceilometer使用pecan代码如下:

/usr/lib/python2.6/site-packages/ceilometer/api/app.py

 

...
def setup_app(pecan_config=None, extra_hooks=None): # FIXME: Replace DBHook with a hooks.TransactionHook app_hooks = [hooks.ConfigHook(), hooks.DBHook( storage.get_connection(cfg.CONF, ‘metric‘), storage.get_connection(cfg.CONF, ‘event‘), ), hooks.PipelineHook(), hooks.TranslationHook()] if extra_hooks: app_hooks.extend(extra_hooks) if not pecan_config: pecan_config = get_pecan_config() pecan.configuration.set_config(dict(pecan_config), overwrite=True) app = pecan.make_app( pecan_config.app.root, static_root=pecan_config.app.static_root, template_path=pecan_config.app.template_path, debug=CONF.debug, force_canonical=getattr(pecan_config.app, ‘force_canonical‘, True), hooks=app_hooks, wrap_app=middleware.ParsableErrorMiddleware, guess_content_type_from_ext=False ) if getattr(pecan_config.app, ‘enable_acl‘, True): return acl.install(app, cfg.CONF) return app
...

ceilometer中pecan的配置 /usr/lib/python2.6/site-packages/ceilometer/api/config.py

...
app = { ‘root‘: ‘ceilometer.api.controllers.root.RootController‘, ‘modules‘: [‘ceilometer.api‘], ‘static_root‘: ‘%(confdir)s/public‘, ‘template_path‘: ‘%(confdir)s/ceilometer/api/templates‘, }
...

RootController /usr/lib/python2.6/site-packages/ceilometer/api/controllers/root.py

...
class RootController(object): v2 = v2.V2Controller() @pecan.expose(generic=True, template=‘index.html‘) def index(self): # FIXME: Return version information return dict()
...

V2Controller包含多个Resource的Controller, /usr/lib/python2.6/site-packages/ceilometer/api/controllers/v2.py

class V2Controller(object):
    """Version 2 API controller root."""

    resources = ResourcesController()
    meters = MetersController()
    samples = SamplesController()
    alarms = AlarmsController()
    event_types = EventTypesController()
    events = EventsController()
    status = StatusController()
    query = QueryController()
    capabilities = CapabilitiesController()

下面以MetersController进行分析:/usr/lib/python2.6/site-packages/ceilometer/api/controllers/v2.py

class MetersController(rest.RestController):
    """Works on meters."""

    @pecan.expose()
    def _lookup(self, meter_name, *remainder):
        return MeterController(meter_name), remainder

#wsme_pecan是来自wsmeext.pecan @wsme_pecan.wsexpose([Meter], [Query]) def get_all(self, q=[]): """Return all known meters, based on the data recorded so far. :param q: Filter rules for the meters to be returned. """ #Timestamp field is not supported for Meter queries kwargs = _query_to_kwargs(q, pecan.request.metric_conn.get_meters, allow_timestamps=False) return [Meter.from_db_model(m) for m in pecan.request.metric_conn.get_meters(**kwargs)]

   这里用到了wsme和wsmeext.pecan。wsme即Web Services Made Easy,简化了REST Web服务的编写。可以运行在另一个框架的顶层,如(Cornice、Flask、Pecan)等,这里就是运行在了pecan之上来更加简单的构建restapi,用法:

wsmeext.pecan.wsexpose(return_type, *arg_types, **options)

 

Flask与Pecan类似,是基于Python的开源微RESTful框架,ceilometer使用Flask代码如下: /usr/lib/python2.6/site-packages/ceilometer/api/v1/app.py

...
def make_app(conf, enable_acl=True, attach_storage=True, sources_file=‘sources.json‘): app = flask.Flask(‘ceilometer.api‘) app.register_blueprint(v1_blueprint.blueprint, url_prefix=‘/v1‘) app.json_encoder = JSONEncoder try: with open(sources_file, "r") as f: sources = jsonutils.load(f) except IOError: sources = {} @app.before_request def attach_config(): flask.request.cfg = conf flask.request.sources = sources if attach_storage: @app.before_request def attach_storage(): flask.request.storage_conn = storage.get_connection(conf) # Install the middleware wrapper if enable_acl: app.wsgi_app = acl.install(app.wsgi_app, conf) return app
...
app.register_blueprint 注册RESTful方法,如下图示
blueprint = flask.Blueprint(‘v1‘, __name__,
                            template_folder=‘templates‘,
                            static_folder=‘static‘)

@blueprint.route(‘/meters‘)
def list_meters_all():
    """Return a list of meters.
    :param metadata.<key>: match on the metadata within the resource.
                           (optional)
    """
    rq = flask.request
    meters = rq.storage_conn.get_meters(
        project=acl.get_limited_to_project(rq.headers),
        metaquery=_get_metaquery(rq.args))
    return flask.jsonify(meters=[m.as_dict() for m in meters])

Ceilometer RESTful框架

标签:

原文地址:http://www.cnblogs.com/multi-task/p/5175892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!