v2 image data upload raises exception

Bug #1147231 reported by Stuart McLaren
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Glance
Fix Released
Critical
Stuart McLaren
Grizzly
Fix Released
Critical
Stuart McLaren

Bug Description

With the latest devstack:

curl -i -k -X PUT -H 'Co -H "x-auth-token: $TOKEN"ntent-Type: application/octet-stream' --data-binary @/etc/motd http://localhost:9292/v2/images/7454cb8d-b033-4aa5-9476-0b9f0752ef75/file

HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
Content-Length: 4988
Date: Tue, 05 Mar 2013 16:24:42 GMT
Connection: close

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/eventlet/wsgi.py", line 383, in handle_one_response
    result = self.application(self.environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/opt/stack/glance/glance/common/wsgi.py", line 333, in __call__
    response = req.get_response(self.application)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py", line 349, in __call__
    return self.app(env, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/opt/stack/glance/glance/common/wsgi.py", line 333, in __call__
    response = req.get_response(self.application)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/opt/stack/glance/glance/common/wsgi.py", line 333, in __call__
    response = req.get_response(self.application)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/opt/stack/glance/glance/common/wsgi.py", line 333, in __call__
    response = req.get_response(self.application)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1296, in send
    application, catch_exc_info=False)
  File "/usr/local/lib/python2.7/dist-packages/webob/request.py", line 1260, in call_application
    app_iter = application(self.environ, start_response)
  File "/usr/lib/python2.7/dist-packages/paste/urlmap.py", line 203, in __call__
    return app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 144, in __call__
    return resp(environ, start_response)
  File "/usr/lib/python2.7/dist-packages/routes/middleware.py", line 131, in __call__
    response = self.app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 144, in __call__
    return resp(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 130, in __call__
    resp = self.call_func(req, *args, **self.kwargs)
  File "/usr/local/lib/python2.7/dist-packages/webob/dec.py", line 195, in call_func
    return self.func(req, *args, **kwargs)
  File "/opt/stack/glance/glance/common/wsgi.py", line 540, in __call__
    request, **action_args)
  File "/opt/stack/glance/glance/common/wsgi.py", line 557, in dispatch
    return method(*args, **kwargs)
  File "/opt/stack/glance/glance/common/utils.py", line 413, in wrapped
    return func(self, req, *args, **kwargs)
  File "/opt/stack/glance/glance/api/v2/image_data.py", line 51, in upload
    image.set_data(data, size)
  File "/opt/stack/glance/glance/domain.py", line 182, in set_data
    self.base.set_data(data, size)
  File "/opt/stack/glance/glance/notifier/__init__.py", line 191, in set_data
    self.image.set_data(data, size)
  File "/opt/stack/glance/glance/domain.py", line 182, in set_data
    self.base.set_data(data, size)
  File "/opt/stack/glance/glance/store/__init__.py", line 351, in set_data
    self.image.image_id, data, size)
  File "/opt/stack/glance/glance/store/__init__.py", line 292, in add_to_backend
    return store.add(image_id, data, size)
  File "/opt/stack/glance/glance/store/swift.py", line 295, in add
    content_length=image_size)
  File "/opt/stack/python-swiftclient/swiftclient/client.py", line 1099, in put_object
    orig_pos = tell()
UnsupportedOperation: seek

From debug, with the v1 api we pass a
CooperativeReader objet to swift whereas with v2 we pass a BufferedReader.

the following change:

$ git diff
diff --git a/glance/api/v2/image_data.py b/glance/api/v2/image_data.py
index 1e67382..1724a8f 100644
--- a/glance/api/v2/image_data.py
+++ b/glance/api/v2/image_data.py
@@ -48,7 +48,7 @@ class ImageDataController(object):
         image_repo = self.gateway.get_repo(req.context)
         try:
             image = image_repo.get(image_id)
- image.set_data(data, size)
+ image.set_data(utils.CooperativeReader(data), size)
             image_repo.save(image)
         except exception.Duplicate, e:
             msg = _("Unable to upload duplicate image data for image: %s")

allows the data to be uploaded ok:

$ curl -i -k -X PUT -H "x-auth-token: $TOKEN" -H 'Content-Type: application/octet-stream' --data-binary @/etc/motd http://localhost:9292/v2/images/7454cb8d-b033-4aa5-9476-0b9f0752ef75/file
HTTP/1.1 204 No Content
Content-Type: text/html; charset=UTF-8
Content-Length: 0
X-Openstack-Request-Id: req-487db605-fb43-4cbd-b9e0-f563a0d8bd56
Date: Tue, 05 Mar 2013 16:31:52 GMT

Changed in glance:
assignee: nobody → Stuart McLaren (stuart-mclaren)
Revision history for this message
Mark Washenberger (markwash) wrote :

Proposed diff looks like a good fix.

Changed in glance:
status: New → Triaged
importance: Undecided → Critical
milestone: none → grizzly-rc1
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to glance (master)

Fix proposed to branch: master
Review: https://review.openstack.org/23683

Changed in glance:
status: Triaged → In Progress
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to glance (master)

Reviewed: https://review.openstack.org/23683
Committed: http://github.com/openstack/glance/commit/db8b10a796be9e6e0951ad231b3f857a2486c5a4
Submitter: Jenkins
Branch: master

commit db8b10a796be9e6e0951ad231b3f857a2486c5a4
Author: Stuart McLaren <email address hidden>
Date: Wed Mar 6 10:59:53 2013 +0000

    Fix v2 data upload to swift

    An upload of image data via the v2 api when using a swift backend would
    stacktrace with 'UnsupportedOperation: seek'.

    Wrap the data in a CooperativeReader to both 1) fix this issue and 2) reap
    the multi-threaded 'sheduling fairness' benefit of the CooperativeReader.

    Fix for bug 1147231.

    Change-Id: I604c67d2d6ecd77a12e11b2f641edb4095c4bb60

Changed in glance:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in glance:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.