Merge "Set timeout value in urllib3.poolmanager.PoolManager"
diff --git a/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml b/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
new file mode 100644
index 0000000..a360f8e
--- /dev/null
+++ b/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - RestClient now supports setting timeout in urllib3.poolmanager.
+    Clients will use CONF.service_clients.http_timeout for timeout
+    value to wait for http request to response.
+  - KeystoneAuthProvider will accept http_timeout and will use it in
+    get_credentials.
diff --git a/tempest/config.py b/tempest/config.py
index 0c2b913..6bae021 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -173,6 +173,16 @@
                      "a domain scoped token to use admin APIs")
 ]
 
+service_clients_group = cfg.OptGroup(name='service-clients',
+                                     title="Service Clients Options")
+
+ServiceClientsGroup = [
+    cfg.IntOpt('http_timeout',
+               default=60,
+               help='Timeout in seconds to wait for the http request to '
+                    'return'),
+]
+
 identity_feature_group = cfg.OptGroup(name='identity-feature-enabled',
                                       title='Enabled Identity Features')
 
@@ -1119,6 +1129,7 @@
     (compute_group, ComputeGroup),
     (compute_features_group, ComputeFeaturesGroup),
     (identity_group, IdentityGroup),
+    (service_clients_group, ServiceClientsGroup),
     (identity_feature_group, IdentityFeatureGroup),
     (image_group, ImageGroup),
     (image_feature_group, ImageFeaturesGroup),
@@ -1184,6 +1195,7 @@
         self.compute = _CONF.compute
         self.compute_feature_enabled = _CONF['compute-feature-enabled']
         self.identity = _CONF.identity
+        self.service_clients = _CONF['service-clients']
         self.identity_feature_enabled = _CONF['identity-feature-enabled']
         self.image = _CONF.image
         self.image_feature_enabled = _CONF['image-feature-enabled']
@@ -1372,6 +1384,7 @@
         * `disable_ssl_certificate_validation`
         * `ca_certs`
         * `trace_requests`
+        * `http_timeout`
 
     The dict returned by this does not fit a few service clients:
 
@@ -1393,7 +1406,8 @@
         'disable_ssl_certificate_validation':
             CONF.identity.disable_ssl_certificate_validation,
         'ca_certs': CONF.identity.ca_certificates_file,
-        'trace_requests': CONF.debug.trace_requests
+        'trace_requests': CONF.debug.trace_requests,
+        'http_timeout': CONF.service_clients.http_timeout
     }
 
     if service_client_name is None:
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 54a7002..1857a43 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -260,11 +260,13 @@
 
     def __init__(self, credentials, auth_url,
                  disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None, scope='project'):
+                 ca_certs=None, trace_requests=None, scope='project',
+                 http_timeout=None):
         super(KeystoneAuthProvider, self).__init__(credentials, scope)
         self.dscv = disable_ssl_certificate_validation
         self.ca_certs = ca_certs
         self.trace_requests = trace_requests
+        self.http_timeout = http_timeout
         self.auth_url = auth_url
         self.auth_client = self._auth_client(auth_url)
 
@@ -342,7 +344,8 @@
     def _auth_client(self, auth_url):
         return json_v2id.TokenClient(
             auth_url, disable_ssl_certificate_validation=self.dscv,
-            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
+            ca_certs=self.ca_certs, trace_requests=self.trace_requests,
+            http_timeout=self.http_timeout)
 
     def _auth_params(self):
         """Auth parameters to be passed to the token request
@@ -429,7 +432,8 @@
     def _auth_client(self, auth_url):
         return json_v3id.V3TokenClient(
             auth_url, disable_ssl_certificate_validation=self.dscv,
-            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
+            ca_certs=self.ca_certs, trace_requests=self.trace_requests,
+            http_timeout=self.http_timeout)
 
     def _auth_params(self):
         """Auth parameters to be passed to the token request
