Add option for retry number of connection attempts
This patch adds a new option (-r | --retries) to specify how many times the client should attempt to connect to the Neutron server when using idempotent methods (GET, PUT and DELETE). The patch also provides more user-friendly message when it's impossible to connect to Neutron server from CLI and ensures that connection-related exceptions are raised to the caller by default when neutronclient is used as a library. DocImpact Closes-Bug: #1312225 Change-Id: Id74d7cf9a0e8c5d2cd3ee4851c883d5286bea19d
This commit is contained in:
parent
b4f4544eaa
commit
65883ba4eb
neutronclient
@ -64,7 +64,9 @@ class ClientManager(object):
|
|||||||
ca_cert=None,
|
ca_cert=None,
|
||||||
log_credentials=False,
|
log_credentials=False,
|
||||||
service_type=None,
|
service_type=None,
|
||||||
timeout=None
|
timeout=None,
|
||||||
|
retries=0,
|
||||||
|
raise_errors=True
|
||||||
):
|
):
|
||||||
self._token = token
|
self._token = token
|
||||||
self._url = url
|
self._url = url
|
||||||
@ -84,7 +86,8 @@ class ClientManager(object):
|
|||||||
self._ca_cert = ca_cert
|
self._ca_cert = ca_cert
|
||||||
self._log_credentials = log_credentials
|
self._log_credentials = log_credentials
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
return
|
self._retries = retries
|
||||||
|
self._raise_errors = raise_errors
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
if not self._url:
|
if not self._url:
|
||||||
|
@ -46,7 +46,9 @@ def make_client(instance):
|
|||||||
token=instance._token,
|
token=instance._token,
|
||||||
auth_strategy=instance._auth_strategy,
|
auth_strategy=instance._auth_strategy,
|
||||||
insecure=instance._insecure,
|
insecure=instance._insecure,
|
||||||
ca_cert=instance._ca_cert)
|
ca_cert=instance._ca_cert,
|
||||||
|
retries=instance._retries,
|
||||||
|
raise_errors=instance._raise_errors)
|
||||||
return client
|
return client
|
||||||
else:
|
else:
|
||||||
raise exceptions.UnsupportedVersion(_("API version %s is not "
|
raise exceptions.UnsupportedVersion(_("API version %s is not "
|
||||||
|
@ -97,6 +97,17 @@ def env(*_vars, **kwargs):
|
|||||||
return kwargs.get('default', '')
|
return kwargs.get('default', '')
|
||||||
|
|
||||||
|
|
||||||
|
def check_non_negative_int(value):
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
raise argparse.ArgumentTypeError(_("invalid int value: %r") % value)
|
||||||
|
if value < 0:
|
||||||
|
raise argparse.ArgumentTypeError(_("input value %d is negative") %
|
||||||
|
value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
COMMAND_V2 = {
|
COMMAND_V2 = {
|
||||||
'net-list': network.ListNetwork,
|
'net-list': network.ListNetwork,
|
||||||
'net-external-list': network.ListExternalNetwork,
|
'net-external-list': network.ListExternalNetwork,
|
||||||
@ -368,6 +379,13 @@ class NeutronShell(app.App):
|
|||||||
nargs=0,
|
nargs=0,
|
||||||
default=self, # tricky
|
default=self, # tricky
|
||||||
help=_("Show this help message and exit."))
|
help=_("Show this help message and exit."))
|
||||||
|
parser.add_argument(
|
||||||
|
'-r', '--retries',
|
||||||
|
metavar="NUM",
|
||||||
|
type=check_non_negative_int,
|
||||||
|
default=0,
|
||||||
|
help=_("How many times the request to the Neutron server should "
|
||||||
|
"be retried if it fails."))
|
||||||
# Global arguments
|
# Global arguments
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--os-auth-strategy', metavar='<auth-strategy>',
|
'--os-auth-strategy', metavar='<auth-strategy>',
|
||||||
@ -650,6 +668,8 @@ class NeutronShell(app.App):
|
|||||||
insecure=self.options.insecure,
|
insecure=self.options.insecure,
|
||||||
ca_cert=self.options.os_cacert,
|
ca_cert=self.options.os_cacert,
|
||||||
timeout=self.options.timeout,
|
timeout=self.options.timeout,
|
||||||
|
retries=self.options.retries,
|
||||||
|
raise_errors=False,
|
||||||
log_credentials=True)
|
log_credentials=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -128,8 +128,8 @@ class ShellTest(testtools.TestCase):
|
|||||||
username='test', user_id='',
|
username='test', user_id='',
|
||||||
password='test', region_name='', api_version={'network': '2.0'},
|
password='test', region_name='', api_version={'network': '2.0'},
|
||||||
auth_strategy='keystone', service_type='network',
|
auth_strategy='keystone', service_type='network',
|
||||||
endpoint_type='publicURL', insecure=False, ca_cert=None,
|
endpoint_type='publicURL', insecure=False, ca_cert=None, retries=0,
|
||||||
log_credentials=True, timeout=None)
|
raise_errors=False, log_credentials=True, timeout=None)
|
||||||
neutron_shell.run_subcommand(['quota-list'])
|
neutron_shell.run_subcommand(['quota-list'])
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
cmdline = ('--os-username test '
|
cmdline = ('--os-username test '
|
||||||
|
@ -62,6 +62,8 @@ class TestSSL(testtools.TestCase):
|
|||||||
url=mox.IgnoreArg(),
|
url=mox.IgnoreArg(),
|
||||||
username=mox.IgnoreArg(),
|
username=mox.IgnoreArg(),
|
||||||
user_id=mox.IgnoreArg(),
|
user_id=mox.IgnoreArg(),
|
||||||
|
retries=mox.IgnoreArg(),
|
||||||
|
raise_errors=mox.IgnoreArg(),
|
||||||
log_credentials=mox.IgnoreArg(),
|
log_credentials=mox.IgnoreArg(),
|
||||||
timeout=mox.IgnoreArg(),
|
timeout=mox.IgnoreArg(),
|
||||||
)
|
)
|
||||||
@ -94,6 +96,8 @@ class TestSSL(testtools.TestCase):
|
|||||||
url=mox.IgnoreArg(),
|
url=mox.IgnoreArg(),
|
||||||
username=mox.IgnoreArg(),
|
username=mox.IgnoreArg(),
|
||||||
user_id=mox.IgnoreArg(),
|
user_id=mox.IgnoreArg(),
|
||||||
|
retries=mox.IgnoreArg(),
|
||||||
|
raise_errors=mox.IgnoreArg(),
|
||||||
log_credentials=mox.IgnoreArg(),
|
log_credentials=mox.IgnoreArg(),
|
||||||
timeout=mox.IgnoreArg(),
|
timeout=mox.IgnoreArg(),
|
||||||
)
|
)
|
||||||
@ -117,6 +121,8 @@ class TestSSL(testtools.TestCase):
|
|||||||
tenant_name=mox.IgnoreArg(),
|
tenant_name=mox.IgnoreArg(),
|
||||||
token=mox.IgnoreArg(),
|
token=mox.IgnoreArg(),
|
||||||
username=mox.IgnoreArg(),
|
username=mox.IgnoreArg(),
|
||||||
|
retries=mox.IgnoreArg(),
|
||||||
|
raise_errors=mox.IgnoreArg(),
|
||||||
)
|
)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
@ -129,6 +129,12 @@ class Client(object):
|
|||||||
http requests. (optional)
|
http requests. (optional)
|
||||||
:param bool insecure: SSL certificate validation. (optional)
|
:param bool insecure: SSL certificate validation. (optional)
|
||||||
:param string ca_cert: SSL CA bundle file to use. (optional)
|
:param string ca_cert: SSL CA bundle file to use. (optional)
|
||||||
|
:param integer retries: How many times idempotent (GET, PUT, DELETE)
|
||||||
|
requests to Neutron server should be retried if
|
||||||
|
they fail (default: 0).
|
||||||
|
:param bool raise_errors: If True then exceptions caused by connection
|
||||||
|
failure are propagated to the caller.
|
||||||
|
(default: True)
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
@ -1194,7 +1200,8 @@ class Client(object):
|
|||||||
self.version = '2.0'
|
self.version = '2.0'
|
||||||
self.format = 'json'
|
self.format = 'json'
|
||||||
self.action_prefix = "/v%s" % (self.version)
|
self.action_prefix = "/v%s" % (self.version)
|
||||||
self.retries = 0
|
self.retries = kwargs.get('retries', 0)
|
||||||
|
self.raise_errors = kwargs.get('raise_errors', True)
|
||||||
self.retry_interval = 1
|
self.retry_interval = 1
|
||||||
|
|
||||||
def _handle_fault_response(self, status_code, response_body):
|
def _handle_fault_response(self, status_code, response_body):
|
||||||
@ -1303,8 +1310,16 @@ class Client(object):
|
|||||||
if i < self.retries:
|
if i < self.retries:
|
||||||
_logger.debug('Retrying connection to Neutron service')
|
_logger.debug('Retrying connection to Neutron service')
|
||||||
time.sleep(self.retry_interval)
|
time.sleep(self.retry_interval)
|
||||||
|
elif self.raise_errors:
|
||||||
|
raise
|
||||||
|
|
||||||
raise exceptions.ConnectionFailed(reason=_("Maximum attempts reached"))
|
if self.retries:
|
||||||
|
msg = (_("Failed to connect to Neutron server after %d attempts")
|
||||||
|
% max_attempts)
|
||||||
|
else:
|
||||||
|
msg = _("Failed to connect Neutron server")
|
||||||
|
|
||||||
|
raise exceptions.ConnectionFailed(reason=msg)
|
||||||
|
|
||||||
def delete(self, action, body=None, headers=None, params=None):
|
def delete(self, action, body=None, headers=None, params=None):
|
||||||
return self.retry_request("DELETE", action, body=body,
|
return self.retry_request("DELETE", action, body=body,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user