Beispiel #1
0
 def parse_uri(self, uri):
     """
     Parse URLs. This method fixes an issue where credentials specified
     in the URL are interpreted differently in Python 2.6.1+ than prior
     versions of Python.
     """
     pieces = urllib.parse.urlparse(uri)
     assert pieces.scheme in ('file', 'filesystem')
     self.scheme = pieces.scheme
     path = (pieces.netloc + pieces.path).strip()
     if path == '':
         reason = _("No path specified in URI")
         LOG.info(reason)
         raise exceptions.BadStoreUri(message=reason)
     self.path = path
Beispiel #2
0
    def parse_uri(self, uri):
        prefix = 'rbd://'
        if not uri.startswith(prefix):
            reason = _('URI must start with rbd://')
            msg = _LI("Invalid URI: %s") % reason

            LOG.info(msg)
            raise exceptions.BadStoreUri(message=reason)
        # convert to ascii since librbd doesn't handle unicode
        try:
            ascii_uri = str(uri)
        except UnicodeError:
            reason = _('URI contains non-ascii characters')
            msg = _LI("Invalid URI: %s") % reason

            LOG.info(msg)
            raise exceptions.BadStoreUri(message=reason)
        pieces = ascii_uri[len(prefix):].split('/')
        if len(pieces) == 1:
            self.fsid, self.pool, self.image, self.snapshot = \
                (None, None, pieces[0], None)
        elif len(pieces) == 4:
            self.fsid, self.pool, self.image, self.snapshot = \
                map(urllib.parse.unquote, pieces)
        else:
            reason = _('URI must have exactly 1 or 4 components')
            msg = _LI("Invalid URI: %s") % reason

            LOG.info(msg)
            raise exceptions.BadStoreUri(message=reason)
        if any(map(lambda p: p == '', pieces)):
            reason = _('URI cannot contain empty components')
            msg = _LI("Invalid URI: %s") % reason

            LOG.info(msg)
            raise exceptions.BadStoreUri(message=reason)
Beispiel #3
0
    def parse_uri(self, uri):
        if not uri.startswith('%s://' % STORE_SCHEME):
            reason = (_("URI %(uri)s must start with %(scheme)s://") % {
                'uri': uri,
                'scheme': STORE_SCHEME
            })
            LOG.info(reason)
            raise exceptions.BadStoreUri(message=reason)
        (self.scheme, self.server_host, path, params, query,
         fragment) = urlparse.urlparse(uri)
        if not query:
            path, query = path.split('?')

        self.path = path
        self.query = query
Beispiel #4
0
 def parse_uri(self, uri):
     valid_schema = 'sheepdog://'
     if not uri.startswith(valid_schema):
         reason = _("URI must start with '%s'") % valid_schema
         raise exceptions.BadStoreUri(message=reason)
     pieces = uri[len(valid_schema):].split(':')
     if len(pieces) == 3:
         self.image = pieces[2]
         self.port = int(pieces[1])
         self.addr = pieces[0]
     # This is used for backwards compatibility.
     else:
         self.image = pieces[0]
         self.port = self.conf.glance_store.sheepdog_store_port
         self.addr = self.conf.glance_store.sheepdog_store_address
 def _get_conf_value_from_account_ref(self, netloc):
     try:
         self.user = SWIFT_STORE_REF_PARAMS[netloc]['user']
         self.key = SWIFT_STORE_REF_PARAMS[netloc]['key']
         netloc = SWIFT_STORE_REF_PARAMS[netloc]['auth_address']
         self.ssl_enabled = True
         if netloc != '':
             if netloc.startswith('http://'):
                 self.ssl_enabled = False
                 netloc = netloc[len('http://'):]
             elif netloc.startswith('https://'):
                 netloc = netloc[len('https://'):]
     except KeyError:
         reason = _("Badly formed Swift URI. Credentials not found for "
                    "account reference")
         LOG.info(reason)
         raise exceptions.BadStoreUri(message=reason)
     return netloc
