Merge "Wrap image data in iterator"
This commit is contained in:
@@ -5,6 +5,7 @@ OpenStack Client interface. Handles the REST calls and responses.
|
|||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import StringIO
|
||||||
import urlparse
|
import urlparse
|
||||||
|
|
||||||
import httplib2
|
import httplib2
|
||||||
@@ -25,6 +26,7 @@ from glanceclient import exc
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
USER_AGENT = 'python-glanceclient'
|
USER_AGENT = 'python-glanceclient'
|
||||||
|
CHUNKSIZE = 1024 * 64 # 64kB
|
||||||
|
|
||||||
|
|
||||||
class HTTPClient(httplib2.Http):
|
class HTTPClient(httplib2.Http):
|
||||||
@@ -88,7 +90,12 @@ class HTTPClient(httplib2.Http):
|
|||||||
# Redirected. Reissue the request to the new location.
|
# Redirected. Reissue the request to the new location.
|
||||||
return self._http_request(resp['location'], method, **kwargs)
|
return self._http_request(resp['location'], method, **kwargs)
|
||||||
|
|
||||||
return resp, body
|
#NOTE(bcwaldon): body has been loaded to a string at this point,
|
||||||
|
# but we want to move to a world where it can be read from a
|
||||||
|
# socket-level cache. This is here until we can do that.
|
||||||
|
body_iter = ResponseBodyIterator(StringIO.StringIO(body))
|
||||||
|
|
||||||
|
return resp, body_iter
|
||||||
|
|
||||||
def json_request(self, method, url, **kwargs):
|
def json_request(self, method, url, **kwargs):
|
||||||
kwargs.setdefault('headers', {})
|
kwargs.setdefault('headers', {})
|
||||||
@@ -97,7 +104,8 @@ class HTTPClient(httplib2.Http):
|
|||||||
if 'body' in kwargs:
|
if 'body' in kwargs:
|
||||||
kwargs['body'] = json.dumps(kwargs['body'])
|
kwargs['body'] = json.dumps(kwargs['body'])
|
||||||
|
|
||||||
resp, body = self._http_request(url, method, **kwargs)
|
resp, body_iter = self._http_request(url, method, **kwargs)
|
||||||
|
body = ''.join([chunk for chunk in body_iter])
|
||||||
|
|
||||||
if body:
|
if body:
|
||||||
try:
|
try:
|
||||||
@@ -115,3 +123,21 @@ class HTTPClient(httplib2.Http):
|
|||||||
kwargs['headers'].setdefault('Content-Type',
|
kwargs['headers'].setdefault('Content-Type',
|
||||||
'application/octet-stream')
|
'application/octet-stream')
|
||||||
return self._http_request(url, method, **kwargs)
|
return self._http_request(url, method, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ResponseBodyIterator(object):
|
||||||
|
"""A class that acts as an iterator over an HTTP response."""
|
||||||
|
|
||||||
|
def __init__(self, resp):
|
||||||
|
self.resp = resp
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
while True:
|
||||||
|
yield self.next()
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
chunk = self.resp.read(CHUNKSIZE)
|
||||||
|
if chunk:
|
||||||
|
return chunk
|
||||||
|
else:
|
||||||
|
raise StopIteration()
|
||||||
|
@@ -159,8 +159,9 @@ class ImageManager(base.Manager):
|
|||||||
if copy_from is not None:
|
if copy_from is not None:
|
||||||
hdrs['x-glance-api-copy-from'] = copy_from
|
hdrs['x-glance-api-copy-from'] = copy_from
|
||||||
|
|
||||||
resp, body = self.api.raw_request(
|
resp, body_iter = self.api.raw_request(
|
||||||
'POST', '/v1/images', headers=hdrs, body=image_data)
|
'POST', '/v1/images', headers=hdrs, body=image_data)
|
||||||
|
body = ''.join([c for c in body_iter])
|
||||||
return Image(self, json.loads(body)['image'])
|
return Image(self, json.loads(body)['image'])
|
||||||
|
|
||||||
def update(self, image, **kwargs):
|
def update(self, image, **kwargs):
|
||||||
@@ -199,6 +200,7 @@ class ImageManager(base.Manager):
|
|||||||
hdrs['x-glance-api-copy-from'] = copy_from
|
hdrs['x-glance-api-copy-from'] = copy_from
|
||||||
|
|
||||||
url = '/v1/images/%s' % base.getid(image)
|
url = '/v1/images/%s' % base.getid(image)
|
||||||
resp, body = self.api.raw_request(
|
resp, body_iter = self.api.raw_request(
|
||||||
'PUT', url, headers=hdrs, body=image_data)
|
'PUT', url, headers=hdrs, body=image_data)
|
||||||
|
body = ''.join([c for c in body_iter])
|
||||||
return Image(self, json.loads(body)['image'])
|
return Image(self, json.loads(body)['image'])
|
||||||
|
@@ -131,7 +131,7 @@ class ImageManagerTest(unittest.TestCase):
|
|||||||
self.assertEqual(image.name, 'image-1')
|
self.assertEqual(image.name, 'image-1')
|
||||||
|
|
||||||
def test_data(self):
|
def test_data(self):
|
||||||
data = self.mgr.data('1')
|
data = ''.join([b for b in self.mgr.data('1')])
|
||||||
expect = [('GET', '/v1/images/1', {}, None)]
|
expect = [('GET', '/v1/images/1', {}, None)]
|
||||||
self.assertEqual(self.api.calls, expect)
|
self.assertEqual(self.api.calls, expect)
|
||||||
self.assertEqual(data, 'XXX')
|
self.assertEqual(data, 'XXX')
|
||||||
@@ -256,7 +256,7 @@ class ImageTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_data(self):
|
def test_data(self):
|
||||||
image = self.mgr.get('1')
|
image = self.mgr.get('1')
|
||||||
data = image.data()
|
data = ''.join([b for b in image.data()])
|
||||||
expect = [
|
expect = [
|
||||||
('HEAD', '/v1/images/1', {}, None),
|
('HEAD', '/v1/images/1', {}, None),
|
||||||
('GET', '/v1/images/1', {}, None),
|
('GET', '/v1/images/1', {}, None),
|
||||||
|
Reference in New Issue
Block a user