Refactor _connect to be called only once
Rather than establishing a new HTTP(S) connection for every operation this refactors HTTP[S]Connect into RedfishConnection._connect, and calls it only once, during __init__.
This commit is contained in:
parent
695181c8b2
commit
c8df358c28
@ -138,19 +138,55 @@ class RedfishConnection(object):
|
|||||||
|
|
||||||
def __init__(self, host, user_name, password,
|
def __init__(self, host, user_name, password,
|
||||||
auth_token=None, enforce_SSL=True):
|
auth_token=None, enforce_SSL=True):
|
||||||
|
"""Initialize a connection to a Redfish service."""
|
||||||
super(RedfishConnection, self).__init__()
|
super(RedfishConnection, self).__init__()
|
||||||
self.host = host
|
|
||||||
self.user_name = user_name
|
self.user_name = user_name
|
||||||
self.password = password
|
self.password = password
|
||||||
self.auth_token = auth_token
|
self.auth_token = auth_token
|
||||||
self.enforce_SSL = enforce_SSL
|
self.enforce_SSL = enforce_SSL
|
||||||
|
|
||||||
|
# If the http schema wasn't specified, default to HTTPS
|
||||||
|
if host[0:4] != 'http':
|
||||||
|
host = 'https://' + host
|
||||||
|
self.host = host
|
||||||
|
self._connect()
|
||||||
|
|
||||||
|
if not self.auth_token:
|
||||||
# TODO: cache the token returned by this call
|
# TODO: cache the token returned by this call
|
||||||
|
LOG.debug('Initiating session with host %s', self.host)
|
||||||
auth_dict = {'Password': self.password, 'UserName': self.user_name}
|
auth_dict = {'Password': self.password, 'UserName': self.user_name}
|
||||||
self.rest_post('/rest/v1/Sessions', None, json.dumps(auth_dict))
|
self.rest_post('/rest/v1/Sessions', None, json.dumps(auth_dict))
|
||||||
|
|
||||||
# TODO: do some schema discovery here and cache the result
|
# TODO: do some schema discovery here and cache the result
|
||||||
LOG.debug('Connection established to host %s.', self.host)
|
# self.schema = ...
|
||||||
|
LOG.info('Connection established to host %s', self.host)
|
||||||
|
|
||||||
|
def _connect(self):
|
||||||
|
LOG.debug("Establishing connection to host %s", self.host)
|
||||||
|
url = urlparse(self.host)
|
||||||
|
if url.scheme == 'https':
|
||||||
|
# New in Python 2.7.9, SSL enforcement is defaulted on.
|
||||||
|
# It can be opted-out of, which might be useful for debugging
|
||||||
|
# some things. The below case is the Opt-Out condition and
|
||||||
|
# should be used with GREAT caution.
|
||||||
|
if (sys.version_info.major == 2
|
||||||
|
and sys.version_info.minor == 7
|
||||||
|
and sys.version_info.micro >= 9
|
||||||
|
and self.enforce_SSL == False):
|
||||||
|
cont = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
cont.verify_mode = ssl.CERT_NONE
|
||||||
|
self.connection = httplib.HTTPSConnection(
|
||||||
|
host=url.netloc, strict=True, context=cont)
|
||||||
|
else:
|
||||||
|
self.connection = httplib.HTTPSConnection(
|
||||||
|
host=url.netloc, strict=True)
|
||||||
|
elif url.scheme == 'http':
|
||||||
|
self.connection = httplib.HTTPConnection(
|
||||||
|
host=url.netloc, strict=True)
|
||||||
|
else:
|
||||||
|
raise exception.RedfishException(
|
||||||
|
message='Unknown connection schema')
|
||||||
|
|
||||||
def _op(self, operation, suburi, request_headers=None, request_body=None):
|
def _op(self, operation, suburi, request_headers=None, request_body=None):
|
||||||
"""
|
"""
|
||||||
@ -178,40 +214,16 @@ class RedfishConnection(object):
|
|||||||
self.user_name + ":" + self.password))
|
self.user_name + ":" + self.password))
|
||||||
# TODO: add support for other types of auth
|
# TODO: add support for other types of auth
|
||||||
|
|
||||||
# TODO: think about redirects....
|
|
||||||
redir_count = 4
|
redir_count = 4
|
||||||
while redir_count:
|
while redir_count:
|
||||||
conn = None
|
|
||||||
if url.scheme == 'https':
|
|
||||||
# New in Python 2.7.9, SSL enforcement is defaulted on.
|
|
||||||
# It can be opted-out of, which might be useful for debugging
|
|
||||||
# some things. The below case is the Opt-Out condition and
|
|
||||||
# should be used with GREAT caution.
|
|
||||||
if (sys.version_info.major == 2
|
|
||||||
and sys.version_info.minor == 7
|
|
||||||
and sys.version_info.micro >= 9
|
|
||||||
and self.enforce_SSL == False):
|
|
||||||
cont = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
|
||||||
cont.verify_mode = ssl.CERT_NONE
|
|
||||||
conn = httplib.HTTPSConnection(
|
|
||||||
host=url.netloc, strict=True, context=cont)
|
|
||||||
else:
|
|
||||||
conn = httplib.HTTPSConnection(host=url.netloc,
|
|
||||||
strict=True)
|
|
||||||
elif url.scheme == 'http':
|
|
||||||
conn = httplib.HTTPConnection(host=url.netloc, strict=True)
|
|
||||||
else:
|
|
||||||
raise exception.RedfishException(
|
|
||||||
message='Unknown connection schema')
|
|
||||||
|
|
||||||
# NOTE: Do not assume every HTTP operation will return a JSON body.
|
# NOTE: Do not assume every HTTP operation will return a JSON body.
|
||||||
# For example, ExtendedError structures are only required for
|
# For example, ExtendedError structures are only required for
|
||||||
# HTTP 400 errors and are optional elsewhere as they are mostly
|
# HTTP 400 errors and are optional elsewhere as they are mostly
|
||||||
# redundant for many of the other HTTP status code. In particular,
|
# redundant for many of the other HTTP status code. In particular,
|
||||||
# 200 OK responses should not have to return any body.
|
# 200 OK responses should not have to return any body.
|
||||||
conn.request(operation, url.path, headers=request_headers,
|
self.connection.request(operation, url.path,
|
||||||
body=json.dumps(request_body))
|
headers=request_headers, body=json.dumps(request_body))
|
||||||
resp = conn.getresponse()
|
resp = self.connection.getresponse()
|
||||||
body = resp.read()
|
body = resp.read()
|
||||||
# NOTE: this makes sure the headers names are all lower case
|
# NOTE: this makes sure the headers names are all lower case
|
||||||
# because HTTP says they are case insensitive
|
# because HTTP says they are case insensitive
|
||||||
@ -228,9 +240,7 @@ class RedfishConnection(object):
|
|||||||
|
|
||||||
response = dict()
|
response = dict()
|
||||||
try:
|
try:
|
||||||
LOG.debug("BODY: %s." % body.decode('utf-8'))
|
|
||||||
response = json.loads(body.decode('utf-8'))
|
response = json.loads(body.decode('utf-8'))
|
||||||
LOG.debug("Loaded json: %s" % response)
|
|
||||||
except ValueError: # if it doesn't decode as json
|
except ValueError: # if it doesn't decode as json
|
||||||
# NOTE: resources may return gzipped content, so try to decode
|
# NOTE: resources may return gzipped content, so try to decode
|
||||||
# as gzip (we should check the headers for Content-Encoding=gzip)
|
# as gzip (we should check the headers for Content-Encoding=gzip)
|
||||||
|
@ -102,6 +102,8 @@ class TestRedfishConnection(base.TestCase):
|
|||||||
# Headers ae lower cased when returned
|
# Headers ae lower cased when returned
|
||||||
self.assertIn('fake-header', res[1].keys())
|
self.assertIn('fake-header', res[1].keys())
|
||||||
self.assertIn('foo', res[2].keys())
|
self.assertIn('foo', res[2].keys())
|
||||||
|
self.con_mock.request.assert_called_with(
|
||||||
|
'GET', '/v1/test', body='null', headers=mock.ANY)
|
||||||
|
|
||||||
# TODO: add test for redirects
|
# TODO: add test for redirects
|
||||||
|
|
||||||
@ -113,6 +115,7 @@ class TestRedfishConnection(base.TestCase):
|
|||||||
body = '{"fake": "body"}'
|
body = '{"fake": "body"}'
|
||||||
json_body = json.dumps(body)
|
json_body = json.dumps(body)
|
||||||
con = connection.RedfishConnection(*get_fake_params())
|
con = connection.RedfishConnection(*get_fake_params())
|
||||||
res = con.rest_put('/v1/test', '', body)
|
res = con.rest_post('/v1/test', '', body)
|
||||||
self.con_mock.assert_called_with('GET', '/v1/test', {}, json_body)
|
|
||||||
self.assertEqual(200, res[0])
|
self.assertEqual(200, res[0])
|
||||||
|
self.con_mock.request.assert_called_with(
|
||||||
|
'POST', '/v1/test', body=json_body, headers=mock.ANY)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user