1 客户端处理报文流程
上图中RestClient类为客户端的基类,所有客户端发送及接收报文的机制都是大致相同的。
1.1 准备头部
发送HTTP报文需要URL、头部和主体这三部分。客户端调用RestClient.get()时,需传入URL和报文头部,如果是发送POST请求则还需传入主体部分。此时URL和报文头部都是不完整的。一些请求中需要包含额外的头部,通过调用self.get_headers()完成。
1.2 请求token、endpoint
发送请求到OpenStack时,头部需要添加’X-Auth-Token’字段。该字段值为token,需要预先向OpenStack请求。客户端传入的URL此时也并不是完整的URL,需要与endpoint拼接得到。
客户端中的self.auth_provider是KeystoneV3AuthProvider或KeystoneV2AuthProvider的实例,具体是哪个类的实例取决于环境中Keystone的版本和Tempest的配置。KeystoneV3AuthProvider提供了请求token和endpoint的功能,客户端的开发过程中就不用考虑认证部分了。
RestClient类中发送请求前调用了self.auth_provider.auth_request(),这个函数调用了self.decorate_request(),其代码如下:
def _decorate_request(self, filters, method, url, headers=None, body=None,
auth_data=None):
if auth_data is None:
auth_data = self.get_auth() #请求token和endpoint列表
token, _ = auth_data
base_url = self.base_url(filters=filters, auth_data=auth_data) #筛选endpoint
_headers = copy.deepcopy(headers) if headers is not None else {
}
_headers['X-Auth-Token'] = str(token) #将token添加至头部
if url is None or url == "":
_url = base_url
else:
_url = "/".join([base_url, url]) #拼接endpoint和URL
parts = [x for x in urlparse.urlparse(_url)]
parts[2] = re.sub("/{2,}", "/", parts[2])
_url = urlparse.urlunparse(parts)
return str(_url), _headers, body
self.decorate_request()完成了以下几件事情:
- 请求token和endpoint列表
- 筛选endpoint
- 添加token至头部
- 拼接URL
请求token和endpoint列表通过self.get_auth()完成,该函数调用了OpenStack的/v3/auth/tokens,向OpenStack发送了认证信息以请求token,返回的响应body如下:
{
"token": {
"audit_ids": [
"3T2dc1CGQxyJsHdDu1xkcw"
],
"catalog": [
{
"endpoints": [
{
"id": "068d1b359ee84b438266cb736d81de97",
"interface": "public",
"region": "RegionOne",
"region_id": "RegionOne",
"url": "http://example.com/identity"
},
{
"id": "8bfc846841ab441ca38471be6d164ced",
"interface": "admin",
"region": "RegionOne",
"region_id": "RegionOne",
"url": "http://example.com/identity"
},
{
"id": "beb6d358c3654b4bada04d4663b640b9",
"interface": "internal",
"region": "RegionOne",
"region_id": "RegionOne",
"url": "http://example.com/identity"
}
],
"type": "identity",
"id": "050726f278654128aba89757ae25950c",
"name": "keystone"
}
],
"expires_at": "2015-11-07T02:58:43.578887Z",
"is_domain": false,
"issued_at"