Merge "Handle create/update of images with unknown size"
This commit is contained in:
@@ -143,6 +143,18 @@ class HTTPClient(object):
|
||||
|
||||
try:
|
||||
conn_url = os.path.normpath('%s/%s' % (self.endpoint_path, 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:
|
||||
@@ -198,6 +210,12 @@ class HTTPClient(object):
|
||||
kwargs.setdefault('headers', {})
|
||||
kwargs['headers'].setdefault('Content-Type',
|
||||
'application/octet-stream')
|
||||
if 'body' in kwargs:
|
||||
if (hasattr(kwargs['body'], 'read')
|
||||
and method.lower() in ('post', 'put')):
|
||||
# We use 'Transfer-Encoding: chunked' because
|
||||
# body size may not always be known in advance.
|
||||
kwargs['headers']['Transfer-Encoding'] = 'chunked'
|
||||
return self._http_request(url, method, **kwargs)
|
||||
|
||||
|
||||
|
@@ -177,10 +177,15 @@ class ImageManager(base.Manager):
|
||||
# Illegal seek. This means the user is trying
|
||||
# to pipe image data to the client, e.g.
|
||||
# echo testdata | bin/glance add blah..., or
|
||||
# that stdin is empty
|
||||
return 0
|
||||
# that stdin is empty, or that a file-like
|
||||
# object which doesn't support 'seek/tell' has
|
||||
# been supplied.
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
# Cannot determine size of input image
|
||||
return None
|
||||
|
||||
def create(self, **kwargs):
|
||||
"""Create an image
|
||||
@@ -190,10 +195,8 @@ class ImageManager(base.Manager):
|
||||
image_data = kwargs.pop('data', None)
|
||||
if image_data is not None:
|
||||
image_size = self._get_file_size(image_data)
|
||||
if image_size != 0:
|
||||
if image_size is not None:
|
||||
kwargs.setdefault('size', image_size)
|
||||
else:
|
||||
image_data = None
|
||||
|
||||
fields = {}
|
||||
for field in kwargs:
|
||||
@@ -218,16 +221,13 @@ class ImageManager(base.Manager):
|
||||
|
||||
TODO(bcwaldon): document accepted params
|
||||
"""
|
||||
hdrs = {}
|
||||
image_data = kwargs.pop('data', None)
|
||||
if image_data is not None:
|
||||
image_size = self._get_file_size(image_data)
|
||||
if image_size != 0:
|
||||
if image_size is not None:
|
||||
kwargs.setdefault('size', image_size)
|
||||
hdrs['Content-Length'] = image_size
|
||||
else:
|
||||
image_data = None
|
||||
|
||||
hdrs = {}
|
||||
try:
|
||||
purge_props = 'true' if kwargs.pop('purge_props') else 'false'
|
||||
except KeyError:
|
||||
|
@@ -81,9 +81,20 @@ def _set_data_field(fields, args):
|
||||
if args.file:
|
||||
fields['data'] = open(args.file, 'rb')
|
||||
else:
|
||||
# We distinguish between cases where image data is pipelined:
|
||||
# (1) glance ... < /tmp/file or cat /tmp/file | glance ...
|
||||
# and cases where no image data is provided:
|
||||
# (2) glance ...
|
||||
if (sys.stdin.isatty() is not True):
|
||||
# Our input is from stdin, and we are part of
|
||||
# a pipeline, so data may be present. (We are of
|
||||
# type (1) above.)
|
||||
if msvcrt:
|
||||
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
|
||||
fields['data'] = sys.stdin
|
||||
else:
|
||||
# We are of type (2) above, no image data supplied
|
||||
fields['data'] = None
|
||||
|
||||
|
||||
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.')
|
||||
|
@@ -390,7 +390,7 @@ class ImageManagerTest(unittest.TestCase):
|
||||
def test_update_with_data(self):
|
||||
image_data = StringIO.StringIO('XXX')
|
||||
self.mgr.update('1', data=image_data)
|
||||
expect_headers = {'x-image-meta-size': '3', 'Content-Length': 3}
|
||||
expect_headers = {'x-image-meta-size': '3'}
|
||||
expect = [('PUT', '/v1/images/1', expect_headers, image_data)]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
|
||||
|
Reference in New Issue
Block a user