示例#1
0
    def log_curl_request(self, method, url, headers, data, kwargs):
        curl = ['curl -i -X %s' % method]

        for (key, value) in self.session.headers.items():
            if key.lower() == 'x-auth-token':
                value = '*' * 3
            header = '-H \'%s: %s\'' % (key, value)
            curl.append(strutils.safe_encode(header))

        if not self.session.verify:
            curl.append('-k')
        else:
            if isinstance(self.session.verify, six.string_types):
                curl.append(' --cacert %s' % self.session.verify)

        if self.session.cert:
            curl.append(' --cert %s --key %s' % self.session.cert)

        if data and isinstance(data, six.string_types):
            curl.append('-d \'%s\'' % data)

        if "//:" not in url:
            url = '%s%s' % (self.endpoint, url)
        curl.append(url)
        LOG.debug(strutils.safe_encode(' '.join(curl), errors='ignore'))
示例#2
0
    def list(self, **kwargs):
        """Retrieve a listing of Image objects

        :param page_size: Number of images to request in each paginated request
        :returns generator over list of Images
        """

        ori_validate_fun = self.model.validate
        empty_fun = lambda *args, **kwargs: None

        def paginate(url):
            resp, body = self.http_client.get(url)
            for image in body['images']:
                # NOTE(bcwaldon): remove 'self' for now until we have
                # an elegant way to pass it into the model constructor
                # without conflict.
                image.pop('self', None)
                yield self.model(**image)
                # NOTE(zhiyan): In order to resolve the performance issue
                # of JSON schema validation for image listing case, we
                # don't validate each image entry but do it only on first
                # image entry for each page.
                self.model.validate = empty_fun

            # NOTE(zhiyan); Reset validation function.
            self.model.validate = ori_validate_fun

            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for image in paginate(next_url):
                    yield image

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        tags = filters.pop('tag', [])
        tags_url_params = []

        for tag in tags:
            if isinstance(tag, six.string_types):
                tags_url_params.append({'tag': strutils.safe_encode(tag)})

        for param, value in six.iteritems(filters):
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/images?%s' % parse.urlencode(filters)

        for param in tags_url_params:
            url = '%s&%s' % (url, parse.urlencode(param))

        for image in paginate(url):
            yield image
示例#3
0
    def log_curl_request(self, method, url, headers, data, kwargs):
        curl = ['curl -i -X %s' % method]

        for (key, value) in self.session.headers.items():
            if key.lower() == 'x-auth-token':
                value = '*' * 3
            header = '-H \'%s: %s\'' % (key, value)
            curl.append(strutils.safe_encode(header))

        if not self.session.verify:
            curl.append('-k')
        else:
            if isinstance(self.session.verify, six.string_types):
                curl.append(' --cacert %s' % self.session.verify)

        if self.session.cert:
            curl.append(' --cert %s --key %s' % self.session.cert)

        if data and isinstance(data, six.string_types):
            curl.append('-d \'%s\'' % data)

        if "//:" not in url:
            url = '%s%s' % (self.endpoint, url)
        curl.append(url)
        LOG.debug(strutils.safe_encode(' '.join(curl), errors='ignore'))
示例#4
0
    def list(self, **kwargs):
        """Retrieve a listing of Image objects

        :param page_size: Number of images to request in each paginated request
        :returns generator over list of Images
        """

        ori_validate_fun = self.model.validate
        empty_fun = lambda *args, **kwargs: None

        def paginate(url):
            resp, body = self.http_client.get(url)
            for image in body['images']:
                # NOTE(bcwaldon): remove 'self' for now until we have
                # an elegant way to pass it into the model constructor
                # without conflict.
                image.pop('self', None)
                yield self.model(**image)
                # NOTE(zhiyan): In order to resolve the performance issue
                # of JSON schema validation for image listing case, we
                # don't validate each image entry but do it only on first
                # image entry for each page.
                self.model.validate = empty_fun

            # NOTE(zhiyan); Reset validation function.
            self.model.validate = ori_validate_fun

            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for image in paginate(next_url):
                    yield image

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        tags = filters.pop('tag', [])
        tags_url_params = []

        for tag in tags:
            if isinstance(tag, six.string_types):
                tags_url_params.append({'tag': strutils.safe_encode(tag)})

        for param, value in six.iteritems(filters):
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/images?%s' % parse.urlencode(filters)

        for param in tags_url_params:
            url = '%s&%s' % (url, parse.urlencode(param))

        for image in paginate(url):
            yield image
示例#5
0
    def encode_headers(headers):
        """Encodes headers.

        Note: This should be used right before
        sending anything out.

        :param headers: Headers to encode
        :returns: Dictionary with encoded headers'
                  names and values
        """
        return dict((strutils.safe_encode(h), strutils.safe_encode(v)) for h, v in six.iteritems(headers))
示例#6
0
    def list(self, **kwargs):
        """Retrieve a listing of Namespace objects

        :param page_size: Number of namespaces to request in each request
        :returns generator over list of Namespaces
        """

        ori_validate_fun = self.model.validate
        empty_fun = lambda *args, **kwargs: None

        def paginate(url):
            resp, body = self.http_client.get(url)
            for namespace in body['namespaces']:
                # NOTE(bcwaldon): remove 'self' for now until we have
                # an elegant way to pass it into the model constructor
                # without conflict.
                namespace.pop('self', None)
                yield self.model(**namespace)
                # NOTE(zhiyan): In order to resolve the performance issue
                # of JSON schema validation for image listing case, we
                # don't validate each image entry but do it only on first
                # image entry for each page.
                self.model.validate = empty_fun

            # NOTE(zhiyan); Reset validation function.
            self.model.validate = ori_validate_fun

            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for namespace in paginate(next_url):
                    yield namespace

        filters = kwargs.get('filters', {})
        filters = {} if filters is None else filters

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        for param, value in six.iteritems(filters):
            if isinstance(value, list):
                filters[param] = strutils.safe_encode(','.join(value))
            elif isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)

        for namespace in paginate(url):
            yield namespace
