def wrapped(self, method, url, body, headers): for _ in xrange(MAX_REDIRECTS): try: return func(self, method, url, body, headers) except exception.RedirectException as redirect: if redirect.url is None: raise exception.InvalidRedirect() url = redirect.url raise exception.MaxRedirectsExceeded(redirects=MAX_REDIRECTS)
def authenticate(self): """Authenticate with the Keystone service. There are a few scenarios to consider here: 1. Which version of Keystone are we using? v1 which uses headers to pass the credentials, or v2 which uses a JSON encoded request body? 2. Keystone may respond back with a redirection using a 305 status code. 3. We may attempt a v1 auth when v2 is what's called for. In this case, we rewrite the url to contain /v2.0/ and retry using the v2 protocol. """ def _authenticate(auth_url): # If OS_AUTH_URL is missing a trailing slash add one if not auth_url.endswith('/'): auth_url += '/' token_url = urlparse.urljoin(auth_url, "tokens") # 1. Check Keystone version is_v2 = auth_url.rstrip('/').endswith('v2.0') if is_v2: self._v2_auth(token_url) else: self._v1_auth(token_url) self.check_auth_params() auth_url = self.creds['auth_url'] for _ in range(self.MAX_REDIRECTS): try: _authenticate(auth_url) except exception.AuthorizationRedirect as e: # 2. Keystone may redirect us auth_url = e.url except exception.AuthorizationFailure: # 3. In some configurations nova makes redirection to # v2.0 keystone endpoint. Also, new location does not # contain real endpoint, only hostname and port. if 'v2.0' not in auth_url: auth_url = urlparse.urljoin(auth_url, 'v2.0/') else: # If we sucessfully auth'd, then memorize the correct auth_url # for future use. self.creds['auth_url'] = auth_url break else: # Guard against a redirection loop raise exception.MaxRedirectsExceeded(redirects=self.MAX_REDIRECTS)