Beispiel #6
0
    def get_size(self, location, context=None):
        """
        Takes a `glance_store.location.Location` object that indicates
        where to find the image file, and returns the size

        :param location `glance_store.location.Location` object, supplied
                        from glance_store.location.get_location_from_uri()
        """
        try:
            size = self._query(location, 'HEAD')[2]
        except socket.error:
            reason = _("The HTTP URL is invalid.")
            LOG.info(reason)
            raise exceptions.BadStoreUri(message=reason)
        except Exception:
            # NOTE(flaper87): Catch more granular exceptions,
            # keeping this branch for backwards compatibility.
            return 0
        return size
    def _query(self, location, method):
        session = new_session(self.api_insecure, self.ca_file)
        loc = location.store_location
        redirects_followed = 0
        # TODO(sabari): The redirect logic was added to handle cases when the
        # backend redirects http url's to https. But the store never makes a
        # http request and hence this can be safely removed.
        while redirects_followed < MAX_REDIRECTS:
            conn, resp = self._retry_request(session, method, location)

            # NOTE(sigmavirus24): _retry_request handles 4xx and 5xx errors so
            # if the response is not a redirect, we can return early.
            if not conn.is_redirect:
                break

            redirects_followed += 1

            location_header = conn.headers.get('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 exceptions.BadStoreUri(message=reason)
                conn.close()
                location = self._new_location(location, location_header)
        else:
            # NOTE(sigmavirus24): We exceeded the maximum number of redirects
            msg = ("The HTTP URL exceeded %(max_redirects)s maximum "
                   "redirects.", {
                       'max_redirects': MAX_REDIRECTS
                   })
            LOG.debug(msg)
            raise exceptions.MaxRedirectsExceeded(redirects=MAX_REDIRECTS)

        content_length = int(resp.getheader('content-length', 0))

        return (conn, resp, content_length)
Beispiel #8
0
    def parse_uri(self, uri):
        """
        Parse URLs. This method fixes an issue where credentials specified
        in the URL are interpreted differently in Python 2.6.1+ than prior
        versions of Python. It also deals with the peculiarity that new-style
        Swift URIs have where a username can contain a ':', like so:

            swift://account:user:[email protected]/container/obj
            and for system created locations with account reference
            swift+config://account_reference/container/obj
        """
        # Make sure that URIs that contain multiple schemes, such as:
        # swift://user:pass@http://authurl.com/v1/container/obj
        # are immediately rejected.
        if uri.count('://') != 1:
            reason = _("URI cannot contain more than one occurrence "
                       "of a scheme. If you have specified a URI like "
                       "swift://*****:*****@http://authurl.com/v1/container/obj"
                       ", you need to change it to use the "
                       "swift+http:// scheme, like so: "
                       "swift+http://user:[email protected]/v1/container/obj")
            LOG.info(_LI("Invalid store URI: %(reason)s"), {'reason': reason})
            raise exceptions.BadStoreUri(message=reason)

        pieces = urlparse.urlparse(uri)
        assert pieces.scheme in ('swift', 'swift+http', 'swift+https',
                                 'swift+config')

        self.scheme = pieces.scheme
        netloc = pieces.netloc
        path = pieces.path.lstrip('/')

        # NOTE(Sridevi): Fix to map the account reference to the
        # corresponding configuration value
        if self.scheme == 'swift+config':
            netloc = self._get_conf_value_from_account_ref(netloc)
        else:
            netloc, path = self._form_uri_parts(netloc, path)

        self._form_auth_or_store_url(netloc, path)
Beispiel #9
0
    def get_size(self, location, context=None):
        """
        Takes a `glance_store.location.Location` object that indicates
        where to find the image file, and returns the size

        :param location: `glance_store.location.Location` object, supplied
                        from glance_store.location.get_location_from_uri()
        """
        conn = None
        try:
            conn, resp, size = self._query(location, 'HEAD')
        except requests.exceptions.ConnectionError as exc:
            err_msg = encodeutils.exception_to_unicode(exc)
            reason = _("The HTTP URL is invalid: %s") % err_msg
            LOG.info(reason)
            raise exceptions.BadStoreUri(message=reason)
        finally:
            # NOTE(sabari): Close the connection as the request was made with
            # stream=True
            if conn is not None:
                conn.close()
        return size
Beispiel #10
0
    def _retry_request(self, session, method, location):
        loc = location.store_location
        # NOTE(arnaud): use a decorator when the config is not tied to self
        for i in range(self.api_retry_count + 1):
            cookie = self._build_vim_cookie_header()
            headers = {'Cookie': cookie}
            conn = session.request(method, loc.https_url, headers=headers,
                                   stream=True)
            resp = conn.raw

            if resp.status >= 400:
                if resp.status == requests.codes.unauthorized:
                    self.reset_session()
                    continue
                if resp.status == requests.codes.not_found:
                    reason = _('VMware datastore could not find image at URI.')
                    LOG.info(reason)
                    raise exceptions.NotFound(message=reason)
                msg = ('HTTP request returned a %(status)s status code.'
                       % {'status': resp.status})
                LOG.debug(msg)
                raise exceptions.BadStoreUri(msg)
            break
        return conn, resp
Beispiel #11
0
    def parse_uri(self, uri):
        if not uri.startswith('%s://' % STORE_SCHEME):
            reason = (_("URI %(uri)s must start with %(scheme)s://") %
                      {'uri': uri, 'scheme': STORE_SCHEME})
            LOG.info(reason)
            raise exceptions.BadStoreUri(message=reason)
        (self.scheme, self.server_host,
         path, params, query, fragment) = urllib.parse.urlparse(uri)
        if not query:
            path, query = path.split('?')

        self.path = path
        self.query = query
        # NOTE(flaper87): Read comment on `_is_valid_path`
        # reason = 'Badly formed VMware datastore URI %(uri)s.' % {'uri': uri}
        # LOG.debug(reason)
        # raise exceptions.BadStoreUri(reason)
        parts = urllib.parse.parse_qs(self.query)
        dc_path = parts.get('dcPath')
        if dc_path:
            self.datacenter_path = dc_path[0]
        ds_name = parts.get('dsName')
        if ds_name:
            self.datastore_name = ds_name[0]
Beispiel #12
0
    def parse_uri(self, uri):
        """
        Parse URLs. This method fixes an issue where credentials specified
        in the URL are interpreted differently in Python 2.6.1+ than prior
        versions of Python.

        Note that an Amazon AWS secret key can contain the forward slash,
        which is entirely retarded, and breaks urlparse miserably.
        This function works around that issue.
        """
        # Make sure that URIs that contain multiple schemes, such as:
        # s3://accesskey:secretkey@https://s3.amazonaws.com/bucket/key-id
        # are immediately rejected.
        if uri.count('://') != 1:
            reason = _("URI cannot contain more than one occurrence "
                       "of a scheme. If you have specified a URI like "
                       "s3://accesskey:secretkey@"
                       "https://s3.amazonaws.com/bucket/key-id"
                       ", you need to change it to use the "
                       "s3+https:// scheme, like so: "
                       "s3+https://accesskey:secretkey@"
                       "s3.amazonaws.com/bucket/key-id")
            LOG.info(_LI("Invalid store uri: %s") % reason)
            raise exceptions.BadStoreUri(message=reason)

        pieces = urllib.parse.urlparse(uri)
        assert pieces.scheme in ('s3', 's3+http', 's3+https')
        self.scheme = pieces.scheme
        path = pieces.path.strip('/')
        netloc = pieces.netloc.strip('/')
        entire_path = (netloc + '/' + path).strip('/')

        if '@' in uri:
            creds, path = entire_path.split('@')
            cred_parts = creds.split(':')

            try:
                access_key = cred_parts[0]
                secret_key = cred_parts[1]
                if six.PY2:
                    # NOTE(jaypipes): Need to encode to UTF-8 here because of a
                    # bug in the HMAC library that boto uses.
                    # See: http://bugs.python.org/issue5285
                    # See: http://trac.edgewall.org/ticket/8083
                    access_key = access_key.encode('utf-8')
                    secret_key = secret_key.encode('utf-8')
                self.accesskey = access_key
                self.secretkey = secret_key
            except IndexError:
                reason = _("Badly formed S3 credentials")
                LOG.info(reason)
                raise exceptions.BadStoreUri(message=reason)
        else:
            self.accesskey = None
            path = entire_path
        try:
            path_parts = path.split('/')
            self.key = path_parts.pop()
            self.bucket = path_parts.pop()
            if path_parts:
                self.s3serviceurl = '/'.join(path_parts).strip('/')
            else:
                reason = _("Badly formed S3 URI. Missing s3 service URL.")
                raise exceptions.BadStoreUri(message=reason)
        except IndexError:
            reason = _("Badly formed S3 URI")
            LOG.info(reason)
            raise exceptions.BadStoreUri(message=reason)
Beispiel #13
0
 def validate_location(self, uri):
     pieces = urlparse.urlparse(uri)
     if pieces.scheme in ['swift+config']:
         reason = (_("Location credentials are invalid"))
         raise exceptions.BadStoreUri(message=reason)
 def parse_uri(self, uri):
     valid_schema = 'sheepdog://'
     if not uri.startswith(valid_schema):
         reason = _("URI must start with '%s://'") % valid_schema
         raise exceptions.BadStoreUri(message=reason)
     self.image = uri[11:]