示例#7
0
    def encode_headers(headers):
        """Encodes headers.

        Note: This should be used right before
        sending anything out.

        :param headers: Headers to encode
        :returns: Dictionary with encoded headers'
                  names and values
        """
        return dict((strutils.safe_encode(h), strutils.safe_encode(v))
                    for h, v in six.iteritems(headers))
示例#8
0
    def list(self, **kwargs):
        """Retrieve a listing of Namespace objects

        :param page_size: Number of namespaces to request in each request
        :returns generator over list of Namespaces
        """

        ori_validate_fun = self.model.validate
        empty_fun = lambda *args, **kwargs: None

        def paginate(url):
            resp, body = self.http_client.get(url)
            for namespace in body['namespaces']:
                # NOTE(bcwaldon): remove 'self' for now until we have
                # an elegant way to pass it into the model constructor
                # without conflict.
                namespace.pop('self', None)
                yield self.model(**namespace)
                # NOTE(zhiyan): In order to resolve the performance issue
                # of JSON schema validation for image listing case, we
                # don't validate each image entry but do it only on first
                # image entry for each page.
                self.model.validate = empty_fun

            # NOTE(zhiyan); Reset validation function.
            self.model.validate = ori_validate_fun

            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for namespace in paginate(next_url):
                    yield namespace

        filters = kwargs.get('filters', {})
        filters = {} if filters is None else filters

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        for param, value in six.iteritems(filters):
            if isinstance(value, list):
                filters[param] = strutils.safe_encode(','.join(value))
            elif isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)

        for namespace in paginate(url):
            yield namespace
    def log_curl_request(self, method, url, kwargs):
        curl = ['curl -i -X %s' % method]

        for (key, value) in kwargs['headers'].items():
            header = '-H \'%s: %s\'' % (key, value)
            curl.append(header)

        conn_params_fmt = [
            ('key_file', '--key %s'),
            ('cert_file', '--cert %s'),
            ('cacert', '--cacert %s'),
        ]
        for (key, fmt) in conn_params_fmt:
            value = self.connection_kwargs.get(key)
            if value:
                curl.append(fmt % value)

        if self.connection_kwargs.get('insecure'):
            curl.append('-k')

        if kwargs.get('body') is not None:
            curl.append('-d \'%s\'' % kwargs['body'])

        curl.append('%s%s' % (self.endpoint, url))
        LOG.debug(strutils.safe_encode(' '.join(curl)))
示例#10
0
def print_list(objs, fields, formatters={}):
    pt = prettytable.PrettyTable([f for f in fields], caching=False)
    pt.align = 'l'

    for o in objs:
        row = []
        for field in fields:
            if field in formatters:
                row.append(formatters[field](o))
            else:
                field_name = field.lower().replace(' ', '_')
                data = getattr(o, field_name, None) or ''
                row.append(data)
        pt.add_row(row)

    print strutils.safe_encode(pt.get_string())
示例#11
0
    def log_curl_request(self, method, url, headers, data, kwargs):
        curl = ['curl -i -X %s' % method]

        headers = copy.deepcopy(headers)
        headers.update(self.session.headers)

        for (key, value) in six.iteritems(headers):
            header = '-H \'%s: %s\'' % safe_header(key, value)
            curl.append(header)

        if not self.session.verify:
            curl.append('-k')
        else:
            if isinstance(self.session.verify, six.string_types):
                curl.append(' --cacert %s' % self.session.verify)

        if self.session.cert:
            curl.append(' --cert %s --key %s' % self.session.cert)

        if data and isinstance(data, six.string_types):
            curl.append('-d \'%s\'' % data)

        curl.append(url)

        msg = ' '.join([strutils.safe_encode(item, errors='ignore')
                        for item in curl])
        LOG.debug(msg)
示例#12
0
    def log_curl_request(self, method, url, headers, data, kwargs):
        curl = ['curl -i -X %s' % method]

        headers = copy.deepcopy(headers)
        headers.update(self.session.headers)

        for (key, value) in six.iteritems(headers):
            header = '-H \'%s: %s\'' % safe_header(key, value)
            curl.append(header)

        if not self.session.verify:
            curl.append('-k')
        else:
            if isinstance(self.session.verify, six.string_types):
                curl.append(' --cacert %s' % self.session.verify)

        if self.session.cert:
            curl.append(' --cert %s --key %s' % self.session.cert)

        if data and isinstance(data, six.string_types):
            curl.append('-d \'%s\'' % data)

        curl.append(url)

        msg = ' '.join(
            [strutils.safe_encode(item, errors='ignore') for item in curl])
        LOG.debug(msg)
示例#13
0
        def paginate(qp, seen=0):
            # Note(flaper87) Url encoding should
            # be moved inside http utils, at least
            # shouldn't be here.
            #
            # Making sure all params are str before
            # trying to encode them
            for param, value in qp.iteritems():
                if isinstance(value, basestring):
                    qp[param] = strutils.safe_encode(value)

            url = '/v1/images/detail?%s' % urllib.urlencode(qp)
            images = self._list(url, "images")
            for image in images:
                seen += 1
                if absolute_limit is not None and seen > absolute_limit:
                    return
                yield image

            page_size = qp.get('limit')
            if (page_size and len(images) == page_size and
                    (absolute_limit is None or 0 < seen < absolute_limit)):
                qp['marker'] = image.id
                for image in paginate(qp, seen):
                    yield image
