分享

Openstack之keystone源代码分析2--Controller->Manager->Driver

tntzbzc 发表于 2014-11-19 22:40:20 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 38739
问题导读
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,如下所示
  1. # notification_driver can be defined multiple times
  2. # Do nothing driver (the default)
  3. # notification_driver = keystone.openstack.common.notifier.no_op_notifier
  4. # Logging driver example (not enabled by default)
  5. # notification_driver = keystone.openstack.common.notifier.log_notifier
  6. # RPC driver example (not enabled by default)
  7. # notification_driver = keystone.openstack.common.notifier.rpc_notifier
复制代码


3.配置rpc,默认是kombu架构的rpc通信机制,keystone.openstack.common.rpc.impl_kombu,如下所示
  1. # For Keystone, these options apply only when the RPC notification driver is
  2. # used.
  3. # The messaging module to use, defaults to kombu.
  4. # rpc_backend = keystone.openstack.common.rpc.impl_kombu
复制代码


4.配置数据库
  1. connection=xxxx
复制代码


5.配置Identity
  1. [identity]
  2. driver = keystone.identity.backends.sql.Identity
复制代码


6.配置credential
  1. [credential]
  2. # driver = keystone.credential.backends.sql.Credential
复制代码


7.配置trust
  1. [trust]
  2. # driver = keystone.trust.backends.sql.Trust
复制代码


8.配置os_inherit
不知到是做什么的。。。roles权限继承?
9.配置catalog
  1. [catalog]
  2. driver = keystone.catalog.backends.sql.Catalog
复制代码


10.配置endpoint_filter
  1. [endpoint_filter]
  2. # extension for creating associations between project and endpoints in order to
  3. # provide a tailored catalog for project-scoped token requests.
  4. # driver = keystone.contrib.endpoint_filter.backends.sql.EndpointFilter
  5. # return_all_endpoints_if_no_filter = True\
复制代码


11.配置token
  1. [token]
  2. driver = keystone.token.backends.sql.Token
复制代码


12.配置cache
  1. [cache]
复制代码


13.配置policy
  1. [policy]
  2. # driver = keystone.policy.backends.sql.Policy
复制代码


14配置ec2
  1. [ec2]
  2. driver = keystone.contrib.ec2.backends.sql.Ec2
  3. # driver = keystone.contrib.ec2.backends.kvs.Ec2
复制代码

15.配置assignment
  1. [assignment]
  2. driver = keystone.assignment.backends.sql.Assignment
复制代码



16.配置OAuth1
  1. [oauth1]
  2. # driver = keystone.contrib.oauth1.backends.sql.OAuth1
复制代码


17.配置ssl
18配置signing
19配置ladp
20配置auth
  1. methods = external,password,token,oauth1
  2. #external = keystone.auth.plugins.external.ExternalDefault
  3. password = keystone.auth.plugins.password.Password
  4. token = keystone.auth.plugins.token.Token
  5. oauth1 = keystone.auth.plugins.oauth1.OAuth
复制代码


21.配置pastedeploy
  1. [paste_deploy]
  2. # Name of the paste configuration file that defines the available pipelines
  3. 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进行路由分发的类。
  1. @dependency.provider('identity_api')
  2. @dependency.requires('assignment_api')
  3. class Manager(manager.Manager):
  4.     """Default pivot point for the Identity backend.
  5.     See :mod:`keystone.common.manager.Manager` for more details on how this
  6.     dynamically calls the backend.
  7.     This class also handles the support of domain specific backends, by using
  8.     the DomainConfigs class. The setup call for DomainConfigs is called
  9.     from with the @domains_configured wrapper in a lazy loading fashion
  10.     to get around the fact that we can't satisfy the assignment api it needs
  11.     from within our __init__() function since the assignment driver is not
  12.     itself yet intitalized.
  13.     Each of the identity calls are pre-processed here to choose, based on
  14.     domain, which of the drivers should be called. The non-domain-specific
  15.     driver is still in place, and is used if there is no specific driver for
  16.     the domain in question.
  17.     """
  18.     def __init__(self):
  19.         super(Manager, self).__init__(CONF.identity.driver)
  20.         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对象
  1. class Manager(object):
  2.     """Base class for intermediary request layer.
  3.     The Manager layer exists to support additional logic that applies to all
  4.     or some of the methods exposed by a service that are not specific to the
  5.     HTTP interface.
  6.     It also provides a stable entry point to dynamic backends.
  7.     An example of a probable use case is logging all the calls.
  8.     """
  9.     def __init__(self, driver_name):
  10.         self.driver = importutils.import_object(driver_name)
