214 lines
6.7 KiB
Python
214 lines
6.7 KiB
Python
# Copyright 2016 Huawei Technologies Co.,LTD.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from nova.i18n import _
|
|
from nova.virt.fusioncomputeapi import constant
|
|
from nova.virt.fusioncomputeapi import exception
|
|
from nova.virt.fusioncomputeapi import restclient
|
|
from nova.virt.fusioncomputeapi import utils
|
|
from nova.virt.fusioncomputeapi.utils import LOG
|
|
|
|
|
|
class FCBaseClient(restclient.RestClient):
|
|
|
|
STATUS_OK = [200, 201, 202]
|
|
STATUS_NO_AUTH = [401]
|
|
STATUS_INVALID = [400, 403, 404, 500, 503]
|
|
|
|
def __init__(self, host, user, key, user_type, api_version='6.0',
|
|
ssl=None, port=None, cert=None, request_time_out=120):
|
|
super(FCBaseClient, self).__init__(host, port=port, ssl=ssl, cert=cert)
|
|
|
|
self.__user = user
|
|
self.__key = key
|
|
self.__user_type = user_type
|
|
|
|
self.__api_version = api_version
|
|
self.__accept = ('application/json;version=%s;charset=UTF-8' %
|
|
api_version)
|
|
self.__content_type = 'application/json'
|
|
self.__accept_language = 'en_US'
|
|
|
|
self.__request_time_out = request_time_out
|
|
self.__token = None
|
|
|
|
self.context = FCClientContext(self)
|
|
|
|
def _update_and_get_headers(self, headers, force_get_token):
|
|
"""update fc rest header and return headers
|
|
|
|
:param headers:
|
|
:param force_get_token:
|
|
:return:
|
|
"""
|
|
if not self.__token or force_get_token:
|
|
self.get_token()
|
|
if not headers:
|
|
headers_res = self._make_headers(self.__token)
|
|
else:
|
|
headers_res = headers.copy()
|
|
headers_res.update(self._make_headers(self.__token))
|
|
return headers_res
|
|
|
|
def request_msg(self, method, path, data=None, headers=None, **kwargs):
|
|
req_headers = self._update_and_get_headers(headers, False)
|
|
|
|
# set default request time out
|
|
kwargs['timeout'] = kwargs.get('timeout', self.__request_time_out)
|
|
rsp = self._request(method, path, data, headers=req_headers, **kwargs)
|
|
|
|
if rsp.status_code in self.STATUS_NO_AUTH:
|
|
LOG.info('token may expired, fetch again.')
|
|
req_headers = self._update_and_get_headers(headers, True)
|
|
rsp = self._request(method, path, data, headers=req_headers,
|
|
**kwargs)
|
|
|
|
# catch message sending exception
|
|
self._raise_if_not_in_status_ok(rsp)
|
|
ret_data = {'response': rsp, 'data': None}
|
|
|
|
if rsp.text:
|
|
try:
|
|
ret_data['data'] = rsp.json()
|
|
# ignore pylint:disable=W0703
|
|
except Exception as excp:
|
|
LOG.warn(_('failed to loads json response data, %s'), excp)
|
|
ret_data['data'] = rsp.text
|
|
|
|
if kwargs.get('need_response', False):
|
|
return ret_data
|
|
return ret_data['data']
|
|
|
|
def _raise_if_not_in_status_ok(self, rsp):
|
|
"""if response is not normal,rasise exception
|
|
|
|
:param rsp:
|
|
:return:
|
|
"""
|
|
if rsp.status_code not in self.STATUS_OK:
|
|
error_info = {}
|
|
try:
|
|
error_info = rsp.json()
|
|
# ignore pylint:disable=W0703
|
|
except Exception as excp:
|
|
LOG.warn('try to get error response content failed: %s', excp)
|
|
|
|
raise exception.RequestError(reason=error_info.get('errorDes'),
|
|
error_code=error_info.get('errorCode')
|
|
)
|
|
|
|
def get_token(self):
|
|
"""Get token from FC
|
|
|
|
:return
|
|
"""
|
|
response = self._request('post', constant.TOKEN_URI, data={},
|
|
headers=self._make_headers())
|
|
self.__token = response.headers['X-Auth-Token']
|
|
|
|
def get_sites(self):
|
|
"""get fc default site info
|
|
|
|
:return:
|
|
"""
|
|
return self.get(constant.SITE_URI)
|
|
|
|
def get_first_site(self):
|
|
|
|
sites = self.get_sites()
|
|
if not sites or not sites.get('sites'):
|
|
raise exception.NoAvailableSite()
|
|
return sites['sites'][0]
|
|
|
|
def set_default_site(self):
|
|
|
|
self.context.set_default_site(self.get_first_site())
|
|
|
|
def _make_headers(self, token=None):
|
|
"""make token header info
|
|
|
|
:param token:
|
|
:return:
|
|
"""
|
|
headers = {
|
|
'Accept-Language': self.__accept_language,
|
|
'Content-Type': self.__content_type,
|
|
'Accept': self.__accept
|
|
}
|
|
|
|
if token:
|
|
headers.update({
|
|
'X-Auth-Token': token
|
|
})
|
|
else:
|
|
headers.update({
|
|
'X-Auth-User': self.__user,
|
|
'X-Auth-Key': self.__key,
|
|
'X-Auth-UserType': self.__user_type,
|
|
'X-ENCRIPT-ALGORITHM': '1'
|
|
})
|
|
return headers
|
|
|
|
|
|
class FCClientContext(dict):
|
|
"""fc base info"""
|
|
|
|
def __init__(self, client):
|
|
super(FCClientContext, self).__init__()
|
|
self.client = client
|
|
self.site_uri_map = None
|
|
|
|
def __getattr__(self, name):
|
|
"""if dict has attr,return dict ,else return site uri info
|
|
|
|
:param name:
|
|
:return:
|
|
"""
|
|
if self.get(name):
|
|
return self.get(name)
|
|
elif self.site_uri_map:
|
|
return utils.get_fc_uri(name, self.site_uri_map)
|
|
else:
|
|
return None
|
|
|
|
def set_default_site(self, site):
|
|
"""set default site infos
|
|
|
|
:param site:
|
|
:return:
|
|
"""
|
|
self['site'] = site
|
|
self['site_id'] = utils.get_id_from_urn(self['site']['urn'])
|
|
self['site_uri'] = '/'.join([constant.SITE_URI, self['site_id']])
|
|
|
|
self.site_uri_map = {'site_uri': self['site_uri']}
|
|
|
|
def get_path_by_site(self, path='', **kwargs):
|
|
"""Connect your path with default site path, and format args value
|
|
|
|
:param path: in format like '/resource/%<id>s/action/%(other)s'
|
|
:param kwargs: Dictionary args, matched path format, like (id=id_value,
|
|
other=other_value)
|
|
:return: path like
|
|
'/service/sites/site_id/resource/id_value/action/other_value'
|
|
"""
|
|
if not kwargs:
|
|
kwargs = {}
|
|
|
|
if isinstance(path, list):
|
|
path = ''.join(path)
|
|
|
|
return ''.join([self['site_uri'], path % kwargs])
|