示例#14
0
def find_resource(manager, name_or_id):
    """Helper for the _find_* methods."""
    # first try to get entity as integer id
    try:
        if isinstance(name_or_id, int) or name_or_id.isdigit():
            return manager.get(int(name_or_id))
    except exc.NotFound:
        pass

    # now try to get entity as uuid
    try:
        uuid.UUID(strutils.safe_encode(name_or_id))
        return manager.get(name_or_id)
    except (ValueError, exc.NotFound):
        pass

    # finally try to find entity by name
    matches = list(manager.list(filters={'name': name_or_id}))
    num_matches = len(matches)
    if num_matches == 0:
        msg = "No %s with a name or ID of '%s' exists." % \
              (manager.resource_class.__name__.lower(), name_or_id)
        raise exc.CommandError(msg)
    elif num_matches > 1:
        msg = ("Multiple %s matches found for '%s', use an ID to be more"
               " specific." % (manager.resource_class.__name__.lower(),
                               name_or_id))
        raise exc.CommandError(msg)
    else:
        return matches[0]
示例#15
0
def find_resource(manager, name_or_id):
    """Helper for the _find_* methods."""
    # first try to get entity as integer id
    try:
        if isinstance(name_or_id, int) or name_or_id.isdigit():
            return manager.get(int(name_or_id))
    except exc.NotFound:
        pass

    # now try to get entity as uuid
    try:
        uuid.UUID(strutils.safe_encode(name_or_id))
        return manager.get(name_or_id)
    except (ValueError, exc.NotFound):
        pass

    # finally try to find entity by name
    matches = list(manager.list(filters={'name': name_or_id}))
    num_matches = len(matches)
    if num_matches == 0:
        msg = "No %s with a name or ID of '%s' exists." % \
              (manager.resource_class.__name__.lower(), name_or_id)
        raise exc.CommandError(msg)
    elif num_matches > 1:
        msg = ("Multiple %s matches found for '%s', use an ID to be more"
               " specific." % (manager.resource_class.__name__.lower(),
                               name_or_id))
        raise exc.CommandError(msg)
    else:
        return matches[0]
示例#16
0
def print_list(objs, fields, formatters={}):
    pt = prettytable.PrettyTable([f for f in fields], caching=False)
    pt.align = 'l'

    for o in objs:
        row = []
        for field in fields:
            if field in formatters:
                row.append(formatters[field](o))
            else:
                field_name = field.lower().replace(' ', '_')
                data = getattr(o, field_name, None) or ''
                row.append(data)
        pt.add_row(row)

    print strutils.safe_encode(pt.get_string())
示例#17
0
    def log_curl_request(self, method, url, kwargs):
        curl = ['curl -i -X %s' % method]

        for (key, value) in kwargs['headers'].items():
            header = '-H \'%s: %s\'' % (key, value)
            curl.append(header)

        conn_params_fmt = [
            ('key_file', '--key %s'),
            ('cert_file', '--cert %s'),
            ('cacert', '--cacert %s'),
        ]
        for (key, fmt) in conn_params_fmt:
            value = self.connection_kwargs.get(key)
            if value:
                curl.append(fmt % value)

        if self.connection_kwargs.get('insecure'):
            curl.append('-k')

        if kwargs.get('body') is not None:
            curl.append('-d \'%s\'' % kwargs['body'])

        curl.append('%s%s' % (self.endpoint, url))
        LOG.debug(strutils.safe_encode(' '.join(curl)))
示例#18
0
    def list(self, **kwargs):
        """Retrieve a listing of Image objects

        :param page_size: Number of images to request in each paginated request
        :returns generator over list of Images
        """
        def paginate(url):
            resp, body = self.http_client.json_request('GET', url)
            for image in body['images']:
                yield image
            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for image in paginate(next_url):
                    yield image

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        tags = filters.pop('tag', [])
        tags_url_params = []

        for tag in tags:
            if isinstance(tag, six.string_types):
                tags_url_params.append({'tag': strutils.safe_encode(tag)})

        for param, value in six.iteritems(filters):
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/images?%s' % parse.urlencode(filters)

        for param in tags_url_params:
            url = '%s&%s' % (url, parse.urlencode(param))

        for image in paginate(url):
            #NOTE(bcwaldon): remove 'self' for now until we have an elegant
            # way to pass it into the model constructor without conflict
            image.pop('self', None)
            yield self.model(**image)
示例#19
0
 def log_http_response(resp, body=None):
     status = (resp.version / 10.0, resp.status, resp.reason)
     dump = ["\nHTTP/%.1f %s %s" % status]
     dump.extend(["%s: %s" % (k, v) for k, v in resp.getheaders()])
     dump.append("")
     if body:
         dump.extend([body, ""])
     LOG.debug(strutils.safe_encode("\n".join(dump)))
示例#20
0
 def log_http_response(resp, body=None):
     status = (resp.version / 10.0, resp.status, resp.reason)
     dump = ['\nHTTP/%.1f %s %s' % status]
     dump.extend(['%s: %s' % (k, v) for k, v in resp.getheaders()])
     dump.append('')
     if body:
         dump.extend([body, ''])
     LOG.debug(strutils.safe_encode('\n'.join(dump)))
示例#21
0
    def list(self, **kwargs):
        """Retrieve a listing of Image objects

        :param page_size: Number of images to request in each paginated request
        :returns generator over list of Images
        """
        def paginate(url):
            resp, body = self.http_client.json_request('GET', url)
            for image in body['images']:
                yield image
            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for image in paginate(next_url):
                    yield image

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        tags = filters.pop('tag', [])
        tags_url_params = []

        for tag in tags:
            if isinstance(tag, six.string_types):
                tags_url_params.append({'tag': strutils.safe_encode(tag)})

        for param, value in six.iteritems(filters):
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/images?%s' % parse.urlencode(filters)

        for param in tags_url_params:
            url = '%s&%s' % (url, parse.urlencode(param))

        for image in paginate(url):
            #NOTE(bcwaldon): remove 'self' for now until we have an elegant
            # way to pass it into the model constructor without conflict
            image.pop('self', None)
            yield self.model(**image)
