对Keystone中Identity服务的实现也是基于controller,manager,driver这3层结构,一个controller可以配置多个manager,一个manager可选择多个driver
Controller:
和上层Router相关,暂时还没理清楚。
Manager:
为动态的driver模块提供稳定的访问点,并且会基于对driver的选择,对Identity请求做一些预处理,并且可以封装Driver提供的函数,实现高层函数。
keystone.common.manager.Manager类为所有manager类的父类,该manager类只是完成一些初始化工作,没有实现任何CRUD操作。Identity,Token等服务继承上述父类,实现自己的manager类。
keystone.identity.core.Manager类继承keystone.common.manager.Manager,并实现了大量功能函数如下图所示:
图1:Manager所提供的功能函数
由上图可以看到,keystone.identity.core.Manager类提供了Identity服务的所有功能,那么这些函数是在哪里实现的呢?已get_user函数为例,下图为该函数的代码截图
图2:LDAP Manager中get_user函数
可以看到,实际上最核心是通过调用driver.get_user(user_id)方法,然后再此基础上做一些高层逻辑的判断(如driver.is_domain_aware()方法)。这里就引出了Keystone结构中的Driver概念。
Driver:
Keystone框架中的最底层,直接和LDAP或SQL数据库等模块进行通信,目前支持LDAP,SQL,KVS等方式。
keystone.identity.core.Driver为Identity服务所有Driver的父类(其他服务也有自己的父类,各个服务父类Driver之间无关),描述了作为一个Identity.Driver类所应具备的功能,其功能函数要比Manager所提供的功能少,和Manager的上层功能并非一一对应,有时候一个上层功能需要若干Driver的方法协作实现。
图3:Identity Driver所提供的功能函数
父类Driver自己并不实现方法,如get_user方法截图如下:
图4:父类Driver中的get_user函数
keystone.identity.backends包下面的kvs.py,ldap.py,sql.py文件分别有Driver相应的实现类,还是以ldap为例。keystone.identity.backends.ldap.Identity类继承keystone.identity.core.Driver,负责“具体实现”Driver各种功能。
图5:Identity LDAP Driver实现类中的get_user函数
如上图所示,LDAP所对应的Driver实现类,通过“user”来实现get_user功能。到此为止,从Identity服务的角度,自上而下梳理了流程,下面从LDAP的角度说明一下如何从“user”实现get_user()。
Keystone中的LDAP:
keystone.common.ldap.core.BaseLdap类,是所有LDAP类的父类,通过调用python.ldap包,实现了大量和具体业务无关的LDAP操作函数,如下图所示:
图6:BaseLdap中提供的方法
Identity,Token等所有服务的Ldap.Driver中,都有两个BaseLdap的子类,以Identity为例,他们是keystone.identity.backends.ldap.userAPI和keystone.identity.backendsl.ldap.groupAPI,从名字可以看出,userAPI主要负责对用户的操作,groupAPI主要负责对组的操作。两个子类都扩展了BaseLdap,如groupAPI中增加了add_user,remove_user等方法。所有Identity服务中和LDAP相关的调用,都是由userAPI或groupAPI提供。
回到上面的Driver层,通过一个“user”实现了get_user函数,这里的“user”就是userAPI,userAPI调用父类BaseLdap中提供的get函数,最终实现get_user函数。