复制代码


assignment的Manager的assignment driver
  1. @dependency.provider('assignment_api')
  2. @dependency.requires('identity_api')
  3. class Manager(manager.Manager):
  4.     """Default pivot point for the Assignment backend.
  5.     See :mod:`keystone.common.manager.Manager` for more details on how this
  6.     dynamically calls the backend.
  7.     assignment.Manager() and identity.Manager() have a circular dependency.
  8.     The late import works around this.  THe if block prevents creation of the
  9.     api object by both managers.
  10.     """
  11.     def __init__(self):
  12.         assignment_driver = CONF.assignment.driver
  13.         if assignment_driver is None:
  14.             identity_driver = dependency.REGISTRY['identity_api'].driver
  15.             assignment_driver = identity_driver.default_assignment_driver()
  16.         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.
  1. def provider(name):
  2.     """Register the wrapped dependency provider under the specified name."""
  3.     def wrapper(cls):
  4.         def wrapped(init):
  5.             def __wrapped_init__(self, *args, **kwargs):
  6.                 """Initialize the wrapped object and add it to the registry."""
  7.                 init(self, *args, **kwargs)
  8.                 REGISTRY[name] = self
  9.                 resolve_future_dependencies(name)
  10.             return __wrapped_init__
  11.         cls.__init__ = wrapped(cls.__init__)
  12.         return cls
  13.     return wrapper
复制代码

  1. def requires(*dependencies):
  2.     """Inject specified dependencies from the registry into the instance."""
  3.     def wrapper(self, *args, **kwargs):
  4.         """Inject each dependency from the registry."""
  5.         self.__wrapped_init__(*args, **kwargs)
  6.         _process_dependencies(self)
  7.     def wrapped(cls):
  8.         """Note the required dependencies on the object for later injection.
  9.         The dependencies of the parent class are combined with that of the
  10.         child class to create a new set of dependencies.
  11.         """
  12.         existing_dependencies = getattr(cls, '_dependencies', set())
  13.         cls._dependencies = existing_dependencies.union(dependencies)
  14.         if not hasattr(cls, '__wrapped_init__'):
  15.             cls.__wrapped_init__ = cls.__init__
  16.             cls.__init__ = wrapper
  17.         return cls
  18.     return wrapped
复制代码


注释说的很清楚,provider是装饰的这个类注册到REGISTER[]下面,requires是将REGISTER里面的类取出来,注入到装饰的类下面。所以为什么Manager上需要这个呢?把Manager进行注册,和提取,这样就可以方便我们的Controller调用了。在哪注册呢?service,py的全局变量。
  1. _IDENTITY_API = identity.Manager()
  2. DRIVERS = dict(
  3.     assignment_api=assignment.Manager(),
  4.     catalog_api=catalog.Manager(),
  5.     credentials_api=credential.Manager(),
  6.     endpoint_filter_api=endpoint_filter.Manager(),
  7.     identity_api=_IDENTITY_API,
  8.     policy_api=policy.Manager(),
  9.     token_api=token.Manager(),
  10.     trust_api=trust.Manager(),
  11.     token_provider_api=token.provider.Manager())
  12. dependency.resolve_future_dependencies()
复制代码


注册了所有的Manager,那在哪提取呢?
  1. @dependency.requires('identity_api', 'policy_api', 'token_api',
  2.                      'trust_api', 'catalog_api', 'credential_api',
  3.                      'assignment_api')
  4. class V2Controller(wsgi.Application):
  5.     """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



已有(1)人评论

跳转到指定楼层
doscho 发表于 2016-9-20 16:51:37
正在学习keystone,数据库中的assignment表,具体字段代表什么意思?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条