diff --git a/README.rst b/README.rst index 3d8be7f..3e5de0c 100644 --- a/README.rst +++ b/README.rst @@ -3,11 +3,11 @@ HP LeftHand/StoreVirtual REST Client This is a Client library that can talk to the HP LeftHand/StoreVirtual Storage array. The HP LeftHand storage array has a REST web service interface. This client library implements a simple interface to talk with that REST -interface using the python Requests http library. +interface using the python httplib2 http library. Requirements ============ -This branch requires 11.5 version or later of the LeftHand OS firmware. +This branch requires 11.5 version of the LeftHand OS firmware. Capabilities ============ diff --git a/docs/api/hplefthandclient/client.rst b/docs/api/hplefthandclient/client.rst index 5c3e1e4..8cb7f48 100644 --- a/docs/api/hplefthandclient/client.rst +++ b/docs/api/hplefthandclient/client.rst @@ -4,7 +4,7 @@ .. automodule:: hplefthandclient.client :synopsis: HP LeftHand REST Web client - .. autoclass:: hplefthandclient.client.HPLeftHandClient(api_url, secure=False) + .. autoclass:: hplefthandclient.client.HPLeftHandClient(api_url) .. automethod:: debug_rest .. automethod:: login diff --git a/docs/api/hplefthandclient/http.rst b/docs/api/hplefthandclient/http.rst index a5c5300..9d130ec 100644 --- a/docs/api/hplefthandclient/http.rst +++ b/docs/api/hplefthandclient/http.rst @@ -4,7 +4,7 @@ .. automodule:: hplefthandclient.http :synopsis: HTTP REST Base Class - .. autoclass:: hplefthandclient.http.HTTPJSONRESTClient(api_url, [secure=True[,http_log_debug=False]]) + .. autoclass:: hplefthandclient.http.HTTPJSONRESTClient(api_url, [insecure=False[,http_log_debug=False]]) .. automethod:: authenticate .. automethod:: unauthenticate diff --git a/docs/changelog.rst b/docs/changelog.rst index 55b677e..48e6741 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -58,7 +58,7 @@ Changes in Version 1.0.5 * Added improved error handling during login attempts. Errors will now be more descriptive in why a login failed. -Changes in Version 1.1.0 +Changes in Version 1.0.6 ------------------------ * Python3.4+ compliant @@ -66,10 +66,6 @@ Changes in Version 1.1.0 pull and install from * Updated tox to run py34 tests * Modified basic Python calls to work with both Python2 and Python3.4 -* Replaced all httplib2 calls with Python Request calls -* SSL certificate verification can be enabled by passing secure=True -* SSL certificate verification can be done against a self provided .crt file - with secure='/path/to/ca-certificates.crt' * Fixed error that was happening during client initialization when an error was missing a description. * Fixes clusterId bug in createVolume (Issue #3) diff --git a/docs/tutorial.rst b/docs/tutorial.rst index 12798f2..8ec3b00 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -31,13 +31,6 @@ Doing so is easy: #LeftHand server with IP 10.10.10.10 on port 8008. cl = client.HPLeftHandClient("https://10.10.10.10:8008/api/v1") - # SSL certification verification is defaulted to False. In order to - # override this, set secure=True. or secure='/path/to/cert.crt' - # cl = client.HP3ParClient("https://10.10.10.10:8080/api/v1", - # secure=True) - # cl = client.HP3ParClient("https://10.10.10.10:8080/api/v1", - # secure='/etc/ssl/certs/ca-certificates.crt') - try: cl.login(username, password) print "Login worked!" diff --git a/hplefthandclient/__init__.py b/hplefthandclient/__init__.py index 5eba8cf..21a97b3 100644 --- a/hplefthandclient/__init__.py +++ b/hplefthandclient/__init__.py @@ -24,7 +24,7 @@ HP LeftHand REST Client """ -version_tuple = (1, 1, 0) +version_tuple = (1, 0, 6) def get_version_string(): diff --git a/hplefthandclient/client.py b/hplefthandclient/client.py index bdc8df3..da82ca4 100644 --- a/hplefthandclient/client.py +++ b/hplefthandclient/client.py @@ -40,10 +40,9 @@ from hplefthandclient import exceptions, http class HPLeftHandClient: - def __init__(self, api_url, debug=False, secure=False): + def __init__(self, api_url, debug=False): self.api_url = api_url - self.secure = secure - self.http = http.HTTPJSONRESTClient(self.api_url, secure=self.secure) + self.http = http.HTTPJSONRESTClient(self.api_url) self.api_version = None self.debug_rest(debug) @@ -76,8 +75,8 @@ class HPLeftHandClient: except Exception as ex: ex_desc = ex.get_description() - if (ex_desc and ("Unable to find the server at" in ex_desc or - "Only absolute URIs are allowed" in ex_desc)): + if (ex_desc and "Unable to find the server at" in ex_desc or + "Only absolute URIs are allowed" in ex_desc): raise exceptions.HTTPBadRequest(ex_desc) if (ex_desc and "SSL Certificate Verification Failed" in ex_desc): raise exceptions.SSLCertFailed() diff --git a/hplefthandclient/exceptions.py b/hplefthandclient/exceptions.py index 069b1b5..68ec0e7 100644 --- a/hplefthandclient/exceptions.py +++ b/hplefthandclient/exceptions.py @@ -105,6 +105,7 @@ class ClientException(Exception): return formatted_string + ## # SSL Errors ## @@ -118,53 +119,6 @@ class SSLCertFailed(ClientException): message = "SSL Certificate Verification Failed" -## -# Python Requests Errors -## - - -class RequestException(ClientException): - """ - There was an ambiguous exception that occurred in Requests - """ - pass - - -class ConnectionError(ClientException): - """ - There was an error connecting to the server - """ - pass - - -class HTTPError(ClientException): - """ - An HTTP error occurred - """ - pass - - -class URLRequired(ClientException): - """ - A valid URL is required to make a request - """ - pass - - -class TooManyRedirects(ClientException): - """ - Too many redirects - """ - pass - - -class Timeout(ClientException): - """ - The request timed out - """ - pass - - ## # 400 Errors ## @@ -401,7 +355,7 @@ _code_map = dict((c.http_status, c) for c in [ def from_response(response, body): """ Return an instance of an ClientException or subclass - based on a Python Requests response. + based on an httplib2 response. Usage:: diff --git a/hplefthandclient/http.py b/hplefthandclient/http.py index 4116b95..cbde2cf 100644 --- a/hplefthandclient/http.py +++ b/hplefthandclient/http.py @@ -27,9 +27,9 @@ HPLeftHand HTTP Client """ import logging -import requests +import httplib2 import time -# requests.packages.urllib3.disable_warnings() +import pprint try: import json @@ -39,7 +39,7 @@ except ImportError: from hplefthandclient import exceptions -class HTTPJSONRESTClient(object): +class HTTPJSONRESTClient(httplib2.Http): """ An HTTP REST Client that sends and recieves JSON data as the body of the HTTP request. @@ -47,8 +47,8 @@ class HTTPJSONRESTClient(object): :param api_url: The url to the LH OS REST service ie. https://:/lhos :type api_url: str - :param secure: Validate SSL cert? Default will not validate - :type secure: bool + :param insecure: Use https? requires a local certificate + :type insecure: bool """ @@ -59,7 +59,9 @@ class HTTPJSONRESTClient(object): http_log_debug = False _logger = logging.getLogger(__name__) - def __init__(self, api_url, secure=False, http_log_debug=False): + def __init__(self, api_url, insecure=False, http_log_debug=False): + super(HTTPJSONRESTClient, + self).__init__(disable_ssl_certificate_validation=True) self.session_key = None #should be http:///lhos @@ -67,7 +69,10 @@ class HTTPJSONRESTClient(object): self.set_debug_flag(http_log_debug) self.times = [] # [("item", starttime, endtime), ...] - self.secure = secure + + # httplib2 overrides + self.force_exception_to_status_code = True + #self.disable_ssl_certificate_validation = insecure def set_url(self, api_url): #should be http:///lhos @@ -163,8 +168,7 @@ class HTTPJSONRESTClient(object): def _http_log_resp(self, resp, body): if not self.http_log_debug: return - HTTPJSONRESTClient._logger.debug("RESP:%s\n", - str(resp).replace('\',', '\'\n')) + HTTPJSONRESTClient._logger.debug("RESP:%s\n", pprint.pformat(resp)) HTTPJSONRESTClient._logger.debug("RESP BODY:%s\n", body) def request(self, *args, **kwargs): @@ -182,51 +186,11 @@ class HTTPJSONRESTClient(object): if 'body' in kwargs: kwargs['headers']['Content-Type'] = 'application/json' kwargs['body'] = json.dumps(kwargs['body']) - payload = kwargs['body'] - else: - payload = None - - # args[0] contains the URL, args[1] contains the HTTP verb/method - http_url = args[0] - http_method = args[1] self._http_log_req(args, kwargs) - try: - r = requests.request(http_method, http_url, data=payload, - headers=kwargs['headers'], verify=self.secure) - except requests.exceptions.SSLError as err: - HTTPJSONRESTClient._logger.error("SSL certificate verification" - " failed: (%s). You must have a" - " valid SSL certificate or" - " disable SSL verification.", err) - raise exceptions.SSLCertFailed("SSL Certificate Verification" - " Failed") - except requests.exceptions.RequestException as err: - raise exceptions.RequestException("Request Exception: %s" % err) - except requests.exceptions.ConnectionError as err: - raise exceptions.ConnectionError("Connection Error: %s" % err) - except requests.exceptions.HTTPError as err: - raise exceptions.HTTPError("HTTP Error: %s" % err) - except requests.exceptions.URLRequired as err: - raise exceptions.URLRequired("URL Required: %s" % err) - except requests.exceptions.TooManyRedirects as err: - raise exceptions.TooManyRedirects("Too Many Redirects: %s" % err) - except requests.exceptions.Timeout as err: - raise exceptions.Timeout("Timeout: %s" % err) - - resp = r.headers - body = r.text + resp, body = super(HTTPJSONRESTClient, self).request(*args, **kwargs) if isinstance(body, bytes): body = body.decode('utf-8') - - # resp['status'], status['content-location'], and resp.status need to - # be manually set as Python Requests doesnt provide them automatically - resp['status'] = str(r.status_code) - resp.status = r.status_code - if 'location' not in resp: - resp['content-location'] = r.url - - r.close() self._http_log_resp(resp, body) # Try and conver the body response to an object diff --git a/requirements.txt b/requirements.txt index 2f7ef8f..97c6c28 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -requests>=2.5.2 +httplib2>=0.6.0 diff --git a/setup.py b/setup.py index 365cec8..6c19801 100644 --- a/setup.py +++ b/setup.py @@ -15,8 +15,8 @@ setup( author_email="kurt.f.martin@hp.com", maintainer="Kurt Martin", keywords=["hp", "lefthand", "storevirtual", "rest"], - requires=['requests(>=2.5.2)'], - install_requires=['requests >= 2.5.2'], + requires=['httplib2(>=0.6.0)'], + install_requires=['httplib2 >= 0.6.0'], tests_require=["nose", "nose-testconfig", "flask", "Werkzeug", "flake8"], license="Apache License, Version 2.0", packages=find_packages(),