Example #1
0
    def get_connect_kwargs(self):
        connect_kwargs = {}

        # Both secure and insecure connections have a timeout option
        connect_kwargs['timeout'] = self.timeout

        if self.use_ssl:
            if self.key_file is None:
                self.key_file = os.environ.get('GLANCE_CLIENT_KEY_FILE')
            if self.cert_file is None:
                self.cert_file = os.environ.get('GLANCE_CLIENT_CERT_FILE')
            if self.ca_file is None:
                self.ca_file = os.environ.get('GLANCE_CLIENT_CA_FILE')

            # Check that key_file/cert_file are either both set or both unset
            if self.cert_file is not None and self.key_file is None:
                msg = _("You have selected to use SSL in connecting, "
                        "and you have supplied a cert, "
                        "however you have failed to supply either a "
                        "key_file parameter or set the "
                        "GLANCE_CLIENT_KEY_FILE environ variable")
                raise exception.ClientConnectionError(msg)

            if self.key_file is not None and self.cert_file is None:
                msg = _("You have selected to use SSL in connecting, "
                        "and you have supplied a key, "
                        "however you have failed to supply either a "
                        "cert_file parameter or set the "
                        "GLANCE_CLIENT_CERT_FILE environ variable")
                raise exception.ClientConnectionError(msg)

            if (self.key_file is not None
                    and not os.path.exists(self.key_file)):
                msg = _("The key file you specified %s does not "
                        "exist") % self.key_file
                raise exception.ClientConnectionError(msg)
            connect_kwargs['key_file'] = self.key_file

            if (self.cert_file is not None
                    and not os.path.exists(self.cert_file)):
                msg = _("The cert file you specified %s does not "
                        "exist") % self.cert_file
                raise exception.ClientConnectionError(msg)
            connect_kwargs['cert_file'] = self.cert_file

            if (self.ca_file is not None and not os.path.exists(self.ca_file)):
                msg = _("The CA file you specified %s does not "
                        "exist") % self.ca_file
                raise exception.ClientConnectionError(msg)

            if self.ca_file is None:
                for ca in self.DEFAULT_CA_FILE_PATH.split(":"):
                    if os.path.exists(ca):
                        self.ca_file = ca
                        break

            connect_kwargs['ca_file'] = self.ca_file
            connect_kwargs['insecure'] = self.insecure

        return connect_kwargs
Example #2
0
def get_stats(user, passwd, tenant, url, host=None):
    creds = {
        "username": user,
        "password": passwd,
        "tenant": tenant,
        "auth_url": url,
        "strategy": OS_AUTH_STRATEGY
    }
    client = V1Client(host, creds=creds)
    try:
        image_list = client.get_images_detailed()
    except exception.NotAuthenticated:
        msg = "Client credentials appear to be invalid"
        raise exception.ClientConnectionError(msg)
    else:
        # TODO(shep): this needs to be rewritten more inline with the keystone|nova plugins
        data = dict()
        data["count"] = int(len(image_list))
        data["bytes"] = 0
        data["snapshot.count"] = 0
        data["snapshot.bytes"] = 0
        data["tenant"] = dict()
        for image in image_list:
            data["bytes"] += int(image["size"])
            if "image_type" in image["properties"] and image["properties"][
                    "image_type"] == "snapshot":
                data["snapshot.count"] += 1
                data["snapshot.bytes"] += int(image["size"])
            uuid = str(image["owner"])
            if uuid in data["tenant"]:
                data["tenant"][uuid]["count"] += 1
                data["tenant"][uuid]["bytes"] += int(image["size"])
                if "image_type" in image["properties"] and image["properties"][
                        "image_type"] == "snapshot":
                    data["tenant"][uuid]["snapshot.count"] += 1
                    data["tenant"][uuid]["snapshot.bytes"] += int(
                        image["size"])
            else:
                data["tenant"][uuid] = dict()
                data["tenant"][uuid]["count"] = 1
                data["tenant"][uuid]["bytes"] = int(image["size"])
                data["tenant"][uuid]["snapshot.count"] = 0
                data["tenant"][uuid]["snapshot.bytes"] = 0
                if "image_type" in image["properties"] and image["properties"][
                        "image_type"] == "snapshot":
                    data["tenant"][uuid]["snapshot.count"] += 1
                    data["tenant"][uuid]["snapshot.bytes"] += int(
                        image["size"])
        # debug
        #for key in data.keys():
        #    if key == "tenant":
        #        for uuid in data[key].keys():
        #            for field in data[key][uuid]:
        #                print "glance.images.tenant.%s.%s : %i" % (uuid, field, data[key][uuid][field])
        #    else:
        #        print "glance.images.%s : %i" % (key, data[key])
        ##########
        return data
