Nexenta volume drivers: refactor NexentaJSONProxy
Change constructor arguments of NexentaJSONProxy. Change-Id: I43d69485e6a98704f4cb02a4b55acccf9c05b683
This commit is contained in:
parent
338c826f2c
commit
87f47e1595
@ -23,7 +23,6 @@ import base64
|
||||
import urllib2
|
||||
|
||||
import mox as mox_lib
|
||||
from mox import stubout
|
||||
|
||||
from cinder import test
|
||||
from cinder import units
|
||||
@ -270,19 +269,22 @@ class TestNexentaDriver(test.TestCase):
|
||||
|
||||
|
||||
class TestNexentaJSONRPC(test.TestCase):
|
||||
URL = 'http://example.com/'
|
||||
URL_S = 'https://example.com/'
|
||||
HOST = 'example.com'
|
||||
URL = 'http://%s/' % HOST
|
||||
URL_S = 'https://%s/' % HOST
|
||||
USER = 'user'
|
||||
PASSWORD = 'password'
|
||||
HEADERS = {'Authorization': 'Basic %s' % (
|
||||
base64.b64encode(':'.join((USER, PASSWORD))),),
|
||||
'Content-Type': 'application/json'}
|
||||
HEADERS = {
|
||||
'Authorization':
|
||||
'Basic %s' % base64.b64encode('%s:%s' % (USER, PASSWORD)),
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
REQUEST = 'the request'
|
||||
|
||||
def setUp(self):
|
||||
super(TestNexentaJSONRPC, self).setUp()
|
||||
self.proxy = jsonrpc.NexentaJSONProxy(
|
||||
self.URL, self.USER, self.PASSWORD, auto=True)
|
||||
'http', self.HOST, 2000, '/', self.USER, self.PASSWORD, auto=True)
|
||||
self.mox.StubOutWithMock(urllib2, 'Request', True)
|
||||
self.mox.StubOutWithMock(urllib2, 'urlopen')
|
||||
self.resp_mock = self.mox.CreateMockAnything()
|
||||
@ -292,7 +294,7 @@ class TestNexentaJSONRPC(test.TestCase):
|
||||
|
||||
def test_call(self):
|
||||
urllib2.Request(
|
||||
self.URL,
|
||||
'http://%s:2000/' % self.HOST,
|
||||
'{"object": null, "params": ["arg1", "arg2"], "method": null}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
self.resp_info_mock.status = ''
|
||||
@ -304,7 +306,7 @@ class TestNexentaJSONRPC(test.TestCase):
|
||||
|
||||
def test_call_deep(self):
|
||||
urllib2.Request(
|
||||
self.URL,
|
||||
'http://%s:2000/' % self.HOST,
|
||||
'{"object": "obj1.subobj", "params": ["arg1", "arg2"],'
|
||||
' "method": "meth"}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
@ -317,11 +319,11 @@ class TestNexentaJSONRPC(test.TestCase):
|
||||
|
||||
def test_call_auto(self):
|
||||
urllib2.Request(
|
||||
self.URL,
|
||||
'http://%s:2000/' % self.HOST,
|
||||
'{"object": null, "params": ["arg1", "arg2"], "method": null}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
urllib2.Request(
|
||||
self.URL_S,
|
||||
'https://%s:2000/' % self.HOST,
|
||||
'{"object": null, "params": ["arg1", "arg2"], "method": null}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
self.resp_info_mock.status = 'EOF in headers'
|
||||
@ -334,7 +336,7 @@ class TestNexentaJSONRPC(test.TestCase):
|
||||
|
||||
def test_call_error(self):
|
||||
urllib2.Request(
|
||||
self.URL,
|
||||
'http://%s:2000/' % self.HOST,
|
||||
'{"object": null, "params": ["arg1", "arg2"], "method": null}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
self.resp_info_mock.status = ''
|
||||
@ -346,7 +348,7 @@ class TestNexentaJSONRPC(test.TestCase):
|
||||
|
||||
def test_call_fail(self):
|
||||
urllib2.Request(
|
||||
self.URL,
|
||||
'http://%s:2000/' % self.HOST,
|
||||
'{"object": null, "params": ["arg1", "arg2"], "method": null}',
|
||||
self.HEADERS).AndReturn(self.REQUEST)
|
||||
self.resp_info_mock.status = 'EOF in headers'
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
.. automodule:: nexenta.jsonrpc
|
||||
.. moduleauthor:: Yuriy Taraday <yorik.sar@gmail.com>
|
||||
.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
|
||||
"""
|
||||
|
||||
import urllib2
|
||||
@ -36,8 +37,13 @@ class NexentaJSONException(nexenta.NexentaException):
|
||||
|
||||
|
||||
class NexentaJSONProxy(object):
|
||||
def __init__(self, url, user, password, auto=False, obj=None, method=None):
|
||||
self.url = url
|
||||
|
||||
def __init__(self, scheme, host, port, path, user, password, auto=False,
|
||||
obj=None, method=None):
|
||||
self.scheme = scheme.lower()
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.path = path
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.auto = auto
|
||||
@ -51,34 +57,46 @@ class NexentaJSONProxy(object):
|
||||
obj, method = self.obj, name
|
||||
else:
|
||||
obj, method = '%s.%s' % (self.obj, self.method), name
|
||||
return NexentaJSONProxy(self.url, self.user, self.password, self.auto,
|
||||
obj, method)
|
||||
return NexentaJSONProxy(self.scheme, self.host, self.port, self.path,
|
||||
self.user, self.password, self.auto, obj,
|
||||
method)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return '%s://%s:%s%s' % (self.scheme, self.host, self.port, self.path)
|
||||
|
||||
def __hash__(self):
|
||||
return self.url.__hash__()
|
||||
|
||||
def __repr__(self):
|
||||
return 'NMS proxy: %s' % self.url
|
||||
|
||||
def __call__(self, *args):
|
||||
data = jsonutils.dumps({'object': self.obj,
|
||||
data = jsonutils.dumps({
|
||||
'object': self.obj,
|
||||
'method': self.method,
|
||||
'params': args})
|
||||
'params': args
|
||||
})
|
||||
auth = ('%s:%s' % (self.user, self.password)).encode('base64')[:-1]
|
||||
headers = {'Content-Type': 'application/json',
|
||||
'Authorization': 'Basic %s' % (auth,)}
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Basic %s' % auth
|
||||
}
|
||||
LOG.debug(_('Sending JSON data: %s'), data)
|
||||
request = urllib2.Request(self.url, data, headers)
|
||||
response_obj = urllib2.urlopen(request)
|
||||
if response_obj.info().status == 'EOF in headers':
|
||||
if self.auto and self.url.startswith('http://'):
|
||||
LOG.info(_('Auto switching to HTTPS connection to %s'),
|
||||
self.url)
|
||||
self.url = 'https' + self.url[4:]
|
||||
request = urllib2.Request(self.url, data, headers)
|
||||
response_obj = urllib2.urlopen(request)
|
||||
else:
|
||||
if not self.auto or self.scheme != 'http':
|
||||
LOG.error(_('No headers in server response'))
|
||||
raise NexentaJSONException(_('Bad response from server'))
|
||||
LOG.info(_('Auto switching to HTTPS connection to %s'), self.url)
|
||||
self.scheme = 'https'
|
||||
request = urllib2.Request(self.url, data, headers)
|
||||
response_obj = urllib2.urlopen(request)
|
||||
|
||||
response_data = response_obj.read()
|
||||
LOG.debug(_('Got response: %s'), response_data)
|
||||
response = jsonutils.loads(response_data)
|
||||
if response.get('error') is not None:
|
||||
raise NexentaJSONException(response['error'].get('message', ''))
|
||||
else:
|
||||
return response.get('result')
|
||||
|
@ -349,28 +349,12 @@ class NexentaNfsDriver(nfs.NfsDriver): # pylint: disable=R0921
|
||||
allocated = utils.str2size(folder_props['used'])
|
||||
return free + allocated, free, allocated
|
||||
|
||||
def _get_nms_for_url(self, nms_url):
|
||||
pr = urlparse.urlparse(nms_url)
|
||||
scheme = pr.scheme
|
||||
auto = scheme == 'auto'
|
||||
if auto:
|
||||
scheme = 'http'
|
||||
user = 'admin'
|
||||
password = 'nexenta'
|
||||
if '@' not in pr.netloc:
|
||||
host_and_port = pr.netloc
|
||||
else:
|
||||
user_and_password, host_and_port = pr.netloc.split('@', 1)
|
||||
if ':' in user_and_password:
|
||||
user, password = user_and_password.split(':')
|
||||
else:
|
||||
user = user_and_password
|
||||
if ':' in host_and_port:
|
||||
host, port = host_and_port.split(':', 1)
|
||||
else:
|
||||
host, port = host_and_port, '2000'
|
||||
url = '%s://%s:%s/rest/nms/' % (scheme, host, port)
|
||||
return jsonrpc.NexentaJSONProxy(url, user, password, auto=auto)
|
||||
def _get_nms_for_url(self, url):
|
||||
"""Returns initialized nms object for url."""
|
||||
auto, scheme, user, password, host, port, path =\
|
||||
utils.parse_nms_url(url)
|
||||
return jsonrpc.NexentaJSONProxy(scheme, host, port, path, user,
|
||||
password, auto=auto)
|
||||
|
||||
def _get_snapshot_volume(self, snapshot):
|
||||
ctxt = context.get_admin_context()
|
||||
|
@ -14,8 +14,17 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""
|
||||
:mod:`nexenta.utils` -- Nexenta-specific utils functions.
|
||||
=========================================================
|
||||
|
||||
.. automodule:: nexenta.utils
|
||||
.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
|
||||
.. moduleauthor:: Mikhail Khodos <hodosmb@gmail.com>
|
||||
"""
|
||||
|
||||
import re
|
||||
import urlparse
|
||||
|
||||
|
||||
def str2size(s, scale=1024):
|
||||
@ -40,7 +49,48 @@ def str2size(s, scale=1024):
|
||||
value = float(groups[0])
|
||||
suffix = len(groups) > 1 and groups[1].upper() or 'B'
|
||||
|
||||
types = ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
|
||||
types = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
|
||||
for i, t in enumerate(types):
|
||||
if suffix == t:
|
||||
return int(value * pow(scale, i))
|
||||
|
||||
|
||||
def parse_nms_url(url):
|
||||
"""Parse NMS url into normalized parts like scheme, user, host and others.
|
||||
|
||||
Example NMS URL:
|
||||
auto://admin:nexenta@192.168.1.1:2000/
|
||||
|
||||
NMS URL parts:
|
||||
auto True if url starts with auto://, protocol will be
|
||||
automatically switched to https if http not
|
||||
supported;
|
||||
scheme (auto) connection protocol (http or https);
|
||||
user (admin) NMS user;
|
||||
password (nexenta) NMS password;
|
||||
host (192.168.1.1) NMS host;
|
||||
port (2000) NMS port.
|
||||
|
||||
:param url: url string
|
||||
:return: tuple (auto, scheme, user, password, host, port, path)
|
||||
"""
|
||||
pr = urlparse.urlparse(url)
|
||||
scheme = pr.scheme
|
||||
auto = scheme == 'auto'
|
||||
if auto:
|
||||
scheme = 'http'
|
||||
user = 'admin'
|
||||
password = 'nexenta'
|
||||
if '@' not in pr.netloc:
|
||||
host_and_port = pr.netloc
|
||||
else:
|
||||
user_and_password, host_and_port = pr.netloc.split('@', 1)
|
||||
if ':' in user_and_password:
|
||||
user, password = user_and_password.split(':')
|
||||
else:
|
||||
user = user_and_password
|
||||
if ':' in host_and_port:
|
||||
host, port = host_and_port.split(':', 1)
|
||||
else:
|
||||
host, port = host_and_port, '2000'
|
||||
return auto, scheme, user, password, host, port, '/rest/nms/'
|
||||
|
@ -69,11 +69,10 @@ class NexentaDriver(driver.ISCSIDriver): # pylint: disable=R0921
|
||||
auto = protocol == 'auto'
|
||||
if auto:
|
||||
protocol = 'http'
|
||||
url = '%s://%s:%s/rest/nms/' % (protocol,
|
||||
self.configuration.nexenta_host,
|
||||
self.configuration.nexenta_rest_port)
|
||||
self.nms = jsonrpc.NexentaJSONProxy(
|
||||
url, self.configuration.nexenta_user,
|
||||
protocol, self.configuration.nexenta_host,
|
||||
self.configuration.nexenta_rest_port, '/rest/nms',
|
||||
self.configuration.nexenta_user,
|
||||
self.configuration.nexenta_password, auto=auto)
|
||||
|
||||
def check_for_setup_error(self):
|
||||
|
Loading…
Reference in New Issue
Block a user