示例#22
0
def print_dict(d, max_column_width=80):
    pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
    pt.align = 'l'
    pt.max_width = max_column_width
    for k, v in six.iteritems(d):
        if isinstance(v, (dict, list)):
            v = json.dumps(v)
        pt.add_row([k, v])
    print(strutils.safe_encode(pt.get_string(sortby='Property')))
示例#23
0
def print_dict(d, max_column_width=80):
    pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
    pt.align = 'l'
    pt.max_width = max_column_width
    for k, v in six.iteritems(d):
        if isinstance(v, (dict, list)):
            v = json.dumps(v)
        pt.add_row([k, v])
    print(strutils.safe_encode(pt.get_string(sortby='Property')))
示例#24
0
def exception_to_str(exc):
    try:
        error = six.text_type(exc)
    except UnicodeError:
        try:
            error = str(exc)
        except UnicodeError:
            error = ("Caught '%(exception)s' exception." %
                     {"exception": exc.__class__.__name__})
    return strutils.safe_encode(error, errors='ignore')
示例#25
0
def exception_to_str(exc):
    try:
        error = six.text_type(exc)
    except UnicodeError:
        try:
            error = str(exc)
        except UnicodeError:
            error = ("Caught '%(exception)s' exception." %
                     {"exception": exc.__class__.__name__})
    return strutils.safe_encode(error, errors='ignore')
示例#26
0
    def list(self, **kwargs):
        """Retrieve a listing of Task objects

        :param page_size: Number of tasks to request in each paginated request
        :returns generator over list of Tasks
        """
        def paginate(url):
            resp, body = self.http_client.get(url)
            for task in body['tasks']:
                yield task
            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for task in paginate(next_url):
                    yield task

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        if 'marker' in kwargs:
            filters['marker'] = kwargs['marker']

        sort_key = kwargs.get('sort_key')
        if sort_key is not None:
            if sort_key in SORT_KEY_VALUES:
                filters['sort_key'] = sort_key
            else:
                raise ValueError('sort_key must be one of the following: %s.'
                                 % ', '.join(SORT_KEY_VALUES))

        sort_dir = kwargs.get('sort_dir')
        if sort_dir is not None:
            if sort_dir in SORT_DIR_VALUES:
                filters['sort_dir'] = sort_dir
            else:
                raise ValueError('sort_dir must be one of the following: %s.'
                                 % ', '.join(SORT_DIR_VALUES))

        for param, value in filters.items():
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/tasks?%s' % six.moves.urllib.parse.urlencode(filters)
        for task in paginate(url):
            #NOTE(flwang): remove 'self' for now until we have an elegant
            # way to pass it into the model constructor without conflict
            task.pop('self', None)
            yield self.model(**task)
示例#27
0
 def log_http_response(resp, body=None):
     status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
     dump = ['\nHTTP/%.1f %s %s' % status]
     headers = resp.headers.items()
     dump.extend(['%s: %s' % safe_header(k, v) for k, v in headers])
     dump.append('')
     if body:
         body = strutils.safe_decode(body)
         dump.extend([body, ''])
     LOG.debug('\n'.join(
         [strutils.safe_encode(x, errors='ignore') for x in dump]))
示例#28
0
 def log_http_response(resp, body=None):
     status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
     dump = ['\nHTTP/%.1f %s %s' % status]
     headers = resp.headers.items()
     dump.extend(['%s: %s' % safe_header(k, v) for k, v in headers])
     dump.append('')
     if body:
         body = strutils.safe_decode(body)
         dump.extend([body, ''])
     LOG.debug('\n'.join([strutils.safe_encode(x, errors='ignore')
                          for x in dump]))
示例#29
0
    def list(self, **kwargs):
        """Retrieve a listing of Task objects

        :param page_size: Number of tasks to request in each paginated request
        :returns generator over list of Tasks
        """
        def paginate(url):
            resp, body = self.http_client.get(url)
            for task in body['tasks']:
                yield task
            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for task in paginate(next_url):
                    yield task

        filters = kwargs.get('filters', {})

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        if 'marker' in kwargs:
            filters['marker'] = kwargs['marker']

        sort_key = kwargs.get('sort_key')
        if sort_key is not None:
            if sort_key in SORT_KEY_VALUES:
                filters['sort_key'] = sort_key
            else:
                raise ValueError('sort_key must be one of the following: %s.' %
                                 ', '.join(SORT_KEY_VALUES))

        sort_dir = kwargs.get('sort_dir')
        if sort_dir is not None:
            if sort_dir in SORT_DIR_VALUES:
                filters['sort_dir'] = sort_dir
            else:
                raise ValueError('sort_dir must be one of the following: %s.' %
                                 ', '.join(SORT_DIR_VALUES))

        for param, value in filters.items():
            if isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/tasks?%s' % six.moves.urllib.parse.urlencode(filters)
        for task in paginate(url):
            #NOTE(flwang): remove 'self' for now until we have an elegant
            # way to pass it into the model constructor without conflict
            task.pop('self', None)
            yield self.model(**task)
示例#30
0
 def log_http_response(resp, body=None):
     status = (resp.version / 10.0, resp.status, resp.reason)
     dump = ["\nHTTP/%.1f %s %s" % status]
     headers = resp.getheaders()
     if "X-Auth-Token" in headers:
         headers["X-Auth-Token"] = "*" * 3
     dump.extend(["%s: %s" % (k, v) for k, v in headers])
     dump.append("")
     if body:
         body = strutils.safe_decode(body)
         dump.extend([body, ""])
     LOG.debug("\n".join([strutils.safe_encode(x) for x in dump]))
