Huawei manila driver support multi RestURLs
- Add support for multi RestURLs - Add multi RestURLs unit tests RestURL is an access address of the REST interface. Multi RestURLs can be configured in manila_huawei_conf.xml(separated by ";") When one of the RestURL failed to connect, driver will retry another automatically. Implements: blueprint huawei-manila-driver-support-multi-resturls Change-Id: Iaecdd4761e388255af833a3e5b0bd1e1d42a0e22
This commit is contained in:
parent
2e4a34a331
commit
d2abb50840
@ -26,3 +26,6 @@ ACCESS_NFS_RW = "1"
|
||||
ACCESS_NFS_RO = "0"
|
||||
ACCESS_CIFS_RW = "5"
|
||||
ACCESS_CIFS_RO = "0"
|
||||
|
||||
ERROR_CONNECT_TO_SERVER = -403
|
||||
ERROR_UNAUTHORIZED_TO_SERVER = -401
|
||||
|
@ -43,7 +43,7 @@ class RestHelper(object):
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def call(self, url, data=None, method=None):
|
||||
def do_call(self, url, data=None, method=None):
|
||||
"""Send requests to server.
|
||||
|
||||
Send HTTPS call, get response in JSON.
|
||||
@ -58,6 +58,7 @@ class RestHelper(object):
|
||||
'data': data})
|
||||
opener = urlreq.build_opener(urlreq.HTTPCookieProcessor(self.cookie))
|
||||
urlreq.install_opener(opener)
|
||||
result = None
|
||||
|
||||
try:
|
||||
req = urlreq.Request(url, data, self.headers)
|
||||
@ -69,36 +70,80 @@ class RestHelper(object):
|
||||
LOG.debug('Response Data: %(res)s.', {'res': res})
|
||||
|
||||
except Exception as err:
|
||||
LOG.error(_LE('Bad response from server: %s.') % err)
|
||||
raise err
|
||||
LOG.error(_LE('\nBad response from server: %(url)s.'
|
||||
' Error: %(err)s'), {'url': url, 'err': err})
|
||||
res = '{"error":{"code":%s,' \
|
||||
'"description":"Connect server error"}}' \
|
||||
% constants.ERROR_CONNECT_TO_SERVER
|
||||
|
||||
try:
|
||||
res_json = jsonutils.loads(res)
|
||||
result = jsonutils.loads(res)
|
||||
except Exception as err:
|
||||
err_msg = (_('JSON transfer error: %s.') % err)
|
||||
LOG.error(err_msg)
|
||||
raise exception.InvalidShare(reason=err_msg)
|
||||
raise exception.InvalidInput(reason=err_msg)
|
||||
|
||||
return res_json
|
||||
return result
|
||||
|
||||
def login(self):
|
||||
"""Log in huawei array."""
|
||||
"""Login huawei array."""
|
||||
login_info = self._get_login_info()
|
||||
url = login_info['RestURL'] + "xx/sessions"
|
||||
data = jsonutils.dumps({"username": login_info['UserName'],
|
||||
"password": login_info['UserPassword'],
|
||||
"scope": "0"})
|
||||
result = self.call(url, data)
|
||||
if (result['error']['code'] != 0) or ("data" not in result):
|
||||
err_msg = (_("Login error, reason is %s.") % result)
|
||||
urlstr = login_info['RestURL']
|
||||
url_list = urlstr.split(";")
|
||||
deviceid = None
|
||||
for item_url in url_list:
|
||||
url = item_url.strip('').strip('\n') + "xx/sessions"
|
||||
data = jsonutils.dumps({"username": login_info['UserName'],
|
||||
"password": login_info['UserPassword'],
|
||||
"scope": "0"})
|
||||
result = self.do_call(url, data)
|
||||
|
||||
if((result['error']['code'] != 0)
|
||||
or ("data" not in result)
|
||||
or (result['data']['deviceid'] is None)):
|
||||
err_msg = (_("Login to %s failed, try another") % item_url)
|
||||
LOG.error(err_msg)
|
||||
continue
|
||||
|
||||
LOG.debug('Login success: %(url)s\n',
|
||||
{'url': item_url})
|
||||
deviceid = result['data']['deviceid']
|
||||
self.url = item_url + deviceid
|
||||
self.headers['iBaseToken'] = result['data']['iBaseToken']
|
||||
break
|
||||
|
||||
if deviceid is None:
|
||||
err_msg = (_("All url Login fail"))
|
||||
LOG.error(err_msg)
|
||||
raise exception.InvalidShare(reason=err_msg)
|
||||
|
||||
deviceid = result['data']['deviceid']
|
||||
self.url = login_info['RestURL'] + deviceid
|
||||
self.headers['iBaseToken'] = result['data']['iBaseToken']
|
||||
return deviceid
|
||||
|
||||
def call(self, url, data=None, method=None):
|
||||
"""Send requests to server.
|
||||
|
||||
if fail, try another RestURL
|
||||
"""
|
||||
deviceid = None
|
||||
old_url = self.url
|
||||
result = self.do_call(url, data, method)
|
||||
error_code = result['error']['code']
|
||||
if(error_code == constants.ERROR_CONNECT_TO_SERVER
|
||||
or error_code == constants.ERROR_UNAUTHORIZED_TO_SERVER):
|
||||
err_msg = (_("Can't open the recent url, re-login."))
|
||||
LOG.error(err_msg)
|
||||
deviceid = self.login()
|
||||
|
||||
if deviceid is not None:
|
||||
LOG.debug('Replace URL: \n'
|
||||
'Old URL: %(old_url)s\n'
|
||||
'New URL: %(new_url)s\n',
|
||||
{'old_url': old_url,
|
||||
'new_url': self.url})
|
||||
url = url.replace(old_url, self.url)
|
||||
result = self.do_call(url, data, method)
|
||||
return result
|
||||
|
||||
def _create_filesystem(self, fs_param):
|
||||
"""Create file system."""
|
||||
url = self.url + "/filesystem"
|
||||
|
@ -139,15 +139,29 @@ class FakeHuaweiNasHelper(helper.RestHelper):
|
||||
self.allow_ro_flag = False
|
||||
self.allow_rw_flag = False
|
||||
self.extend_share_flag = False
|
||||
self.test_multi_url_flag = 0
|
||||
|
||||
def _change_file_mode(self, filepath):
|
||||
pass
|
||||
|
||||
def call(self, url, data=None, method=None):
|
||||
def do_call(self, url, data=None, method=None):
|
||||
url = url.replace('http://100.115.10.69:8082/deviceManager/rest', '')
|
||||
url = url.replace('/210235G7J20000000000/', '')
|
||||
|
||||
if self.test_normal:
|
||||
if self.test_multi_url_flag == 1:
|
||||
data = '{"error":{"code":-403}}'
|
||||
res_json = jsonutils.loads(data)
|
||||
return res_json
|
||||
elif self.test_multi_url_flag == 2:
|
||||
if 'http://100.115.10.70:8082/deviceManager/rest' in url:
|
||||
url = url.replace('http://100.115.10.70:8082/'
|
||||
'deviceManager/rest', '')
|
||||
else:
|
||||
data = '{"error":{"code":-403}}'
|
||||
res_json = jsonutils.loads(data)
|
||||
return res_json
|
||||
|
||||
if url == "/xx/sessions" or url == "sessions":
|
||||
data = data_session(url)
|
||||
|
||||
@ -979,11 +993,34 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
self.driver.delete_snapshot, self._context,
|
||||
self.cifs_snapshot, self.share_server)
|
||||
|
||||
def test_multi_resturls_success(self):
|
||||
self.recreate_fake_conf_file(multi_url=True)
|
||||
self.driver.plugin.configuration.manila_huawei_conf_file = (
|
||||
self.fake_conf_file)
|
||||
self.driver.plugin.helper.login()
|
||||
self.driver.plugin.helper.test_multi_url_flag = 2
|
||||
location = self.driver.create_share(self._context, self.share_nfs,
|
||||
self.share_server)
|
||||
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
|
||||
|
||||
def test_multi_resturls_fail(self):
|
||||
self.recreate_fake_conf_file(multi_url=True)
|
||||
self.driver.plugin.configuration.manila_huawei_conf_file = (
|
||||
self.fake_conf_file)
|
||||
self.driver.plugin.helper.login()
|
||||
self.driver.plugin.helper.test_multi_url_flag = 1
|
||||
self.assertRaises(exception.InvalidShare,
|
||||
self.driver.create_share,
|
||||
self._context,
|
||||
self.share_nfs,
|
||||
self.share_server)
|
||||
|
||||
def create_fake_conf_file(self, fake_conf_file,
|
||||
product_flag=True, username_flag=True,
|
||||
pool_node_flag=True, timeout_flag=True,
|
||||
wait_interval_flag=True,
|
||||
alloctype_value='Thick'):
|
||||
alloctype_value='Thick',
|
||||
multi_url=False):
|
||||
doc = xml.dom.minidom.Document()
|
||||
config = doc.createElement('Config')
|
||||
doc.appendChild(config)
|
||||
@ -1019,8 +1056,14 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
userpassword.appendChild(userpassword_text)
|
||||
storage.appendChild(userpassword)
|
||||
url = doc.createElement('RestURL')
|
||||
url_text = doc.createTextNode('http://100.115.10.69:8082/'
|
||||
'deviceManager/rest/')
|
||||
if multi_url:
|
||||
url_text = doc.createTextNode('http://100.115.10.69:8082/'
|
||||
'deviceManager/rest/;'
|
||||
'http://100.115.10.70:8082/'
|
||||
'deviceManager/rest/')
|
||||
else:
|
||||
url_text = doc.createTextNode('http://100.115.10.69:8082/'
|
||||
'deviceManager/rest/')
|
||||
url.appendChild(url_text)
|
||||
storage.appendChild(url)
|
||||
|
||||
@ -1070,12 +1113,13 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
def recreate_fake_conf_file(self, product_flag=True, username_flag=True,
|
||||
pool_node_flag=True, timeout_flag=True,
|
||||
wait_interval_flag=True,
|
||||
alloctype_value='Thick'):
|
||||
alloctype_value='Thick',
|
||||
multi_url=False):
|
||||
self.tmp_dir = tempfile.mkdtemp()
|
||||
self.fake_conf_file = self.tmp_dir + '/manila_huawei_conf.xml'
|
||||
self.addCleanup(shutil.rmtree, self.tmp_dir)
|
||||
self.create_fake_conf_file(self.fake_conf_file, product_flag,
|
||||
username_flag, pool_node_flag,
|
||||
timeout_flag, wait_interval_flag,
|
||||
alloctype_value)
|
||||
alloctype_value, multi_url)
|
||||
self.addCleanup(os.remove, self.fake_conf_file)
|
||||
|
Loading…
Reference in New Issue
Block a user