Merge "Handle create/update of images with unknown size"

This commit is contained in:
Jenkins
2012-10-13 02:17:31 +00:00
committed by Gerrit Code Review
4 changed files with 44 additions and 15 deletions

View File

@@ -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)

View File

@@ -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:

View File

@@ -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.')

View File

@@ -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)