@@ -595,7 +599,7 @@
 
 def get_credentials(auth_url, fill_in=True, identity_version='v2',
                     disable_ssl_certificate_validation=None, ca_certs=None,
-                    trace_requests=None, **kwargs):
+                    trace_requests=None, http_timeout=None, **kwargs):
     """Builds a credentials object based on the configured auth_version
 
     :param auth_url (string): Full URI of the OpenStack Identity API(Keystone)
@@ -611,6 +615,8 @@
     :param ca_certs: CA certificate bundle for validation of certificates
            in SSL API requests to the auth system
     :param trace_requests: trace in log API requests to the auth system
+    :param http_timeout: timeout in seconds to wait for the http request to
+           return
     :param kwargs (dict): Dict of credential key/value pairs
 
     Examples:
@@ -634,7 +640,8 @@
         dscv = disable_ssl_certificate_validation
         auth_provider = auth_provider_class(
             creds, auth_url, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests,
+            http_timeout=http_timeout)
         creds = auth_provider.fill_credentials()
     return creds
 
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index dffc5f9..86ea26e 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -18,7 +18,7 @@
 
 class ClosingHttp(urllib3.poolmanager.PoolManager):
     def __init__(self, disable_ssl_certificate_validation=False,
-                 ca_certs=None):
+                 ca_certs=None, timeout=None):
         kwargs = {}
 
         if disable_ssl_certificate_validation:
@@ -29,6 +29,9 @@
             kwargs['cert_reqs'] = 'CERT_REQUIRED'
             kwargs['ca_certs'] = ca_certs
 
+        if timeout:
+            kwargs['timeout'] = timeout
+
         super(ClosingHttp, self).__init__(**kwargs)
 
     def request(self, url, method, *args, **kwargs):
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 1b0f53a..7e1a442 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -66,6 +66,8 @@
                          TLS server cert
     :param str trace_request: Regex to use for specifying logging the entirety
                               of the request and response payload
+    :param str http_timeout: Timeout in seconds to wait for the http request to
+                             return
     """
     TYPE = "json"
 
@@ -78,7 +80,7 @@
                  endpoint_type='publicURL',
                  build_interval=1, build_timeout=60,
                  disable_ssl_certificate_validation=False, ca_certs=None,
-                 trace_requests='', name=None):
+                 trace_requests='', name=None, http_timeout=None):
         self.auth_provider = auth_provider
         self.service = service
         self.region = region
@@ -99,7 +101,8 @@
                                        'vary', 'www-authenticate'))
         dscv = disable_ssl_certificate_validation
         self.http_obj = http.ClosingHttp(
-            disable_ssl_certificate_validation=dscv, ca_certs=ca_certs)
+            disable_ssl_certificate_validation=dscv, ca_certs=ca_certs,
+            timeout=http_timeout)
 
     def _get_type(self):
         return self.TYPE
diff --git a/tempest/lib/services/identity/v2/token_client.py b/tempest/lib/services/identity/v2/token_client.py
index 5716027..a5d7c86 100644
--- a/tempest/lib/services/identity/v2/token_client.py
+++ b/tempest/lib/services/identity/v2/token_client.py
@@ -22,11 +22,11 @@
 class TokenClient(rest_client.RestClient):
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None):
+                 ca_certs=None, trace_requests=None, **kwargs):
         dscv = disable_ssl_certificate_validation
         super(TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
 
         if auth_url is None:
             raise exceptions.IdentityError("Couldn't determine auth_url")
diff --git a/tempest/lib/services/identity/v3/token_client.py b/tempest/lib/services/identity/v3/token_client.py
index 964d43f..c1f7e7b 100644
--- a/tempest/lib/services/identity/v3/token_client.py
+++ b/tempest/lib/services/identity/v3/token_client.py
@@ -22,11 +22,11 @@
 class V3TokenClient(rest_client.RestClient):
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None):
+                 ca_certs=None, trace_requests=None, **kwargs):
         dscv = disable_ssl_certificate_validation
         super(V3TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
 
         if auth_url is None:
             raise exceptions.IdentityError("Couldn't determine auth_url")