示例#31
0
 def log_http_response(resp, body=None):
     status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
     dump = ['\nHTTP/%.1f %s %s' % status]
     headers = resp.headers.items()
     if 'X-Auth-Token' in resp.headers:
         headers['X-Auth-Token'] = '*' * 3
     dump.extend(['%s: %s' % (k, v) for k, v in headers])
     dump.append('')
     if body:
         body = strutils.safe_decode(body)
         dump.extend([body, ''])
     LOG.debug('\n'.join([strutils.safe_encode(x) for x in dump]))
示例#32
0
 def log_http_response(resp, body=None):
     status = (resp.raw.version / 10.0, resp.status_code, resp.reason)
     dump = ['\nHTTP/%.1f %s %s' % status]
     headers = resp.headers.items()
     if 'X-Auth-Token' in headers:
         headers['X-Auth-Token'] = '*' * 3
     dump.extend(['%s: %s' % (k, v) for k, v in headers])
     dump.append('')
     if body:
         body = strutils.safe_decode(body)
         dump.extend([body, ''])
     LOG.debug('\n'.join([strutils.safe_encode(x) for x in dump]))
示例#33
0
def do_image_delete(gc, args):
    """Delete specified image(s)."""
    for args_image in args.images:
        image = utils.find_resource(gc.images, args_image)
        try:
            if args.verbose:
                print("Requesting image delete for %s ..." % strutils.safe_encode(args_image), end=" ")

            gc.images.delete(image)

            if args.verbose:
                print("[Done]")

        except exc.HTTPException as e:
            if args.verbose:
                print("[Fail]")
            print("%s: Unable to delete image %s" % (e, args_image))
示例#34
0
def do_image_delete(gc, args):
    """Delete specified image(s)."""
    for args_image in args.images:
        image = utils.find_resource(gc.images, args_image)
        try:
            if args.verbose:
                print 'Requesting image delete for %s ...' % \
                      strutils.safe_encode(args_image),

            gc.images.delete(image)

            if args.verbose:
                print '[Done]'

        except exc.HTTPException as e:
            if args.verbose:
                print '[Fail]'
            print '%s: Unable to delete image %s' % (e, args_image)
示例#35
0
def do_image_delete(gc, args):
    """Delete specified image(s)."""
    for args_image in args.images:
        image = utils.find_resource(gc.images, args_image)
        try:
            if args.verbose:
                print 'Requesting image delete for %s ...' % \
                      strutils.safe_encode(args_image),

            gc.images.delete(image)

            if args.verbose:
                print '[Done]'

        except exc.HTTPException as e:
            if args.verbose:
                print '[Fail]'
            print '%s: Unable to delete image %s' % (e, args_image)
示例#36
0
        def paginate(qp, seen=0, return_request_id=None):
            def filter_owner(owner, image):
                # If client side owner 'filter' is specified
                # only return images that match 'owner'.
                if owner is None:
                    # Do not filter based on owner
                    return False
                if (not hasattr(image, 'owner')) or image.owner is None:
                    # ownerless image
                    return not (owner == '')
                else:
                    return not (image.owner == owner)

            owner = qp.pop('owner', None)
            for param, value in six.iteritems(qp):
                if isinstance(value, six.string_types):
                    # Note(flaper87) Url encoding should
                    # be moved inside http utils, at least
                    # shouldn't be here.
                    #
                    # Making sure all params are str before
                    # trying to encode them
                    qp[param] = strutils.safe_encode(value)

            url = '/v1/images/detail?%s' % urlparse.urlencode(qp)
            images, resp = self._list(url, "images")

            if return_request_id is not None:
                return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None))

            for image in images:
                if filter_owner(owner, image):
                    continue
                seen += 1
                if absolute_limit is not None and seen > absolute_limit:
                    return
                yield image

            page_size = qp.get('limit')
            if (page_size and len(images) == page_size and
                    (absolute_limit is None or 0 < seen < absolute_limit)):
                qp['marker'] = image.id
                for image in paginate(qp, seen, return_request_id):
                    yield image
示例#37
0
        def paginate(qp, seen=0, return_request_id=None):
            def filter_owner(owner, image):
                # If client side owner 'filter' is specified
                # only return images that match 'owner'.
                if owner is None:
                    # Do not filter based on owner
                    return False
                if (not hasattr(image, 'owner')) or image.owner is None:
                    # ownerless image
                    return not (owner == '')
                else:
                    return not (image.owner == owner)

            owner = qp.pop('owner', None)
            for param, value in six.iteritems(qp):
                if isinstance(value, six.string_types):
                    # Note(flaper87) Url encoding should
                    # be moved inside http utils, at least
                    # shouldn't be here.
                    #
                    # Making sure all params are str before
                    # trying to encode them
                    qp[param] = strutils.safe_encode(value)

            url = '/v1/images/detail?%s' % parse.urlencode(qp)
            images, resp = self._list(url, "images")

            if return_request_id is not None:
                return_request_id.append(resp.getheader(OS_REQ_ID_HDR, None))

            for image in images:
                if filter_owner(owner, image):
                    continue
                seen += 1
                if absolute_limit is not None and seen > absolute_limit:
                    return
                yield image

            page_size = qp.get('limit')
            if (page_size and len(images) == page_size and
                    (absolute_limit is None or 0 < seen < absolute_limit)):
                qp['marker'] = image.id
                for image in paginate(qp, seen, return_request_id):
                    yield image
 def __init__(self, data):
     super(TestResponse, self).__init__()
     self._content_consumed = True
     if isinstance(data, dict):
         self.status_code = data.get('status_code', 200)
         # Fake the text attribute to streamline Response creation
         text = data.get('text', "")
         if isinstance(text, (dict, list)):
             self._content = json.dumps(text)
             default_headers = {
                 "Content-Type": "application/json",
             }
         else:
             self._content = text
             default_headers = {}
         if six.PY3 and isinstance(self._content, six.string_types):
             self._content = strutils.safe_encode(self._content)
         self.headers = data.get('headers') or default_headers
     else:
         self.status_code = data
