问题导读
1.Driver在那个配置文件中可配置?
2.Manager怎么调用conf下面配置的或者默认的driver的?
完成WSGI的接口后需要调用Controller的函数来实现功能,完成并返回结果,根据官方文档,Controller可配置多个Manager,Manager可选择Driver。Driver在配置文件keystone.conf下面可以进行配置,流程是Controller->Manager->Driver.配置文件的读取功能是由oslo.config文件来完成的,keystone.conf配置如下:
1.配置Log信息
2.配置notification,driver默认是没有notification的,keystone.openstack.common.notifier.no_op_notifier,如下所示
- # notification_driver can be defined multiple times
- # Do nothing driver (the default)
- # notification_driver = keystone.openstack.common.notifier.no_op_notifier
- # Logging driver example (not enabled by default)
- # notification_driver = keystone.openstack.common.notifier.log_notifier
- # RPC driver example (not enabled by default)
- # notification_driver = keystone.openstack.common.notifier.rpc_notifier
复制代码
3.配置rpc,默认是kombu架构的rpc通信机制,keystone.openstack.common.rpc.impl_kombu,如下所示
- # For Keystone, these options apply only when the RPC notification driver is
- # used.
- # The messaging module to use, defaults to kombu.
- # rpc_backend = keystone.openstack.common.rpc.impl_kombu
复制代码
4.配置数据库
复制代码
5.配置Identity
- [identity]
- driver = keystone.identity.backends.sql.Identity
复制代码
6.配置credential
- [credential]
- # driver = keystone.credential.backends.sql.Credential
复制代码
7.配置trust
- [trust]
- # driver = keystone.trust.backends.sql.Trust
复制代码
8.配置os_inherit
不知到是做什么的。。。roles权限继承?
9.配置catalog
- [catalog]
- driver = keystone.catalog.backends.sql.Catalog
复制代码
10.配置endpoint_filter
- [endpoint_filter]
- # extension for creating associations between project and endpoints in order to
- # provide a tailored catalog for project-scoped token requests.
- # driver = keystone.contrib.endpoint_filter.backends.sql.EndpointFilter
- # return_all_endpoints_if_no_filter = True\
复制代码
11.配置token
- [token]
- driver = keystone.token.backends.sql.Token
复制代码
12.配置cache
复制代码
13.配置policy
- [policy]
- # driver = keystone.policy.backends.sql.Policy
复制代码
14配置ec2
- [ec2]
- driver = keystone.contrib.ec2.backends.sql.Ec2
- # driver = keystone.contrib.ec2.backends.kvs.Ec2
复制代码
15.配置assignment
- [assignment]
- driver = keystone.assignment.backends.sql.Assignment
复制代码
16.配置OAuth1
- [oauth1]
- # driver = keystone.contrib.oauth1.backends.sql.OAuth1
复制代码
17.配置ssl
18配置signing
19配置ladp
20配置auth
- methods = external,password,token,oauth1
- #external = keystone.auth.plugins.external.ExternalDefault
- password = keystone.auth.plugins.password.Password
- token = keystone.auth.plugins.token.Token
- oauth1 = keystone.auth.plugins.oauth1.OAuth
复制代码
21.配置pastedeploy
- [paste_deploy]
- # Name of the paste configuration file that defines the available pipelines
- config_file = /etc/keystone/keystone-paste.ini
复制代码
我的keystone.conf下面就这么多配置,可见对基本的操作和driver都进行了配置,那么在实际的代码中哪里?
IOK,首先找找看Manager类,以Identity包为例,在core下实现了Identity的manager包,也就是以前说过的注册的WSGI接口的Identity.routers.Public()使用的Manager,由service.py下,wsgi.ComposingRouter进行路由分发的类。
- @dependency.provider('identity_api')
- @dependency.requires('assignment_api')
- class Manager(manager.Manager):
- """Default pivot point for the Identity backend.
- See :mod:`keystone.common.manager.Manager` for more details on how this
- dynamically calls the backend.
- This class also handles the support of domain specific backends, by using
- the DomainConfigs class. The setup call for DomainConfigs is called
- from with the @domains_configured wrapper in a lazy loading fashion
- to get around the fact that we can't satisfy the assignment api it needs
- from within our __init__() function since the assignment driver is not
- itself yet intitalized.
- Each of the identity calls are pre-processed here to choose, based on
- domain, which of the drivers should be called. The non-domain-specific
- driver is still in place, and is used if there is no specific driver for
- the domain in question.
- """
- def __init__(self):
- super(Manager, self).__init__(CONF.identity.driver)
- self.domain_configs = DomainConfigs()
复制代码
源代码Manager实现了很多功能,这里只粘贴一小部分有关的,看到上面的@dependency装饰器了吗,Controller怎么调用Manager的秘密就在那里。这里先不管,先挖掘Manager怎么调用conf下面配置的或者默认的driver的。其实很简单,CONF.identity,driver就配置了本域下Manager用的Driver,这样也就实现了Manager和Driver的绑定,CONF是在keystone-all初始化就已经配置好了,通过oslo.config模块。而且Manager也通过DomainConfigs来实现了针对不同域的keystone认证实现(跨域认证?,需要测试)。不仅仅是Identity的core.py的Manager是这样配置其他的Manager也是类似的。下面的Manager基类实现了self.driver的赋值,通过import.import_object导入driver对象
- class Manager(object):
- """Base class for intermediary request layer.
- The Manager layer exists to support additional logic that applies to all
- or some of the methods exposed by a service that are not specific to the
- HTTP interface.
- It also provides a stable entry point to dynamic backends.
- An example of a probable use case is logging all the calls.
- """
- def __init__(self, driver_name):
- self.driver = importutils.import_object(driver_name)
复制代码
assignment的Manager的assignment driver
- @dependency.provider('assignment_api')
- @dependency.requires('identity_api')
- class Manager(manager.Manager):
- """Default pivot point for the Assignment backend.
- See :mod:`keystone.common.manager.Manager` for more details on how this
- dynamically calls the backend.
- assignment.Manager() and identity.Manager() have a circular dependency.
- The late import works around this. THe if block prevents creation of the
- api object by both managers.
- """
- def __init__(self):
- assignment_driver = CONF.assignment.driver
- if assignment_driver is None:
- identity_driver = dependency.REGISTRY['identity_api'].driver
- assignment_driver = identity_driver.default_assignment_driver()
- super(Manager, self).__init__(assignment_driver)
复制代码
根据配置文件,Identity的Driver继承自core.,py下Driver和sql.Base基类,通过openstack.common下的sql包实现了对数据库的操作。基本所有的driver针对的都是数据库,有sql的,kvs(key-value存储),ldap(目录)等等。OK,我们知道了Manager与Driver的关系,下面就是Controller和Manager的关系了,看看Manager上的dependency装饰器吧,核心的函数就是两个一个是provider,一个是requires.
- def provider(name):
- """Register the wrapped dependency provider under the specified name."""
- def wrapper(cls):
- def wrapped(init):
- def __wrapped_init__(self, *args, **kwargs):
- """Initialize the wrapped object and add it to the registry."""
- init(self, *args, **kwargs)
- REGISTRY[name] = self
- resolve_future_dependencies(name)
- return __wrapped_init__
- cls.__init__ = wrapped(cls.__init__)
- return cls
- return wrapper
复制代码
- def requires(*dependencies):
- """Inject specified dependencies from the registry into the instance."""
- def wrapper(self, *args, **kwargs):
- """Inject each dependency from the registry."""
- self.__wrapped_init__(*args, **kwargs)
- _process_dependencies(self)
- def wrapped(cls):
- """Note the required dependencies on the object for later injection.
- The dependencies of the parent class are combined with that of the
- child class to create a new set of dependencies.
- """
- existing_dependencies = getattr(cls, '_dependencies', set())
- cls._dependencies = existing_dependencies.union(dependencies)
- if not hasattr(cls, '__wrapped_init__'):
- cls.__wrapped_init__ = cls.__init__
- cls.__init__ = wrapper
- return cls
- return wrapped
复制代码
注释说的很清楚,provider是装饰的这个类注册到REGISTER[]下面,requires是将REGISTER里面的类取出来,注入到装饰的类下面。所以为什么Manager上需要这个呢?把Manager进行注册,和提取,这样就可以方便我们的Controller调用了。在哪注册呢?service,py的全局变量。
- _IDENTITY_API = identity.Manager()
- DRIVERS = dict(
- assignment_api=assignment.Manager(),
- catalog_api=catalog.Manager(),
- credentials_api=credential.Manager(),
- endpoint_filter_api=endpoint_filter.Manager(),
- identity_api=_IDENTITY_API,
- policy_api=policy.Manager(),
- token_api=token.Manager(),
- trust_api=trust.Manager(),
- token_provider_api=token.provider.Manager())
- dependency.resolve_future_dependencies()
复制代码
注册了所有的Manager,那在哪提取呢?
- @dependency.requires('identity_api', 'policy_api', 'token_api',
- 'trust_api', 'catalog_api', 'credential_api',
- 'assignment_api')
- class V2Controller(wsgi.Application):
- """Base controller class for Identity API v2."""
复制代码
这样Controller就可以调用所有的Manager了。
相关文章
Openstack源代码分析之keystone服务(keystone-all)
http://www.aboutyun.com/thread-10139-1-1.html
Openstack之keystone源代码分析1--WSGI接口流程分析
http://www.aboutyun.com/thread-10137-1-1.html
[openstack][G版]keystone源码学习
http://www.aboutyun.com/thread-10136-1-1.html
bluefire1991
2013.11.2
21:14:54
|