• cinder api启动过程源码分析


    1、启动cinder-api服务

    当你通过cinder-api命令(如:/usr/bin/cinder-api --config-file /etc/cinder/cinder.conf)启动api服务时,执行的实际上是
    cinder/cmd/api.py/main()函数, 如下:

    [root@xgto02n010027244133 ~]# cat /usr/bin/cinder-api
    #!/usr/bin/python2
    # PBR Generated from u'console_scripts'
    import sys
    from cinder.cmd.api import main
    if __name__ == "__main__":
        sys.exit(main())
    

    cinder/cmd/api.py/main()函数,内容如下:

    def main():
    	
        objects.register_all() #加载辅助对象,封装与数据库相关的操作
        gmr_opts.set_defaults(CONF) #oslo_reports模块,用于生成错误报告,如内存泄漏等
        CONF(sys.argv[1:], project='cinder',
             version=version.version_string())
        config.set_middleware_defaults()
        logging.setup(CONF, "cinder")
        python_logging.captureWarnings(True)
        utils.monkey_patch() # monkey-patch,替换库比如socket、thread等,不改变import的行为,改变的是操作的指向函数
    
        gmr.TextGuruMeditation.setup_autorun(version, conf=CONF)
        """初始化rpc:
        设置全局Transport和Notifier,Transport是
        oslo_messaging/transport.py/Transport实例,我采用的是默认的
        rpc_backend=rabbit,所以Transport采用的driver=oslo_messaging/
        _drivers/impl_rabbit.py/RabbitDriver;Notifier是一个通知消息发
        送器,它借助Transport将通知发送发送给ceilometer
        """
        rpc.init(CONF)
    	#通过服务启动器启动WSGI服务(`osapi_volume`)并等待服务启动成功
        #在初始化WSGI服务时,会设置路由映射以及加载WSGI应用程序
        #在启动WSGI服务时,会启动http监听
        launcher = service.process_launcher()
        server = service.WSGIService('osapi_volume') #创建一个名为`osapi_volume`的`WSGIService`服务对象 ,2里面详解
        launcher.launch_service(server, workers=server.workers)
        launcher.wait()
    

    2、创建 WSGIService 服务对象

    from oslo_service import wsgi
    from cinder import service
    cinder/service.py:class WSGIService(service.ServiceBase):	
    class WSGIService(service.ServiceBase):
        """Provides ability to launch API from a 'paste' configuration."""
    
        def __init__(self, name, loader=None):
            """Initialize, but do not start the WSGI server.
    		初始化,但是并不启动wsgi server服务
            :param name: The name of the WSGI server given to the loader.
            :param loader: Loads the WSGI application using the given name.
            :returns: None
    
            """
            self.name = name #服务名`osapi_volume`
            self.manager = self._get_manager()  #加载名为(`osapi_volume_manager`)的管理器,返回值为None)
    		#创建WSGI应用加载器,并根据配置文件(`cinder.conf`)设置应用配置路径,config_path` = `/etc/cinder/api-paste.ini‘
            self.loader = loader or wsgi.Loader(CONF) #该函数会寻找cinder.conf文件中 api_paste_config 参数对应的配置文件,并保存到变量中
            self.app = self.loader.load_app(name)  #加载WSGI应用并设置路由映射,return paste.urlmap.URLMap
    		
    		 """
    		 根据配置文件(`cinder.conf`)设置监听地址及工作线程数
    		 如果未指定监听ip及端口就分别设置为`0.0.0.0`及`0`
    		 如果为指定工作线程数就设置为cpu个数
    		 如果设置的工作线程数小于1,则抛异常
    		 """
            self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0")
            self.port = getattr(CONF, '%s_listen_port' % name, 0)
            self.use_ssl = getattr(CONF, '%s_use_ssl' % name, False)
            self.workers = (getattr(CONF, '%s_workers' % name, None) or
                            processutils.get_worker_count())
            if self.workers and self.workers < 1:
                worker_name = '%s_workers' % name
                msg = (_("%(worker_name)s value of %(workers)d is invalid, "
                         "must be greater than 0.") %
                       {'worker_name': worker_name,
                        'workers': self.workers})
                raise exception.InvalidInput(msg)
    			
    		"""如果CONF.profiler.enabled = True就开启性能分析  
    		创建一个类型为`Messaging`的通知器(`_notifier`),将性能数据发送给
    		ceilometer
    		"""
            setup_profiler(name, self.host)
    		##创建WSGI服务器对象
            self.server = wsgi.Server(CONF,
                                      name,
                                      self.app,
                                      host=self.host,
                                      port=self.port,
                                      use_ssl=self.use_ssl)
    

    在cinder.conf配置文件中与cinder api服务有关的参数
    # File name for the paste.deploy config for api service (string value)
    api_paste_config = /etc/cinder/api-paste.ini
    在初始化WSGIService服务对象过程中,主要完成了如下操作:
    1)加载WSGI Application(Python Paste Deployment)
    2)设置路由映射(Python Routes)
    3)创建WSGI服务器对象并完成初始化

    2.1 对wsgi的使用

    oslo_service/wsgi.py
    class Loader(object):
        """Used to load WSGI applications from paste configurations."""
    
        def __init__(self, conf):
            """Initialize the loader, and attempt to find the config.
            :param conf: Application config
            :returns: None
            """
            conf.register_opts(_options.wsgi_opts)
            self.config_path = None
    
            config_path = conf.api_paste_config
            if not os.path.isabs(config_path):
                self.config_path = conf.find_file(config_path)
            elif os.path.exists(config_path):
                self.config_path = config_path
    
            if not self.config_path:
                raise ConfigNotFound(path=config_path)
    
        def load_app(self, name):
            """Return the paste URLMap wrapped WSGI application.
            :param name: Name of the application to load.
            :returns: Paste URLMap object wrapping the requested application.
            :raises: PasteAppNotFound
            """
            try:
                LOG.debug("Loading app %(name)s from %(path)s",
                          {'name': name, 'path': self.config_path})
                return deploy.loadapp("config:%s" % self.config_path, name=name)
            except LookupError:
                LOG.exception("Couldn't lookup app: %s", name)
                raise PasteAppNotFound(name=name, path=self.config_path)
    

    配置文件api-paste.ini内容如下

    [composite:osapi_volume]
    use = call:cinder.api:root_app_factory
    /: apiversions
    /v1: openstack_volume_api_v1
    /v2: openstack_volume_api_v2
    /v3: openstack_volume_api_v3
    
    [composite:openstack_volume_api_v1]
    use = call:cinder.api.middleware.auth:pipeline_factory
    noauth = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv1
    keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv1
    keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv1
    
    [composite:openstack_volume_api_v2]
    use = call:cinder.api.middleware.auth:pipeline_factory
    noauth = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv2
    keystone = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv2
    keystone_nolimit = cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv2
    
    cinder.conf文件中的api启动的配置
    这三个参数控制的是api 版本的控制
    # DEPRECATED: Deploy v1 of the Cinder API. (boolean value)
    # This option is deprecated for remoervice_down_timeal.
    # Its value may be silently ignored in the future.
    #enable_v1_api = false--------不加载v1对应的app
    
    # DEPRECATED: Deploy v2 of the Cinder API. (boolean value)
    # This option is deprecated for removal.
    # Its value may be silently ignored in the future.
    #enable_v2_api = True------------加载v2对应的app
    
    # Deploy v3 of the Cinder API. (boolean value)
    enable_v3_api = True-------------加载v3对应的app
    
    # The strategy to use for auth. Supports noauth or keystone. (string value)
    # Allowed values: noauth, keystone
    auth_strategy = keystone----------这个参数控制的api-paste.ini中选择哪一种认证方式
    

      

      

      

      

      

  • 相关阅读:
    玩儿了一下django User authentication
    python装饰器方法
    django session
    采用asyncore进行实时同步
    django internal search
    素质拓展
    框架,公共模块,unified思想
    Linux操作系统分析__破解操作系统的奥秘
    ASP.NET]ASP.NET C# 用 Print2Flash 实现在线预览 Word、PPT、PDF 等
    [Asp.net]常见word,excel,ppt,pdf在线预览方案,有图有真相,总有一款适合你!
  • 原文地址:https://www.cnblogs.com/potato-chip/p/12299190.html
Copyright © 2020-2023  润新知