cinder api启动过程源码分析

1、启动cinder-api服务

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

[[email protected] ~]# 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中选择哪一种认证方式

  

  

  

  

  

原文地址:https://www.cnblogs.com/potato-chip/p/12299190.html

时间: 2024-12-20 04:38:20

cinder api启动过程源码分析的相关文章

Flume-NG启动过程源码分析(三)(原创)

上一篇文章分析了Flume如何加载配置文件的,动态加载也只是重复运行getConfiguration(). 本篇分析加载配置文件后各个组件是如何运行的? 加载完配置文件订阅者Application类会收到订阅信息执行: @Subscribe public synchronized void handleConfigurationEvent(MaterializedConfiguration conf) { stopAllComponents(); startAllComponents(conf)

【Java】【Flume】Flume-NG启动过程源码分析(一)

从bin/flume 这个shell脚本可以看到Flume的起始于org.apache.flume.node.Application类,这是flume的main函数所在. main方法首先会先解析shell命令,如果指定的配置文件不存在就甩出异常. 根据命令中含有"no-reload-conf"参数,决定采用那种加载配置文件方式:一.没有此参数,会动态加载配置文件,默认每30秒加载一次配置文件,因此可以动态修改配置文件:二.有此参数,则只在启动时加载一次配置文件.实现动态加载功能采用了

【Java】【Flume】Flume-NG启动过程源码分析(二)

本节分析配置文件的解析,即PollingPropertiesFileConfigurationProvider.FileWatcherRunnable.run中的eventBus.post(getConfiguration()).分析getConfiguration()方法.此方法在AbstractConfigurationProvider类中实现了,并且这个类也初始化了三大组件的工厂类:this.sourceFactory = new DefaultSourceFactory();this.s

【Java】【Flume】Flume-NG启动过程源码分析(三)

本篇分析加载配置文件后各个组件是如何运行的? 加载完配置文件订阅者Application类会收到订阅信息执行: @Subscribe public synchronized void handleConfigurationEvent(MaterializedConfiguration conf) { stopAllComponents(); startAllComponents(conf); } MaterializedConfiguration conf就是getConfiguration()

Activity启动流程源码分析之Launcher启动(二)

1.前述 在前一篇文章中我们简要的介绍Activity的启动流程Activity启动流程源码分析之入门(一),当时只是简单的分析了一下流程,而且在上一篇博客中我们也说了Activity的两种启动方式,现在我们就来分析其中的第一种方式--Launcher启动,这种启动方式的特点是会创建一个新的进程来加载相应的Activity(基于Android5.1源码). 2.Activity启动流程时序图 好啦,接下来我们先看一下Launcher启动Activity的时序图: 好啦,接下来我们将上述时序图用代

Android系统默认Home应用程序(Launcher)的启动过程源码分析

在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还须要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Launcher应用程序的启动过程. Android系统的Home应用程序Launcher是由ActivityManagerService启动的,而ActivityManagerService和PackageManagerService一样,都是在开机时由

嵌入式linux开发uboot移植(三)——uboot启动过程源码分析

嵌入式linux开发uboot移植(三)--uboot启动过程源码分析 一.uboot启动流程简介 与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段.BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言来实现:BL2阶段主要是对外部设备如网卡.Flash等的初始化以及uboot命令集等的自身实现,通常用C语言来实现. 1.BL1阶段 uboot的BL1阶段代码通常放在start.s文件中,用汇编语言实现,其主要代码功能如下:

Openstack liberty 中Cinder-api启动过程源码分析2

在前一篇博文中,我分析了cinder-api启动过程中WSGI应用的加载及路由的建立过程,本文将分析WSGI服务器的启动及其接收客户端请求并完成方法映射的过程,请看下文的分析内容: 创建WSGI服务器 在初始化WSGIService对象的过程中,会创建WSGI服务器,如下: #`cinder.service:WSGIService.__init__` def __init__(self, name, loader=None): """ name = `osapi_volume

【Android】应用程序启动过程源码分析

在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程序的启动过程. 启动Android应用程序中的Activity的两种情景:其中,在手机屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来.这种启动方式的特点是会启动一个新的进程来加载相应的Activity. 这里,我们以这个例子为例来说明