和调用openstack的其他服务一样,keystone服务在被其他模块调用时也是用keystone client,来看一看keystone client调用时的方式,以及和rest的不同。
前面仔细分析过ironic的client启动过过程,argparser等虽然没有细说,是因为我暂时不用修改client,虽然不难:),我更多是将client作为研究openstack的入口,
就像看一个大型项目,从测试开始浏览全貌一样,从client入手是对server端实现方式最合适的探测点。
一样的,通过/usr/bin/keystone脚本,在keystoneclient.shell.py中执行main:
OpenStackIdentityShell().main(sys.argv[1:])
client这不是服务,是函数的执行,来一个command line的命令配上参数,shell执行一下,对不同的调用方法, 和ironic类似,严格来说,ironic遵循了这一风格,
在shell.py的main中:
subcommand_parser = self.get_subcommand_parser(api_version)
subparsers = parser.add_subparsers(metavar='<subcommand>')
self._find_actions(subparsers, actions_module) #不错关键在这一部分,我们输入keystone tenant-list对应的是什么方法呢?
在_find_action方法中:
for attr in (a for a in dir(actions_module) if a.startswith('do_')):
# I prefer to be hyphen-separated instead of underscores.
command = attr[3:].replace('_', '-')
callback = getattr(actions_module, attr)
。。。。
是不是和ironic一样:),对命令指明callback的方法,(这里对使用keystone v2.0 api来说在keystoneclient/v2.0目录下的client.py中指定了命令的list),
OK,那现在有一个命令 “keystone tenant-list”:
self.cs = self.get_api_class #由shell_v2_0.CLIENT_CLASS,得到v2.0下的client
args.func(self.cs, args) #这里的func就是刚才所说的callback,第一个参数cs为v2.0下的client
来看do_tenant_list::
def do_tenant_list(kc, args):
"""List all tenants."""
tenants = kc.tenants.list() #真正的执行
utils.print_list(tenants, ['id', 'name', 'enabled'], order_by='name')
而在client中:
def __init__(self, **kwargs):
"""Initialize a new client for the Keystone v2.0 API."""
super(Client, self).__init__(**kwargs)
self.endpoints = endpoints.EndpointManager(self)
self.extensions = extensions.ExtensionManager(self)
self.roles = roles.RoleManager(self)
self.services = services.ServiceManager(self)
self.tokens = tokens.TokenManager(self)
self.tenants = tenants.TenantManager(self, self.roles, self.users)
。。。。
所以在do_tenant_list中kc.tenants.list()执行的是self.tenants.list() 也就是TenantManager,在TenantManager中:
tenant_list = self._list('/tenants%s' % query, 'tenants')
trace一下发现调用的_list实际上是发送client的get或者post方法(client继承自HttpClient,进行了封装)
在_lsit中:
if body:
resp, body = self.client.post(url, body=body, **kwargs)
else:
resp, body = self.client.get(url, **kwargs)
trace一下keystoneclient/httpclient.py中的HttpClient,
get/post/delete/put -> _cs_request -->request
当然了所有的call都会受到前面说的“token_auth admin_token_auth”等filter的check,因为这里所有的调用也都变成了rest call
知道了client调用时候的流程,那么怎么样传递参数得到client的对象,再用client 去call方法呢,如何使用client才能让鉴权通过呢,本来想和
在一起做一节,累了,下一节再说。
本文详细解析了使用keystoneclient调用OpenStack服务的过程,特别是通过/usr/bin/keystone脚本执行main函数实现命令行操作。以keystoneclient为例,展示其与rest API的不同之处,以及在不同服务调用方法中的应用,如通过shell.py的main函数处理命令和参数。同时,阐述了client初始化和调用方法的具体实现,如在do_tenant_list方法中如何执行真正的API调用,以及通过client对象进行实际请求的过程。
1963

被折叠的 条评论
为什么被折叠?