Example #3
0
 def inner_func(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         exc_message = str(exc)
         if ('Unknown error occurred' in exc_message
                 or 'Internal Server error' in exc_message):
             raise glance_exception.ClientConnectionError(exc_message)
         raise
    def test_index_client_conn_error(self):
        self.mox.StubOutWithMock(api, 'image_list_detailed')
        self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
        exc = glance_exception.ClientConnectionError('clientConnError')
        api.image_list_detailed(IsA(http.HttpRequest)).AndRaise(exc)
        api.snapshot_list_detailed(IsA(http.HttpRequest)) \
                                   .AndReturn(self.snapshots.list())
        self.mox.ReplayAll()

        res = self.client.get(INDEX_URL)
        self.assertTemplateUsed(res, 'nova/images_and_snapshots/index.html')
Example #5
0
    def test_index_client_conn_error(self):
        self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
        exception = glance_exception.ClientConnectionError('clientConnError')
        api.snapshot_list_detailed(IsA(http.HttpRequest)).AndRaise(exception)

        self.mox.StubOutWithMock(messages, 'error')
        messages.error(IsA(http.HttpRequest), IsA(basestring))

        self.mox.ReplayAll()

        res = self.client.get(reverse('horizon:nova:snapshots:index'))

        self.assertTemplateUsed(res, 'nova/snapshots/index.html')
Example #6
0
    def test_index_client_conn_error(self):
        self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
        exception = glance_exception.ClientConnectionError('clientConnError')
        api.snapshot_list_detailed(IsA(http.HttpRequest)).AndRaise(exception)

        self.mox.StubOutWithMock(messages, 'error')
        messages.error(IsA(http.HttpRequest), IsA(str))

        self.mox.ReplayAll()

        res = self.client.get(
            reverse('dash_snapshots', args=[self.TEST_TENANT]))

        self.assertTemplateUsed(res,
                                'django_openstack/dash/snapshots/index.html')

        self.mox.VerifyAll()
Example #7
0
    def test_index_client_conn_error(self):
        self.mox.StubOutWithMock(api, 'image_list_detailed')
        exception = glance_exception.ClientConnectionError('clientConnError')
        api.image_list_detailed(IsA(http.HttpRequest)).AndRaise(exception)

        self.mox.StubOutWithMock(api, 'tenant_quota_get')
        api.tenant_quota_get(IsA(http.HttpRequest), self.TEST_TENANT) \
                .AndReturn({})

        self.mox.StubOutWithMock(messages, 'error')
        messages.error(IsA(http.HttpRequest), IsA(basestring))

        self.mox.ReplayAll()

        res = self.client.get(IMAGES_INDEX_URL)

        self.assertTemplateUsed(res,
                'nova/images/index.html')
    def test_download_metadata_client_conn_error(self):
        IMAGE_ID = '1'

        self.mox.StubOutWithMock(api, 'image_get_meta')
        exception = glance_exception.ClientConnectionError('clientConnError')
        api.image_get_meta(IsA(http.HttpRequest), IMAGE_ID).AndRaise(exception)

        self.mox.StubOutWithMock(messages, 'error')
        messages.error(IsA(http.HttpRequest), IsA(str))

        self.mox.ReplayAll()

        res = self.client.get(
            reverse('dash_metadata_download',
                    args=[self.TEST_TENANT, IMAGE_ID]))

        self.assertRedirectsNoFollow(
            res, reverse('dash_images_metadata', args=[self.TEST_TENANT]))

        self.mox.VerifyAll()
Example #9
0
    def _do_request(self, method, url, body, headers):
        """
        Connects to the server and issues a request.  Handles converting
        any returned HTTP error status codes to OpenStack/Glance exceptions
        and closing the server connection. Returns the result data, or
        raises an appropriate exception.

        :param method: HTTP method ("GET", "POST", "PUT", etc...)
        :param url: urlparse.ParsedResult object with URL information
        :param body: data to send (as string, filelike or iterable),
                     or None (default)
        :param headers: mapping of key/value pairs to add as headers

        :note

        If the body param has a read attribute, and method is either
        POST or PUT, this method will automatically conduct a chunked-transfer
        encoding and use the body as a file object or iterable, transferring
        chunks of data using the connection's send() method. This allows large
        objects to be transferred efficiently without buffering the entire
        body in memory.
        """
        if url.query:
            path = url.path + "?" + url.query
        else:
            path = url.path

        try:
            connection_type = self.get_connection_type()
            headers = self._encode_headers(headers or {})

            if 'x-auth-token' not in headers and self.auth_tok:
                headers['x-auth-token'] = self.auth_tok

            c = connection_type(url.hostname, url.port, **self.connect_kwargs)

            def _pushing(method):
                return method.lower() in ('post', 'put')

            def _simple(body):
                return body is None or isinstance(body, six.string_types)

            def _filelike(body):
                return hasattr(body, 'read')

            def _sendbody(connection, iter):
                connection.endheaders()
                for sent in iter:
                    # iterator has done the heavy lifting
                    pass

            def _chunkbody(connection, iter):
                connection.putheader('Transfer-Encoding', 'chunked')
                connection.endheaders()
                for chunk in iter:
                    connection.send('%x\r\n%s\r\n' % (len(chunk), chunk))
                connection.send('0\r\n\r\n')

            # Do a simple request or a chunked request, depending
            # on whether the body param is file-like or iterable and
            # the method is PUT or POST
            #
            if not _pushing(method) or _simple(body):
                # Simple request...
                c.request(method, path, body, headers)
            elif _filelike(body) or self._iterable(body):
                c.putrequest(method, path)

                use_sendfile = self._sendable(body)

                # According to HTTP/1.1, Content-Length and Transfer-Encoding
                # conflict.
                for header, value in headers.items():
                    if use_sendfile or header.lower() != 'content-length':
                        c.putheader(header, str(value))

                iter = self.image_iterator(c, headers, body)

                if use_sendfile:
                    # send actual file without copying into userspace
                    _sendbody(c, iter)
                else:
                    # otherwise iterate and chunk
                    _chunkbody(c, iter)
            else:
                raise TypeError('Unsupported image type: %s' % body.__class__)

            res = c.getresponse()

            def _retry(res):
                return res.getheader('Retry-After')

            status_code = self.get_status_code(res)
            if status_code in self.OK_RESPONSE_CODES:
                return res
            elif status_code in self.REDIRECT_RESPONSE_CODES:
                raise exception.RedirectException(res.getheader('Location'))
            elif status_code == httplib.UNAUTHORIZED:
                raise exception.NotAuthenticated(res.read())
            elif status_code == httplib.FORBIDDEN:
                raise exception.Forbidden(res.read())
            elif status_code == httplib.NOT_FOUND:
                raise exception.NotFound(res.read())
            elif status_code == httplib.CONFLICT:
                raise exception.Duplicate(res.read())
            elif status_code == httplib.BAD_REQUEST:
                raise exception.Invalid(res.read())
            elif status_code == httplib.MULTIPLE_CHOICES:
                raise exception.MultipleChoices(body=res.read())
            elif status_code == httplib.REQUEST_ENTITY_TOO_LARGE:
                raise exception.LimitExceeded(retry=_retry(res),
                                              body=res.read())
            elif status_code == httplib.INTERNAL_SERVER_ERROR:
                raise exception.ServerError()
            elif status_code == httplib.SERVICE_UNAVAILABLE:
                raise exception.ServiceUnavailable(retry=_retry(res))
            else:
                raise exception.UnexpectedStatus(status=status_code,
                                                 body=res.read())

        except (socket.error, IOError) as e:
            raise exception.ClientConnectionError(e)
Example #10
0
    def __init__(self,
                 host,
                 port=None,
                 use_ssl=False,
                 auth_tok=None,
                 creds=None,
                 doc_root=None,
                 key_file=None,
                 cert_file=None,
                 ca_file=None):
        """
        Creates a new client to some service.

        :param host: The host where service resides
        :param port: The port where service resides
        :param use_ssl: Should we use HTTPS?
        :param auth_tok: The auth token to pass to the server
        :param creds: The credentials to pass to the auth plugin
        :param doc_root: Prefix for all URLs we request from host
        :param key_file: Optional PEM-formatted file that contains the private
                         key.
                         If use_ssl is True, and this param is None (the
                         default), then an environ variable
                         GLANCE_CLIENT_KEY_FILE is looked for. If no such
                         environ variable is found, ClientConnectionError
                         will be raised.
        :param cert_file: Optional PEM-formatted certificate chain file.
                          If use_ssl is True, and this param is None (the
                          default), then an environ variable
                          GLANCE_CLIENT_CERT_FILE is looked for. If no such
                          environ variable is found, ClientConnectionError
                          will be raised.
        :param ca_file: Optional CA cert file to use in SSL connections
                        If use_ssl is True, and this param is None (the
                        default), then an environ variable
                        GLANCE_CLIENT_CA_FILE is looked for.
        """
        self.host = host
        self.port = port or self.DEFAULT_PORT
        self.use_ssl = use_ssl
        self.auth_tok = auth_tok
        self.creds = creds or {}
        self.connection = None
        # doc_root can be a nullstring, which is valid, and why we
        # cannot simply do doc_root or self.DEFAULT_DOC_ROOT below.
        self.doc_root = (doc_root
                         if doc_root is not None else self.DEFAULT_DOC_ROOT)
        self.auth_plugin = self.make_auth_plugin(self.creds)
        self.connect_kwargs = {}

        if use_ssl:
            if key_file is None:
                key_file = os.environ.get('GLANCE_CLIENT_KEY_FILE')
            if cert_file is None:
                cert_file = os.environ.get('GLANCE_CLIENT_CERT_FILE')
            if ca_file is None:
                ca_file = os.environ.get('GLANCE_CLIENT_CA_FILE')

            # Check that key_file/cert_file are either both set or both unset
            if cert_file is not None and key_file is None:
                msg = _("You have selected to use SSL in connecting, "
                        "and you have supplied a cert, "
                        "however you have failed to supply either a "
                        "key_file parameter or set the "
                        "GLANCE_CLIENT_KEY_FILE environ variable")
                raise exception.ClientConnectionError(msg)

            if key_file is not None and cert_file is None:
                msg = _("You have selected to use SSL in connecting, "
                        "and you have supplied a key, "
                        "however you have failed to supply either a "
                        "cert_file parameter or set the "
                        "GLANCE_CLIENT_CERT_FILE environ variable")
                raise exception.ClientConnectionError(msg)

            if key_file is not None and not os.path.exists(key_file):
                msg = _("The key file you specified %s does not "
                        "exist") % key_file
                raise exception.ClientConnectionError(msg)
            self.connect_kwargs['key_file'] = key_file

            if cert_file is not None and not os.path.exists(cert_file):
                msg = _("The cert file you specified %s does not "
                        "exist") % cert_file
                raise exception.ClientConnectionError(msg)
            self.connect_kwargs['cert_file'] = cert_file

            if ca_file is not None and not os.path.exists(ca_file):
                msg = _("The CA file you specified %s does not "
                        "exist") % ca_file
                raise exception.ClientConnectionError(msg)
            self.connect_kwargs['ca_file'] = ca_file
Example #11
0
    def _do_request(self,
                    method,
                    action,
                    body=None,
                    headers=None,
                    params=None):
        """
        Connects to the server and issues a request.  Handles converting
        any returned HTTP error status codes to OpenStack/Glance exceptions
        and closing the server connection. Returns the result data, or
        raises an appropriate exception.

        :param method: HTTP method ("GET", "POST", "PUT", etc...)
        :param action: part of URL after root netloc
        :param body: string of data to send, or None (default)
        :param headers: mapping of key/value pairs to add as headers
        :param params: dictionary of key/value pairs to add to append
                             to action

        :note

        If the body param has a read attribute, and method is either
        POST or PUT, this method will automatically conduct a chunked-transfer
        encoding and use the body as a file object, transferring chunks
        of data using the connection's send() method. This allows large
        objects to be transferred efficiently without buffering the entire
        body in memory.
        """
        if type(params) is dict:

            # remove any params that are None
            for (key, value) in params.items():
                if value is None:
                    del params[key]

            action += '?' + urllib.urlencode(params)

        try:
            connection_type = self.get_connection_type()
            headers = headers or {}

            if 'x-auth-token' not in headers and self.auth_tok:
                headers['x-auth-token'] = self.auth_tok

            c = connection_type(self.host, self.port)

            if self.doc_root:
                action = '/'.join([self.doc_root, action.lstrip('/')])

            # Do a simple request or a chunked request, depending
            # on whether the body param is a file-like object and
            # the method is PUT or POST
            if hasattr(body, 'read') and method.lower() in ('post', 'put'):
                # Chunk it, baby...
                c.putrequest(method, action)

                for header, value in headers.items():
                    c.putheader(header, value)
                c.putheader('Transfer-Encoding', 'chunked')
                c.endheaders()

                chunk = body.read(self.CHUNKSIZE)
                while chunk:
                    c.send('%x\r\n%s\r\n' % (len(chunk), chunk))
                    chunk = body.read(self.CHUNKSIZE)
                c.send('0\r\n\r\n')
            else:
                # Simple request...
                c.request(method, action, body, headers)
            res = c.getresponse()
            status_code = self.get_status_code(res)
            if status_code in (httplib.OK, httplib.CREATED, httplib.ACCEPTED,
                               httplib.NO_CONTENT):
                return res
            elif status_code == httplib.UNAUTHORIZED:
                raise exception.NotAuthorized(res.read())
            elif status_code == httplib.FORBIDDEN:
                raise exception.NotAuthorized(res.read())
            elif status_code == httplib.NOT_FOUND:
                raise exception.NotFound(res.read())
            elif status_code == httplib.CONFLICT:
                raise exception.Duplicate(res.read())
            elif status_code == httplib.BAD_REQUEST:
                raise exception.Invalid(res.read())
            elif status_code == httplib.MULTIPLE_CHOICES:
                raise exception.MultipleChoices(body=res.read())
            elif status_code == httplib.INTERNAL_SERVER_ERROR:
                raise Exception("Internal Server error: %s" % res.read())
            else:
                raise Exception("Unknown error occurred! %s" % res.read())

        except (socket.error, IOError), e:
            raise exception.ClientConnectionError("Unable to connect to "
                                                  "server. Got error: %s" % e)
Example #12
0
    def _do_request(self, method, url, body, headers):
        """
        Connects to the server and issues a request.  Handles converting
        any returned HTTP error status codes to OpenStack/Glance exceptions
        and closing the server connection. Returns the result data, or
        raises an appropriate exception.

        :param method: HTTP method ("GET", "POST", "PUT", etc...)
        :param url: urlparse.ParsedResult object with URL information
        :param body: string of data to send, or None (default)
        :param headers: mapping of key/value pairs to add as headers

        :note

        If the body param has a read attribute, and method is either
        POST or PUT, this method will automatically conduct a chunked-transfer
        encoding and use the body as a file object, transferring chunks
        of data using the connection's send() method. This allows large
        objects to be transferred efficiently without buffering the entire
        body in memory.
        """
        if url.query:
            path = url.path + "?" + url.query
        else:
            path = url.path

        try:
            connection_type = self.get_connection_type()
            headers = headers or {}

            if 'x-auth-token' not in headers and self.auth_tok:
                headers['x-auth-token'] = self.auth_tok

            c = connection_type(url.hostname, url.port, **self.connect_kwargs)

            # Do a simple request or a chunked request, depending
            # on whether the body param is a file-like object and
            # the method is PUT or POST
            if hasattr(body, 'read') and method.lower() in ('post', 'put'):
                # Chunk it, baby...
                c.putrequest(method, path)

                for header, value in headers.items():
                    c.putheader(header, value)
                c.putheader('Transfer-Encoding', 'chunked')
                c.endheaders()

                chunk = body.read(self.CHUNKSIZE)
                while chunk:
                    c.send('%x\r\n%s\r\n' % (len(chunk), chunk))
                    chunk = body.read(self.CHUNKSIZE)
                c.send('0\r\n\r\n')
            else:
                # Simple request...
                c.request(method, path, body, headers)
            res = c.getresponse()
            status_code = self.get_status_code(res)
            if status_code in self.OK_RESPONSE_CODES:
                return res
            elif status_code in self.REDIRECT_RESPONSE_CODES:
                raise exception.RedirectException(res.getheader('Location'))
            elif status_code == httplib.UNAUTHORIZED:
                raise exception.NotAuthorized(res.read())
            elif status_code == httplib.FORBIDDEN:
                raise exception.NotAuthorized(res.read())
            elif status_code == httplib.NOT_FOUND:
                raise exception.NotFound(res.read())
            elif status_code == httplib.CONFLICT:
                raise exception.Duplicate(res.read())
            elif status_code == httplib.BAD_REQUEST:
                raise exception.Invalid(res.read())
            elif status_code == httplib.MULTIPLE_CHOICES:
                raise exception.MultipleChoices(body=res.read())
            elif status_code == httplib.INTERNAL_SERVER_ERROR:
                raise Exception("Internal Server error: %s" % res.read())
            else:
                raise Exception("Unknown error occurred! %s" % res.read())

        except (socket.error, IOError), e:
            raise exception.ClientConnectionError(e)