Ejemplo n.º 1
0
    def _query(self, location, verb, depth=0):
        if depth > MAX_REDIRECTS:
            reason = (_("The HTTP URL exceeded %s maximum "
                        "redirects.") % MAX_REDIRECTS)
            LOG.debug(reason)
            raise exception.MaxRedirectsExceeded(redirects=MAX_REDIRECTS)
        loc = location.store_location
        conn_class = self._get_conn_class(loc)
        conn = conn_class(loc.netloc)
        conn.request(verb, loc.path, "", {})
        resp = conn.getresponse()

        # Check for bad status codes
        if resp.status >= 400:
            reason = _("HTTP URL returned a %s status code.") % resp.status
            LOG.debug(reason)
            raise exception.BadStoreUri(loc.path, reason)

        location_header = resp.getheader("location")
        if location_header:
            if resp.status not in (301, 302):
                reason = (_("The HTTP URL attempted to redirect with an "
                            "invalid %s status code.") % resp.status)
                LOG.debug(reason)
                raise exception.BadStoreUri(loc.path, reason)
            location_class = glance.store.location.Location
            new_loc = location_class(location.store_name,
                                     location.store_location.__class__,
                                     uri=location_header,
                                     image_id=location.image_id,
                                     store_specs=location.store_specs)
            return self._query(new_loc, verb, depth + 1)
        content_length = int(resp.getheader('content-length', 0))
        return (conn, resp, content_length)
Ejemplo n.º 2
0
    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 check_auth_params():
            # Ensure that supplied credential parameters are as required
            for required in ('username', 'password', 'auth_url'):
                if required not in self.creds:
                    raise exception.MissingCredentialError(required=required)
            # For v2.0 also check tenant is present
            if self.creds['auth_url'].rstrip('/').endswith('v2.0'):
                if 'tenant' not in self.creds:
                    raise exception.MissingCredentialError(required='tenant')

        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)

        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)
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
    def _query(self, location, method, depth=0):
        if depth > MAX_REDIRECTS:
            msg = ("The HTTP URL exceeded %(max_redirects)s maximum "
                   "redirects.", {
                       'max_redirects': MAX_REDIRECTS
                   })
            LOG.debug(msg)
            raise exception.MaxRedirectsExceeded(redirects=MAX_REDIRECTS)
        loc = location.store_location
        cookie = self._build_vim_cookie_header(
            self._session.vim.client.options.transport.cookiejar)
        headers = {'Cookie': cookie}
        try:
            conn = self._get_http_conn(method, loc, headers)
            resp = conn.getresponse()
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE('Failed to access image %(image)s content.'),
                              {'image': location.image_id})
        if resp.status >= 400:
            if resp.status == httplib.UNAUTHORIZED:
                self._create_session()
                raise exception.NotAuthenticated()
            if resp.status == httplib.NOT_FOUND:
                msg = 'VMware datastore could not find image at URI.'
                LOG.debug(msg)
                raise exception.NotFound(msg)
            reason = (_('HTTP request returned a %(status)s status code.') % {
                'status': resp.status
            })
            LOG.info(reason)
            raise exception.BadStoreUri(message=reason)
        location_header = resp.getheader('location')
        if location_header:
            if resp.status not in (301, 302):
                reason = (_("The HTTP URL %(path)s attempted to redirect "
                            "with an invalid %(status)s status code.") % {
                                'path': loc.path,
                                'status': resp.status
                            })
                LOG.info(reason)
                raise exception.BadStoreUri(message=reason)
            location_class = glance.store.location.Location
            new_loc = location_class(location.store_name,
                                     location.store_location.__class__,
                                     uri=location_header,
                                     image_id=location.image_id,
                                     store_specs=location.store_specs)
            return self._query(new_loc, method, depth + 1)
        content_length = int(resp.getheader('content-length', 0))

        return (conn, resp, content_length)
Ejemplo n.º 5
0
    def _query(self, location, method, headers, depth=0):
        if depth > MAX_REDIRECTS:
            msg = (_("The HTTP URL exceeded %(max_redirects)s maximum "
                     "redirects.") % {
                         'max_redirects': MAX_REDIRECTS
                     })
            LOG.debug(msg)
            raise exception.MaxRedirectsExceeded(redirects=MAX_REDIRECTS)
        loc = location.store_location
        conn = self._get_http_conn(method, loc, headers)
        resp = conn.getresponse()
        if resp.status >= 400:
            if resp.status == httplib.NOT_FOUND:
                msg = _('VMware datastore could not find image at URI.')
                LOG.debug(msg)
                raise exception.NotFound(msg)
            msg = (_('HTTP URL %(url)s returned a %(status)s status code.') % {
                'url': loc.get_uri(),
                'status': resp.status
            })
            LOG.debug(msg)
            raise exception.BadStoreUri(msg)
        location_header = resp.getheader('location')
        if location_header:
            if resp.status not in (301, 302):
                msg = (_("The HTTP URL %(path)s attempted to redirect "
                         "with an invalid %(status)s status code.") % {
                             'path': loc.path,
                             'status': resp.status
                         })
                LOG.debug(msg)
                raise exception.BadStoreUri(msg)
            location_class = glance.store.location.Location
            new_loc = location_class(location.store_name,
                                     location.store_location.__class__,
                                     uri=location_header,
                                     image_id=location.image_id,
                                     store_specs=location.store_specs)
            return self._query(new_loc, method, depth + 1)
        content_length = int(resp.getheader('content-length', 0))

        return (conn, resp, content_length)