From d76c660977d0b8dc1cc8fe051ae718d58a25728f Mon Sep 17 00:00:00 2001 From: nikeshm Date: Tue, 11 Aug 2015 19:32:44 +0530 Subject: [PATCH] Use Requests HTTP library and URL safe names Use Requests HTTP library instead of urllib, and also use URL safe resource names to communicate to the DotHill array. Change-Id: If20bca9f375269cf652ef367c1b70eb061f57337 Closes-Bug: #1461718 Co-Authored-By: Lakshman --- cinder/tests/unit/test_dothill.py | 23 ++++++++++--------- .../volume/drivers/dothill/dothill_client.py | 15 ++++++------ .../volume/drivers/dothill/dothill_common.py | 21 ++++------------- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/cinder/tests/unit/test_dothill.py b/cinder/tests/unit/test_dothill.py index e3a3cd7da..b1528793b 100644 --- a/cinder/tests/unit/test_dothill.py +++ b/cinder/tests/unit/test_dothill.py @@ -18,7 +18,7 @@ from lxml import etree import mock -from six.moves import urllib +import requests from cinder import exception from cinder import test @@ -149,14 +149,14 @@ class TestDotHillClient(test.TestCase): self.client = dothill.DotHillClient(self.ip, self.login, self.passwd, self.protocol) - @mock.patch('six.moves.urllib.request.urlopen') - def test_login(self, mock_url_open): + @mock.patch('requests.get') + def test_login(self, mock_requests_get): m = mock.Mock() - m.read.side_effect = [resp_login] - mock_url_open.return_value = m + m.text.encode.side_effect = [resp_login] + mock_requests_get.return_value = m self.client.login() self.assertEqual(session_key, self.client._session_key) - m.read.side_effect = [resp_badlogin] + m.text.encode.side_effect = [resp_badlogin] self.assertRaises(exception.DotHillAuthenticationError, self.client.login) @@ -175,14 +175,15 @@ class TestDotHillClient(test.TestCase): arg2='val2') self.assertEqual('http://10.0.0.1/api/path/arg2/val2/arg1/arg3', url) - @mock.patch('six.moves.urllib.request.urlopen') - def test_request(self, mock_url_open): + @mock.patch('requests.get') + def test_request(self, mock_requests_get): self.client._session_key = session_key m = mock.Mock() - m.read.side_effect = [response_ok, malformed_xml, - urllib.error.URLError("error")] - mock_url_open.return_value = m + m.text.encode.side_effect = [response_ok, malformed_xml, + requests.exceptions. + RequestException("error")] + mock_requests_get.return_value = m ret = self.client._request('/path') self.assertTrue(type(ret) == etree._Element) self.assertRaises(exception.DotHillConnectionError, diff --git a/cinder/volume/drivers/dothill/dothill_client.py b/cinder/volume/drivers/dothill/dothill_client.py index a2054bdaa..5cc864805 100644 --- a/cinder/volume/drivers/dothill/dothill_client.py +++ b/cinder/volume/drivers/dothill/dothill_client.py @@ -20,8 +20,8 @@ import time from lxml import etree from oslo_log import log as logging +import requests import six -from six.moves import urllib from cinder import exception from cinder.i18n import _LE @@ -53,11 +53,11 @@ class DotHillClient(object): url = self._base_url + "/login/" + digest try: - xml = urllib.request.urlopen(url).read() - except urllib.error.URLError: + xml = requests.get(url) + except requests.exceptions.RequestException: raise exception.DotHillConnectionError - self._get_auth_token(xml) + self._get_auth_token(xml.text.encode('utf8')) if self._session_key is None: raise exception.DotHillAuthenticationError @@ -95,10 +95,9 @@ class DotHillClient(object): url = self._build_request_url(path, *args, **kargs) headers = {'dataType': 'api', 'sessionKey': self._session_key} - req = urllib.request.Request(url, headers=headers) try: - xml = urllib.request.urlopen(req).read() - tree = etree.XML(xml) + xml = requests.get(url, headers=headers) + tree = etree.XML(xml.text.encode('utf8')) except Exception: raise exception.DotHillConnectionError @@ -110,7 +109,7 @@ class DotHillClient(object): def logout(self): url = self._base_url + '/exit' try: - urllib.request.urlopen(url) + requests.get(url) return True except Exception: return False diff --git a/cinder/volume/drivers/dothill/dothill_common.py b/cinder/volume/drivers/dothill/dothill_common.py index 492546ef0..7f1ac84b2 100644 --- a/cinder/volume/drivers/dothill/dothill_common.py +++ b/cinder/volume/drivers/dothill/dothill_common.py @@ -129,29 +129,16 @@ class DotHillCommon(object): fceec30e-98bc-4ce5-85ff-d7309cc17cc2 to v_O7DDpi8TOWF_9cwnMF - - We convert the 128(32*4) bits of the uuid into a 24character long + We convert the 128(32*4) bits of the uuid into a 24 characters long base64 encoded string. This still exceeds the limit of 20 characters - so we truncate the name later. + in some models so we return 19 characters because the + _get_{vol,snap}_name functions prepend a character. """ uuid_str = name.replace("-", "") vol_uuid = uuid.UUID('urn:uuid:%s' % uuid_str) - vol_encoded = base64.b64encode(vol_uuid.bytes) + vol_encoded = base64.urlsafe_b64encode(vol_uuid.bytes) if six.PY3: vol_encoded = vol_encoded.decode('ascii') - vol_encoded = vol_encoded.replace('=', '') - - # + is not a valid character for DotHill - vol_encoded = vol_encoded.replace('+', '.') - # since we use http URLs to send paramters, '/' is not an acceptable - # parameter - vol_encoded = vol_encoded.replace('/', '_') - - # NOTE:we limit the size to 20 characters since the array - # doesn't support more than that for now. Duplicates should happen very - # rarely. - # We return 19 chars here because the _get_{vol,snap}_name functions - # prepend a character return vol_encoded[:19] def check_flags(self, options, required_flags): -- 2.45.2