示例#39
0
    def log_curl_request(self, method, url, kwargs):
        curl = ["curl -i -X %s" % method]

        for (key, value) in kwargs["headers"].items():
            header = "-H '%s: %s'" % (key, value)
            curl.append(header)

        conn_params_fmt = [("key_file", "--key %s"), ("cert_file", "--cert %s"), ("cacert", "--cacert %s")]
        for (key, fmt) in conn_params_fmt:
            value = self.connection_kwargs.get(key)
            if value:
                curl.append(fmt % value)

        if self.connection_kwargs.get("insecure"):
            curl.append("-k")

        if kwargs.get("body") is not None:
            curl.append("-d '%s'" % kwargs["body"])

        curl.append("%s%s" % (self.endpoint, url))
        LOG.debug(strutils.safe_encode(" ".join(curl)))
示例#40
0
def print_list(objs, fields, formatters=None, field_settings=None):
    formatters = formatters or {}
    field_settings = field_settings or {}
    pt = prettytable.PrettyTable([f for f in fields], caching=False)
    pt.align = 'l'

    for o in objs:
        row = []
        for field in fields:
            if field in field_settings:
                for setting, value in six.iteritems(field_settings[field]):
                    setting_dict = getattr(pt, setting)
                    setting_dict[field] = value

            if field in formatters:
                row.append(formatters[field](o))
            else:
                field_name = field.lower().replace(' ', '_')
                data = getattr(o, field_name, None) or ''
                row.append(data)
        pt.add_row(row)

    print(strutils.safe_encode(pt.get_string()))
示例#41
0
def print_list(objs, fields, formatters=None, field_settings=None):
    formatters = formatters or {}
    field_settings = field_settings or {}
    pt = prettytable.PrettyTable([f for f in fields], caching=False)
    pt.align = 'l'

    for o in objs:
        row = []
        for field in fields:
            if field in field_settings:
                for setting, value in six.iteritems(field_settings[field]):
                    setting_dict = getattr(pt, setting)
                    setting_dict[field] = value

            if field in formatters:
                row.append(formatters[field](o))
            else:
                field_name = field.lower().replace(' ', '_')
                data = getattr(o, field_name, None) or ''
                row.append(data)
        pt.add_row(row)

    print(strutils.safe_encode(pt.get_string()))
示例#42
0
def exit(msg=''):
    if msg:
        print >> sys.stderr, strutils.safe_encode(msg)
    sys.exit(1)
示例#43
0
def print_dict(d):
    pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
    pt.align = 'l'
    [pt.add_row(list(r)) for r in d.iteritems()]
    print strutils.safe_encode(pt.get_string(sortby='Property'))
