
committed by
Gerrit Code Review

parent
3b1eda3b3b
commit
dcbebd7b78
@@ -11,10 +11,6 @@ import httplib2
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import urlparse
|
import urlparse
|
||||||
try:
|
|
||||||
from eventlet import sleep
|
|
||||||
except ImportError:
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import json
|
import json
|
||||||
@@ -46,7 +42,7 @@ class HTTPClient(httplib2.Http):
|
|||||||
timeout=None, tenant_id=None, proxy_tenant_id=None,
|
timeout=None, tenant_id=None, proxy_tenant_id=None,
|
||||||
proxy_token=None, region_name=None,
|
proxy_token=None, region_name=None,
|
||||||
endpoint_type='publicURL', service_type=None,
|
endpoint_type='publicURL', service_type=None,
|
||||||
service_name=None, volume_service_name=None, retries=0):
|
service_name=None, volume_service_name=None):
|
||||||
super(HTTPClient, self).__init__(timeout=timeout)
|
super(HTTPClient, self).__init__(timeout=timeout)
|
||||||
self.user = user
|
self.user = user
|
||||||
self.password = password
|
self.password = password
|
||||||
@@ -59,7 +55,6 @@ class HTTPClient(httplib2.Http):
|
|||||||
self.service_type = service_type
|
self.service_type = service_type
|
||||||
self.service_name = service_name
|
self.service_name = service_name
|
||||||
self.volume_service_name = volume_service_name
|
self.volume_service_name = volume_service_name
|
||||||
self.retries = retries
|
|
||||||
|
|
||||||
self.management_url = None
|
self.management_url = None
|
||||||
self.auth_token = None
|
self.auth_token = None
|
||||||
@@ -116,40 +111,28 @@ class HTTPClient(httplib2.Http):
|
|||||||
return resp, body
|
return resp, body
|
||||||
|
|
||||||
def _cs_request(self, url, method, **kwargs):
|
def _cs_request(self, url, method, **kwargs):
|
||||||
attempts = 0
|
if not self.management_url:
|
||||||
backoff = 1
|
|
||||||
while attempts <= self.retries:
|
|
||||||
attempts += 1
|
|
||||||
if not self.management_url or not self.auth_token:
|
|
||||||
self.authenticate()
|
self.authenticate()
|
||||||
|
|
||||||
|
# Perform the request once. If we get a 401 back then it
|
||||||
|
# might be because the auth token expired, so try to
|
||||||
|
# re-authenticate and try again. If it still fails, bail.
|
||||||
|
try:
|
||||||
kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token
|
kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token
|
||||||
if self.projectid:
|
if self.projectid:
|
||||||
kwargs['headers']['X-Auth-Project-Id'] = self.projectid
|
kwargs['headers']['X-Auth-Project-Id'] = self.projectid
|
||||||
try:
|
|
||||||
|
resp, body = self.request(self.management_url + url, method,
|
||||||
|
**kwargs)
|
||||||
|
return resp, body
|
||||||
|
except exceptions.Unauthorized, ex:
|
||||||
|
try:
|
||||||
|
self.authenticate()
|
||||||
resp, body = self.request(self.management_url + url, method,
|
resp, body = self.request(self.management_url + url, method,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
return resp, body
|
return resp, body
|
||||||
except exceptions.BadRequest as e:
|
|
||||||
# Socket errors show up here (400) when
|
|
||||||
# force_exception_to_status_code = True
|
|
||||||
if e.message != 'n/a':
|
|
||||||
raise
|
|
||||||
except exceptions.Unauthorized:
|
except exceptions.Unauthorized:
|
||||||
if attempts > 1:
|
raise ex
|
||||||
raise
|
|
||||||
_logger.debug("Unauthorized, reauthenticating.")
|
|
||||||
self.management_url = self.auth_token = None
|
|
||||||
except exceptions.ClientException as e:
|
|
||||||
if 500 <= e.code <= 599:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
if attempts > self.retries:
|
|
||||||
raise
|
|
||||||
_logger.debug("Failed attempt(%s), retrying in %s seconds" %
|
|
||||||
(attempts, backoff))
|
|
||||||
sleep(backoff)
|
|
||||||
backoff *= 2
|
|
||||||
|
|
||||||
def get(self, url, **kwargs):
|
def get(self, url, **kwargs):
|
||||||
return self._cs_request(url, 'GET', **kwargs)
|
return self._cs_request(url, 'GET', **kwargs)
|
||||||
|
@@ -169,11 +169,6 @@ class OpenStackCinderShell(object):
|
|||||||
action='store_true',
|
action='store_true',
|
||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument('--retries',
|
|
||||||
metavar='<retries>',
|
|
||||||
default=0,
|
|
||||||
help='Number of retries.')
|
|
||||||
|
|
||||||
# FIXME(dtroyer): The args below are here for diablo compatibility,
|
# FIXME(dtroyer): The args below are here for diablo compatibility,
|
||||||
# remove them in folsum cycle
|
# remove them in folsum cycle
|
||||||
|
|
||||||
@@ -413,8 +408,7 @@ class OpenStackCinderShell(object):
|
|||||||
extensions=self.extensions,
|
extensions=self.extensions,
|
||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
service_name=service_name,
|
service_name=service_name,
|
||||||
volume_service_name=volume_service_name,
|
volume_service_name=volume_service_name)
|
||||||
retries=options.retries)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not utils.isunauthenticated(args.func):
|
if not utils.isunauthenticated(args.func):
|
||||||
|
@@ -27,7 +27,7 @@ class Client(object):
|
|||||||
proxy_tenant_id=None, proxy_token=None, region_name=None,
|
proxy_tenant_id=None, proxy_token=None, region_name=None,
|
||||||
endpoint_type='publicURL', extensions=None,
|
endpoint_type='publicURL', extensions=None,
|
||||||
service_type='volume', service_name=None,
|
service_type='volume', service_name=None,
|
||||||
volume_service_name=None, retries=None):
|
volume_service_name=None):
|
||||||
# FIXME(comstud): Rename the api_key argument above when we
|
# FIXME(comstud): Rename the api_key argument above when we
|
||||||
# know it's not being used as keyword argument
|
# know it's not being used as keyword argument
|
||||||
password = api_key
|
password = api_key
|
||||||
@@ -61,8 +61,7 @@ class Client(object):
|
|||||||
endpoint_type=endpoint_type,
|
endpoint_type=endpoint_type,
|
||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
service_name=service_name,
|
service_name=service_name,
|
||||||
volume_service_name=volume_service_name,
|
volume_service_name=volume_service_name)
|
||||||
retries=retries)
|
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
"""
|
"""
|
||||||
|
@@ -13,7 +13,7 @@ mock_request = mock.Mock(return_value=(fake_response, fake_body))
|
|||||||
|
|
||||||
def get_client():
|
def get_client():
|
||||||
cl = client.HTTPClient("username", "password",
|
cl = client.HTTPClient("username", "password",
|
||||||
"project_id", "auth_test", retries=1)
|
"project_id", "auth_test")
|
||||||
return cl
|
return cl
|
||||||
|
|
||||||
|
|
||||||
@@ -44,66 +44,6 @@ class ClientTest(utils.TestCase):
|
|||||||
|
|
||||||
test_get_call()
|
test_get_call()
|
||||||
|
|
||||||
def test_get_retry_500(self):
|
|
||||||
cl = get_authed_client()
|
|
||||||
|
|
||||||
bad_response = httplib2.Response({"status": 500})
|
|
||||||
bad_body = '{"error": {"message": "FAILED!", "details": "DETAILS!"}}'
|
|
||||||
bad_request = mock.Mock(return_value=(bad_response, bad_body))
|
|
||||||
self.requests = [bad_request, mock_request]
|
|
||||||
|
|
||||||
def request(*args, **kwargs):
|
|
||||||
next_request = self.requests.pop(0)
|
|
||||||
return next_request(*args, **kwargs)
|
|
||||||
|
|
||||||
@mock.patch.object(httplib2.Http, "request", request)
|
|
||||||
@mock.patch('time.time', mock.Mock(return_value=1234))
|
|
||||||
def test_get_call():
|
|
||||||
resp, body = cl.get("/hi")
|
|
||||||
|
|
||||||
test_get_call()
|
|
||||||
self.assertEqual(self.requests, [])
|
|
||||||
|
|
||||||
def test_get_no_retry_400(self):
|
|
||||||
cl = get_authed_client()
|
|
||||||
|
|
||||||
bad_response = httplib2.Response({"status": 400})
|
|
||||||
bad_body = '{"error": {"message": "Bad!", "details": "Terrible!"}}'
|
|
||||||
bad_request = mock.Mock(return_value=(bad_response, bad_body))
|
|
||||||
self.requests = [bad_request, mock_request]
|
|
||||||
|
|
||||||
def request(*args, **kwargs):
|
|
||||||
next_request = self.requests.pop(0)
|
|
||||||
return next_request(*args, **kwargs)
|
|
||||||
|
|
||||||
@mock.patch.object(httplib2.Http, "request", request)
|
|
||||||
@mock.patch('time.time', mock.Mock(return_value=1234))
|
|
||||||
def test_get_call():
|
|
||||||
resp, body = cl.get("/hi")
|
|
||||||
|
|
||||||
self.assertRaises(exceptions.BadRequest, test_get_call)
|
|
||||||
self.assertEqual(self.requests, [mock_request])
|
|
||||||
|
|
||||||
def test_get_retry_400_socket(self):
|
|
||||||
cl = get_authed_client()
|
|
||||||
|
|
||||||
bad_response = httplib2.Response({"status": 400})
|
|
||||||
bad_body = '{"error": {"message": "n/a", "details": "n/a"}}'
|
|
||||||
bad_request = mock.Mock(return_value=(bad_response, bad_body))
|
|
||||||
self.requests = [bad_request, mock_request]
|
|
||||||
|
|
||||||
def request(*args, **kwargs):
|
|
||||||
next_request = self.requests.pop(0)
|
|
||||||
return next_request(*args, **kwargs)
|
|
||||||
|
|
||||||
@mock.patch.object(httplib2.Http, "request", request)
|
|
||||||
@mock.patch('time.time', mock.Mock(return_value=1234))
|
|
||||||
def test_get_call():
|
|
||||||
resp, body = cl.get("/hi")
|
|
||||||
|
|
||||||
test_get_call()
|
|
||||||
self.assertEqual(self.requests, [])
|
|
||||||
|
|
||||||
def test_post(self):
|
def test_post(self):
|
||||||
cl = get_authed_client()
|
cl = get_authed_client()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user