when "v2/images" API with "changes-since" option is requested, Glance API Server returns 500 code

Bug #1273975 reported by Noboru Arai
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Glance
Fix Released
Medium
Henrique Truta

Bug Description

environment:
    Openstack by deployed devstack

reproduce:
  1. request "v2/images" with "chnages-since" to Glance API Server.

  2. return 500 error code

expect result:
   return list filtered out by "changes-since" option

cause:
   in "_make_conditions_from_filters" method of glance/db/sqlalchemy/api.py,
 "timeutils.normalize_time" function is used.

Although the argument of "timeutils.normalize_time" have to have datetime,
unicode object is set.

syslog:

2014-01-29 15:21:16.444 24293 INFO glance.wsgi.server [561294e8-8719-4dd1-84d3-c070f9bf421d 2fdafc2b68a54ec19343c5eb45d2b65b ac9666adfda644f181d8005053e27b73] Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/eventlet/wsgi.py", line 389, 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 372, 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 581, 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 372, 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 372, 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 372, 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 604, in __call__
    request, **action_args)
  File "/opt/stack/glance/glance/common/wsgi.py", line 623, in dispatch
    return method(*args, **kwargs)
  File "/opt/stack/glance/glance/api/v2/images.py", line 91, in index
    member_status=member_status)
  File "/opt/stack/glance/glance/api/authorization.py", line 90, in list
    images = self.image_repo.list(*args, **kwargs)
  File "/opt/stack/glance/glance/domain/proxy.py", line 56, in list
    items = self.base.list(*args, **kwargs)
  File "/opt/stack/glance/glance/api/policy.py", line 182, in list
    return super(ImageRepoProxy, self).list(*args, **kwargs)
  File "/opt/stack/glance/glance/domain/proxy.py", line 56, in list
    items = self.base.list(*args, **kwargs)
  File "/opt/stack/glance/glance/domain/proxy.py", line 56, in list
    items = self.base.list(*args, **kwargs)
  File "/opt/stack/glance/glance/domain/proxy.py", line 56, in list
    items = self.base.list(*args, **kwargs)
  File "/opt/stack/glance/glance/db/__init__.py", line 74, in list
    member_status=member_status)
  File "/opt/stack/glance/glance/db/sqlalchemy/api.py", line 486, in image_get_all
    _make_conditions_from_filters(filters, is_public)
  File "/opt/stack/glance/glance/db/sqlalchemy/api.py", line 359, in _make_conditions_from_filters
    changes_since = timeutils.normalize_time(filters.pop('changes-since'))
  File "/opt/stack/glance/glance/openstack/common/timeutils.py", line 70, in normalize_time
    offset = timestamp.utcoffset()
AttributeError: 'unicode' object has no attribute 'utcoffset'

2014-01-29 15:21:16.445 24293 INFO glance.wsgi.server [561294e8-8719-4dd1-84d3-c070f9bf421d 2fdafc2b68a54ec19343c5eb45d2b65b ac9666adfda644f181d8005053e27b73] 192.168.0.10 - - [29/Jan/2014 15:21:16] "GET /v2/images?changes-since=20131010T10:10:10 HTTP/1.1" 500 139 23.403289

remark)
   in pdb debug, when the value of "changes-since" is changed, it works correctly.

   pdb
  -----------------------------------------------------------------------
  ll__ /usr/lib/python2.7/dist-packages/routes/middleware.py:103
  > /opt/stack/glance/glance/api/v2/images.py(78)index()
  -> if filters is None:
  (Pdb) import datetime
  (Pdb) filters
  MultiDict([(u'changes-since', u'20131010T10:10:10')])
  (Pdb) filters[changes-since]=datetime.datetime(2013,10,10,10,10,10)
  *** NameError: name 'changes' is not defined
  (Pdb) filters["changes-since"]=datetime.datetime(2013,10,10,10,10,10)
  (Pdb) filters
   MultiDict([('changes-since', datetime.datetime(2013, 10, 10, 10, 10, 10))])
   (Pdb) c
   > /opt/stack/glance/glance/db/sqlalchemy/api.py(359)_make_conditions_from_filters()
   -> changes_since = timeutils.normalize_time(filters.pop('changes-since'))
   (Pdb) c
   2014-01-29 15:29:42.317 24293 INFO glance.wsgi.server [27c9a666-0136-467d-8e18-6f9a78afb8b0 2fdafc2b68a54ec19343c5eb45d2b65b ac9666adfda644f181d8005053e27b73] 192.168.0.10 - - [29/Jan/2014 15:29:42] "GET /v2/images?changes-since=20131010T10:10:10 HTTP/1.1" 200 2013 87.969698

Noboru Arai (arai-h)
Changed in glance:
assignee: nobody → Noboru Arai (arai-h)
status: New → In Progress
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/69819

Zhi Yan Liu (lzy-dev)
Changed in glance:
importance: Undecided → Medium
Revision history for this message
Mark Washenberger (markwash) wrote :

I think the right response when changes-since is used is a 400 Bad Request error. We did not intend to add support for changes-since and the fact that it gives a 500 error is just a carry-over from reusing the db api between v1 and v2.

Changed in glance:
assignee: Noboru Arai (arai-h) → Henrique Truta (henrique-4)
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

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

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to glance (master)

Reviewed: https://review.openstack.org/107106
Committed: https://git.openstack.org/cgit/openstack/glance/commit/?id=82fd29ad0f58d0669e97377984442eb4df524bfe
Submitter: Jenkins
Branch: master

commit 82fd29ad0f58d0669e97377984442eb4df524bfe
Author: henriquetruta <email address hidden>
Date: Tue Jul 15 13:32:41 2014 -0300

    Raising 400 Bad Request when using "changes-since" filter on v2

    In Glance API V2, currently, the user gets a 500 error when tries
    to use the "changes-since" filter.This filter, which was available
    on API v1 is no longer available on V2.

    This patch returns to the user a 400 Bad Request with a proper message,
    instead of a generic 500 Internal Server Error.

    Change-Id: Icece859a7f12f6f4aa1f7bb945134a935048b315
    Closes-bug: 1273975

Changed in glance:
status: In Progress → Fix Committed
Changed in glance:
milestone: none → juno-2
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in glance:
milestone: juno-2 → 2014.2
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.