示例#44
0
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
        kwargs['headers'].setdefault('User-Agent', USER_AGENT)
        if self.auth_token:
            kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        # Note(flaper87): Before letting headers / url fly,
        # they should be encoded otherwise httplib will
        # complain. If we decide to rely on python-request
        # this wont be necessary anymore.
        kwargs['headers'] = self.encode_headers(kwargs['headers'])

        try:
            if self.endpoint_path:
                url = '%s/%s' % (self.endpoint_path, url)
            conn_url = posixpath.normpath(url)
            # Note(flaper87): Ditto, headers / url
            # encoding to make httplib happy.
            conn_url = strutils.safe_encode(conn_url)
            if kwargs['headers'].get('Transfer-Encoding') == 'chunked':
                conn.putrequest(method, conn_url)
                for header, value in kwargs['headers'].items():
                    conn.putheader(header, value)
                conn.endheaders()
                chunk = kwargs['body'].read(CHUNKSIZE)
                # Chunk it, baby...
                while chunk:
                    conn.send('%x\r\n%s\r\n' % (len(chunk), chunk))
                    chunk = kwargs['body'].read(CHUNKSIZE)
                conn.send('0\r\n\r\n')
            else:
                conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = "Error finding address for %s: %s" % (
                self.endpoint_hostname, e)
            raise exc.InvalidEndpoint(message=message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = "Error communicating with %(endpoint)s %(e)s" % locals()
            raise exc.CommunicationError(message=message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        if resp.getheader('content-type', None) != 'application/octet-stream':
            body_str = ''.join([chunk for chunk in body_iter])
            self.log_http_response(resp, body_str)
            body_iter = StringIO.StringIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.error("Request returned failure status.")
            raise exc.from_response(resp, body_str)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp['location'], method, **kwargs)
        elif resp.status == 300:
            raise exc.from_response(resp)

        return resp, body_iter
示例#45
0
def exit(msg=''):
    if msg:
        print >> sys.stderr, strutils.safe_encode(msg)
    sys.exit(1)
示例#46
0
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {}))
        kwargs['headers'].setdefault('User-Agent', USER_AGENT)
        if self.auth_token:
            kwargs['headers'].setdefault('X-Auth-Token', self.auth_token)

        if self.identity_headers:
            for k, v in self.identity_headers.iteritems():
                kwargs['headers'].setdefault(k, v)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        # Note(flaper87): Before letting headers / url fly,
        # they should be encoded otherwise httplib will
        # complain. If we decide to rely on python-request
        # this wont be necessary anymore.
        kwargs['headers'] = self.encode_headers(kwargs['headers'])

        try:
            if self.endpoint_path:
                # NOTE(yuyangbj): this method _http_request could either be
                # called by API layer, or be called recursively with
                # redirection. For example, url would be '/v1/images/detail'
                # from API layer, but url would be 'https://example.com:92/
                # v1/images/detail'  from recursion.
                # See bug #1230032 and bug #1208618.
                if url is not None:
                    all_parts = urlparse.urlparse(url)
                    if not (all_parts.scheme and all_parts.netloc):
                        norm_parse = posixpath.normpath
                        url = norm_parse('/'.join([self.endpoint_path, url]))
                else:
                    url = self.endpoint_path

            conn_url = urlparse.urlsplit(url).geturl()
            # Note(flaper87): Ditto, headers / url
            # encoding to make httplib happy.
            conn_url = strutils.safe_encode(conn_url)
            if kwargs['headers'].get('Transfer-Encoding') == 'chunked':
                conn.putrequest(method, conn_url)
                for header, value in kwargs['headers'].items():
                    conn.putheader(header, value)
                conn.endheaders()
                chunk = kwargs['body'].read(CHUNKSIZE)
                # Chunk it, baby...
                while chunk:
                    conn.send('%x\r\n%s\r\n' % (len(chunk), chunk))
                    chunk = kwargs['body'].read(CHUNKSIZE)
                conn.send('0\r\n\r\n')
            else:
                conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = "Error finding address for %s: %s" % (
                self.endpoint_hostname, e)
            raise exc.InvalidEndpoint(message=message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = ("Error communicating with %(endpoint)s %(e)s" % {
                'endpoint': endpoint,
                'e': e
            })
            raise exc.CommunicationError(message=message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        if resp.getheader('content-type', None) != 'application/octet-stream':
            body_str = ''.join([chunk for chunk in body_iter])
            self.log_http_response(resp, body_str)
            body_iter = StringIO.StringIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.error("Request returned failure status.")
            raise exc.from_response(resp, body_str)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp.getheader('location', None), method,
                                      **kwargs)
        elif resp.status == 300:
            raise exc.from_response(resp)

        return resp, body_iter
示例#47
0
def exit(msg=''):
    if msg:
        print(strutils.safe_encode(msg), file=sys.stderr)
    sys.exit(1)
示例#48
0
def print_dict(d):
    pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
    pt.align = 'l'
    [pt.add_row(list(r)) for r in d.iteritems()]
    print(strutils.safe_encode(pt.get_string(sortby='Property')))
示例#49
0
def print_dict(d, max_column_width=80):
    pt = prettytable.PrettyTable(['Property', 'Value'], caching=False)
    pt.align = 'l'
    pt.max_width = max_column_width
    [pt.add_row(list(r)) for r in six.iteritems(d)]
    print(strutils.safe_encode(pt.get_string(sortby='Property')))
示例#50
0
    def list(self, **kwargs):
        """Retrieve a listing of Namespace objects
        :param page_size: Number of items to request in each paginated request
        :param limit: Use to request a specific page size. Expect a response
                      to a limited request to return between zero and limit
                      items.
        :param marker: Specifies the namespace of the last-seen namespace.
                       The typical pattern of limit and marker is to make an
                       initial limited request and then to use the last
                       namespace from the response as the marker parameter
                       in a subsequent limited request.
        :param sort_key: The field to sort on (for example, 'created_at')
        :param sort_dir: The direction to sort ('asc' or 'desc')
        :returns generator over list of Namespaces
        """

        ori_validate_fun = self.model.validate
        empty_fun = lambda *args, **kwargs: None

        def paginate(url):
            resp, body = self.http_client.get(url)
            for namespace in body['namespaces']:
                # NOTE(bcwaldon): remove 'self' for now until we have
                # an elegant way to pass it into the model constructor
                # without conflict.
                namespace.pop('self', None)
                yield self.model(**namespace)
                # NOTE(zhiyan): In order to resolve the performance issue
                # of JSON schema validation for image listing case, we
                # don't validate each image entry but do it only on first
                # image entry for each page.
                self.model.validate = empty_fun

            # NOTE(zhiyan); Reset validation function.
            self.model.validate = ori_validate_fun

            try:
                next_url = body['next']
            except KeyError:
                return
            else:
                for namespace in paginate(next_url):
                    yield namespace

        filters = kwargs.get('filters', {})
        filters = {} if filters is None else filters

        if not kwargs.get('page_size'):
            filters['limit'] = DEFAULT_PAGE_SIZE
        else:
            filters['limit'] = kwargs['page_size']

        if 'marker' in kwargs:
            filters['marker'] = kwargs['marker']

        sort_key = kwargs.get('sort_key')
        if sort_key is not None:
            if sort_key in SORT_KEY_VALUES:
                filters['sort_key'] = sort_key
            else:
                raise ValueError('sort_key must be one of the following: %s.'
                                 % ', '.join(SORT_KEY_VALUES))

        sort_dir = kwargs.get('sort_dir')
        if sort_dir is not None:
            if sort_dir in SORT_DIR_VALUES:
                filters['sort_dir'] = sort_dir
            else:
                raise ValueError('sort_dir must be one of the following: %s.'
                                 % ', '.join(SORT_DIR_VALUES))

        for param, value in six.iteritems(filters):
            if isinstance(value, list):
                filters[param] = strutils.safe_encode(','.join(value))
            elif isinstance(value, six.string_types):
                filters[param] = strutils.safe_encode(value)

        url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)

        for namespace in paginate(url):
            yield namespace
示例#51
0
def exit(msg=''):
    if msg:
        print(strutils.safe_encode(msg), file=sys.stderr)
    sys.exit(1)
