Liberty nova-api load app过程跟踪
来源:互联网 发布:唱歌培训软件 编辑:程序博客网 时间:2024/05/01 12:06
本博客欢迎转载,但请注明出处 http://blog.csdn.net/ringoshen/article/details/51334973
由于能力与时间有限,文章内容难免错漏,望大家多加指正,相互进步!
之前的文章中已经分析了nova-api的整体启动流程,但是其中一些重要的细节并没有深入看,今天这篇文章主要看一下nova-api中的loadapp的过程。至于URLMap、APIRouter以及各个Filter的功能流程之后在解析http请求的时候会做一下分析。
接下来还是直接看一下代码。
# nova/service.pyclass WSGIService(service.Service): def __init__(self, name, loader=None, use_ssl=False, max_url_len=None): ... ... ... ... # 接下来2步加载app,app的信息在"/etc/nova/api-paste.ini", # loader = <nova.wsgi.Loader object at 0x7f6f2b5b1ed0> self.loader = loader or wsgi.Loader() # app = <nova.api.openstack.urlmap.URLMap object at 0x7f6f2b541790> # 这边主要返回一个URLMap对象,从名字上就知道是用来根据url路由到app self.app = self.loader.load_app(name) ... ... ... ...
加载app代码跟踪
这边简单跟踪一下整体的代码调用过程,不做细节的介绍。
# nova/wsgi.pyclass Loader(object): ... ... def load_app(self, name): try: LOG.debug("Loading app %(name)s from %(path)s", {'name': name, 'path': self.config_path}) # deploy.loadapp("config:'/etc/nova/api-paste.ini'", name='osapi_compute') return deploy.loadapp("config:%s" % self.config_path, name=name) except LookupError: LOG.exception(_LE("Couldn't lookup app: %s"), name) raise exception.PasteAppNotFound(name=name, path=self.config_path)
之后的流程就开始在paste.deploy中执行。
# paste/deploy/loadwsgi.py# uri = 'config:/etc/nova/api-paste.ini'# name = 'osapi_compute'# kw = {}# APP = _App()def loadapp(uri, name=None, **kw): return loadobj(APP, uri, name=name, **kw)
def loadobj(object_type, uri, name=None, relative_to=None, global_conf=None): # object_type = <application protocols=[['paste.app_factory'], ['paste.composite_factory'], ['paste.composit_factory']] prefixes=[['app', 'application'], ['composite', 'composit'], ['pipeline'], ['filter-app']]> # uri = 'config:/etc/nova/api-paste.ini' # name = 'osapi_compute' # relative_to = None # global_conf = None # 这一个过程十分漫长 context = loadcontext( object_type, uri, name=name, relative_to=relative_to, global_conf=global_conf) return context.create()
def loadcontext(object_type, uri, name=None, relative_to=None, global_conf=None): ... ... ... ... # scheme = 'config' # _loaders['config'] = _loadconfig return _loaders[scheme]( object_type, uri, path, name=name, relative_to=relative_to, global_conf=global_conf)
def _loadconfig(object_type, uri, path, name, relative_to, global_conf): ... ... ... ... # path = '/etc/nova/api-paste.ini' path = unquote(path) # loader = <paste.deploy.loadwsgi.ConfigLoader object at 0x7fe4c77f2e50> loader = ConfigLoader(path) if global_conf: loader.update_defaults(global_conf, overwrite=False) return loader.get_context(object_type, name, global_conf)
class ConfigLoader(_Loader): def __init__(self, filename): # filename = '/etc/nova/api-paste.ini' self.filename = filename = filename.strip() # defaults = {'__file__': '/etc/nova/api-paste.ini', 'here': '/etc/nova'} defaults = { 'here': os.path.dirname(os.path.abspath(filename)), '__file__': os.path.abspath(filename) } self.parser = NicerConfigParser(filename, defaults=defaults) self.parser.optionxform = str # Don't lower-case keys with open(filename) as f: self.parser.read_file(f) def get_context(self, object_type, name=None, global_conf=None): if self.absolute_name(name): return loadcontext(object_type, name, relative_to=os.path.dirname(self.filename), global_conf=global_conf) # section = 'composite:osapi_compute' section = self.find_config_section( object_type, name=name) ... ... ... ... # 循环读取section成local_conf和global_conf for option in self.parser.options(section): if option.startswith('set '): name = option[4:].strip() global_additions[name] = global_conf[name] = ( self.parser.get(section, option)) elif option.startswith('get '): name = option[4:].strip() get_from_globals[name] = self.parser.get(section, option) else: if option in defaults: continue local_conf[option] = self.parser.get(section, option) # local_conf = {'/v2': 'openstack_compute_api_v21_legacy_v2_compatible', '/v2.1': 'openstack_compute_api_v21', 'use': 'call:nova.api.openstack.urlmap:urlmap_factory', '/': 'oscomputeversions'} # global_conf = {'__file__': '/etc/nova/api-paste.ini', 'here': '/etc/nova'} ... ... ... ... if section.startswith('filter-app:'): context = self._filter_app_context( object_type, section, name=name, global_conf=global_conf, local_conf=local_conf, global_additions=global_additions) elif section.startswith('pipeline:'): context = self._pipeline_app_context( object_type, section, name=name, global_conf=global_conf, local_conf=local_conf, global_additions=global_additions) elif 'use' in local_conf: context = self._context_from_use( object_type, local_conf, global_conf, global_additions, section) else: context = self._context_from_explicit( object_type, local_conf, global_conf, global_additions, section) if filter_with is not None: filter_with_context = LoaderContext( obj=None, object_type=FILTER_WITH, protocol=None, global_conf=global_conf, local_conf=local_conf, loader=self) filter_with_context.filter_context = self.filter_context( name=filter_with, global_conf=global_conf) filter_with_context.next_context = context return filter_with_context return context def _context_from_use(self, object_type, local_conf, global_conf, global_additions, section): # 这边真正取到urlmap_factory # use = 'call:nova.api.openstack.urlmap:urlmap_factory' use = local_conf.pop('use') context = self.get_context( object_type, name=use, global_conf=global_conf) context.global_conf.update(global_additions) context.local_conf.update(local_conf) if '__file__' in global_conf: context.global_conf['__file__'] = global_conf['__file__'] context.loader = self if context.protocol is None: section_protocol = section.split(':', 1)[0] if section_protocol in ('application', 'app'): context.protocol = 'paste.app_factory' elif section_protocol in ('composit', 'composite'): context.protocol = 'paste.composit_factory' else: context.protocol = 'paste.%s_factory' % section_protocol return context
之后又调用回loadcontext方法。
def loadcontext(object_type, uri, name=None, relative_to=None, global_conf=None): ... ... ... ... # 此处开始加载urlmap的步骤 # scheme = 'call' # _loaders['call'] = _loadfunc return _loaders[scheme]( object_type, uri, path, name=name, relative_to=relative_to, global_conf=global_conf)
def _loadfunc(object_type, uri, spec, name, relative_to, global_conf): loader = FuncLoader(spec) return loader.get_context(object_type, name, global_conf)
class FuncLoader(_Loader): def __init__(self, spec): self.spec = spec if not ':' in spec: raise LookupError("Configuration not in format module:function") def get_context(self, object_type, name=None, global_conf=None): # 从uri -> module的过程主要是通过这个方法实现,实现方式主要是动态加载 # module = __import__(parts) obj = lookup_object(self.spec) return LoaderContext(obj, object_type, None, global_conf or {}, {}, self,)
class LoaderContext(object): def __init__(self, obj, object_type, protocol, global_conf, local_conf, loader, distribution=None, entry_point_name=None): self.object = obj self.object_type = object_type self.protocol = protocol self.global_conf = global_conf self.local_conf = local_conf self.loader = loader self.distribution = distribution self.entry_point_name = entry_point_name # 之前的create方法的定义在此 def create(self): return self.object_type.invoke(self)
这是之前APP = _App()的定义
class _App(_ObjectType): name = 'application' egg_protocols = ['paste.app_factory', 'paste.composite_factory', 'paste.composit_factory'] config_prefixes = [['app', 'application'], ['composite', 'composit'], 'pipeline', 'filter-app'] def invoke(self, context): if context.protocol in ('paste.composit_factory', 'paste.composite_factory'): return fix_call(context.object, context.loader, context.global_conf, **context.local_conf) elif context.protocol == 'paste.app_factory': return fix_call(context.object, context.global_conf, **context.local_conf) else: assert 0, "Protocol %r unknown" % context.protocol
之后调用了公共模块
# paste/deploy/util.pydef fix_call(callable, *args, **kw): """ Call ``callable(*args, **kw)`` fixing any type errors that come out. """ try: # ###### 此处真正调用urlmap_factory工厂方法 ###### val = callable(*args, **kw) except TypeError: exc_info = fix_type_error(None, callable, args, kw) reraise(*exc_info) return val
# nova/api/openstack/urlmap.pydef urlmap_factory(loader, global_conf, **local_conf): if 'not_found_app' in local_conf: not_found_app = local_conf.pop('not_found_app') else: not_found_app = global_conf.get('not_found_app') if not_found_app: not_found_app = loader.get_app(not_found_app, global_conf=global_conf) urlmap = URLMap(not_found_app=not_found_app) for path, app_name in local_conf.items(): path = paste.urlmap.parse_path_expression(path) # 类似的方法加载section里面的各类app app = loader.get_app(app_name, global_conf=global_conf) urlmap[path] = app return urlmap
至此,加载app的方法调用过程就走完一遍了,已经加载到我们需要的urlmap_factory,至于urlmap里面的app的加载方式跟上述方式整体上是大致一样的,这里不继续跟踪,不过可以看一下filter包裹app的过程。
# nova/api/auth.py# 在Liberty版本中采用的openstack compute api是v2.1def pipeline_factory_v21(loader, global_conf, **local_conf): """A paste pipeline replica that keys off of auth_strategy.""" return _load_pipeline(loader, local_conf[CONF.auth_strategy].split())
# nova/api/auth.pydef _load_pipeline(loader, pipeline): # 加载pipeline中各个filter filters = [loader.get_filter(n) for n in pipeline[:-1]] # 加载app(osapi_compute_app_v21) app = loader.get_app(pipeline[-1]) # 倒序filter filters.reverse() # 反复使用filter包装app for filter in filters: app = filter(app) return app
0 0
- Liberty nova-api load app过程跟踪
- Liberty nova-api启动流程分析
- Liberty nova-api HTTP请求执行流程
- Openstack liberty中nova-compute服务的启动过程
- Nova Liberty blueprints
- [nova]nova api执行过程分析
- Openstack nova-api 处理过程
- OpenStack Liberty部署Nova-Docker
- Openstack liberty 中Cinder-api启动过程源码分析1
- Openstack liberty 中Cinder-api启动过程源码分析2
- nova api执行过程(以nova list为例)
- openstack nova 创建虚拟机流程 liberty版本
- openstack nova schduler服务分析 liberty版本
- Nova API
- nova-api对web请求的路由过程的分析
- openstack nova 源码解析 — Nova API 执行过程从(novaclient到Action)
- 【Nova】nova-api-metadata学习
- 手动安装liberty版本openstack环境(allinone)---安装nova
- PAT-B 1037. 在霍格沃茨找零钱
- 木化html
- iOS之数据加密
- HDU 2163 Palindromes
- iOS开发之原生二维码生成
- Liberty nova-api load app过程跟踪
- 第10周项目一-点-圆-圆柱类的设计(1)
- 窗体的使用
- 欢迎使用CSDN-markdown编辑器
- 一步步分析百度音乐的播放地址,利用Python爬虫批量下载
- 将按钮添加到窗体
- 《剑指offer》-反转链表
- poj 3177 3352 边双连通分量
- LeetCode------Majority Element