示例#52
0
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs["headers"] = copy.deepcopy(kwargs.get("headers", {}))
        kwargs["headers"].setdefault("User-Agent", USER_AGENT)
        if self.auth_token:
            kwargs["headers"].setdefault("X-Auth-Token", self.auth_token)

        if self.identity_headers:
            for k, v in self.identity_headers.iteritems():
                kwargs["headers"].setdefault(k, v)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        # Note(flaper87): Before letting headers / url fly,
        # they should be encoded otherwise httplib will
        # complain. If we decide to rely on python-request
        # this wont be necessary anymore.
        kwargs["headers"] = self.encode_headers(kwargs["headers"])

        try:
            if self.endpoint_path:
                url = "%s/%s" % (self.endpoint_path, url)
            conn_url = posixpath.normpath(url)
            # Note(flaper87): Ditto, headers / url
            # encoding to make httplib happy.
            conn_url = strutils.safe_encode(conn_url)
            if kwargs["headers"].get("Transfer-Encoding") == "chunked":
                conn.putrequest(method, conn_url)
                for header, value in kwargs["headers"].items():
                    conn.putheader(header, value)
                conn.endheaders()
                chunk = kwargs["body"].read(CHUNKSIZE)
                # Chunk it, baby...
                while chunk:
                    conn.send("%x\r\n%s\r\n" % (len(chunk), chunk))
                    chunk = kwargs["body"].read(CHUNKSIZE)
                conn.send("0\r\n\r\n")
            else:
                conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = "Error finding address for %s: %s" % (self.endpoint_hostname, e)
            raise exc.InvalidEndpoint(message=message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = "Error communicating with %(endpoint)s %(e)s" % locals()
            raise exc.CommunicationError(message=message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        if resp.getheader("content-type", None) != "application/octet-stream":
            body_str = "".join([chunk for chunk in body_iter])
            self.log_http_response(resp, body_str)
            body_iter = StringIO.StringIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.error("Request returned failure status.")
            raise exc.from_response(resp, body_str)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp["location"], method, **kwargs)
        elif resp.status == 300:
            raise exc.from_response(resp)

        return resp, body_iter
示例#53
0
 def request_url(self, request, proxies):
     # NOTE(flaper87): Make sure the url is encoded, otherwise
     # python's standard httplib will fail with a TypeError.
     url = super(HTTPSAdapter, self).request_url(request, proxies)
     return strutils.safe_encode(url)
示例#54
0
    def _http_request(self, url, method, **kwargs):
        """Send an http request with the specified characteristics.

        Wrapper around httplib.HTTP(S)Connection.request to handle tasks such
        as setting headers and error handling.
        """
        # Copy the kwargs so we can reuse the original in case of redirects
        kwargs["headers"] = copy.deepcopy(kwargs.get("headers", {}))
        kwargs["headers"].setdefault("User-Agent", USER_AGENT)
        if self.auth_token:
            kwargs["headers"].setdefault("X-Auth-Token", self.auth_token)

        if self.identity_headers:
            for k, v in six.iteritems(self.identity_headers):
                kwargs["headers"].setdefault(k, v)

        self.log_curl_request(method, url, kwargs)
        conn = self.get_connection()

        # Note(flaper87): Before letting headers / url fly,
        # they should be encoded otherwise httplib will
        # complain. If we decide to rely on python-request
        # this wont be necessary anymore.
        kwargs["headers"] = self.encode_headers(kwargs["headers"])

        try:
            if self.endpoint_path:
                # NOTE(yuyangbj): this method _http_request could either be
                # called by API layer, or be called recursively with
                # redirection. For example, url would be '/v1/images/detail'
                # from API layer, but url would be 'https://example.com:92/
                # v1/images/detail'  from recursion.
                # See bug #1230032 and bug #1208618.
                if url is not None:
                    all_parts = parse.urlparse(url)
                    if not (all_parts.scheme and all_parts.netloc):
                        norm_parse = posixpath.normpath
                        url = norm_parse("/".join([self.endpoint_path, url]))
                else:
                    url = self.endpoint_path

            conn_url = parse.urlsplit(url).geturl()
            # Note(flaper87): Ditto, headers / url
            # encoding to make httplib happy.
            conn_url = strutils.safe_encode(conn_url)
            if kwargs["headers"].get("Transfer-Encoding") == "chunked":
                conn.putrequest(method, conn_url)
                for header, value in kwargs["headers"].items():
                    conn.putheader(header, value)
                conn.endheaders()
                chunk = kwargs["body"].read(CHUNKSIZE)
                # Chunk it, baby...
                while chunk:
                    conn.send("%x\r\n%s\r\n" % (len(chunk), chunk))
                    chunk = kwargs["body"].read(CHUNKSIZE)
                conn.send("0\r\n\r\n")
            else:
                conn.request(method, conn_url, **kwargs)
            resp = conn.getresponse()
        except socket.gaierror as e:
            message = "Error finding address for %s: %s" % (self.endpoint_hostname, e)
            raise exc.InvalidEndpoint(message=message)
        except (socket.error, socket.timeout) as e:
            endpoint = self.endpoint
            message = "Error communicating with %(endpoint)s %(e)s" % {"endpoint": endpoint, "e": e}
            raise exc.CommunicationError(message=message)

        body_iter = ResponseBodyIterator(resp)

        # Read body into string if it isn't obviously image data
        if resp.getheader("content-type", None) != "application/octet-stream":
            body_str = b"".join([to_bytes(chunk) for chunk in body_iter])
            self.log_http_response(resp, body_str)
            body_iter = six.BytesIO(body_str)
        else:
            self.log_http_response(resp)

        if 400 <= resp.status < 600:
            LOG.debug("Request returned failure status: %d" % resp.status)
            raise exc.from_response(resp, body_str)
        elif resp.status in (301, 302, 305):
            # Redirected. Reissue the request to the new location.
            return self._http_request(resp.getheader("location", None), method, **kwargs)
        elif resp.status == 300:
            raise exc.from_response(resp)

        return resp, body_iter