supporting changes-since
This commit is contained in:
@@ -107,6 +107,14 @@ class Controller(object):
|
|||||||
LOG.error(reason)
|
LOG.error(reason)
|
||||||
raise exception.InvalidInput(reason=reason)
|
raise exception.InvalidInput(reason=reason)
|
||||||
|
|
||||||
|
if 'changes-since' in search_opts:
|
||||||
|
try:
|
||||||
|
parsed = utils.parse_isotime(search_opts['changes-since'])
|
||||||
|
except ValueError:
|
||||||
|
msg = _('Invalid changes-since value')
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
search_opts['changes-since'] = parsed
|
||||||
|
|
||||||
# By default, compute's get_all() will return deleted instances.
|
# By default, compute's get_all() will return deleted instances.
|
||||||
# If an admin hasn't specified a 'deleted' search option, we need
|
# If an admin hasn't specified a 'deleted' search option, we need
|
||||||
# to filter out deleted instances by setting the filter ourselves.
|
# to filter out deleted instances by setting the filter ourselves.
|
||||||
@@ -114,23 +122,17 @@ class Controller(object):
|
|||||||
# should return recently deleted images according to the API spec.
|
# should return recently deleted images according to the API spec.
|
||||||
|
|
||||||
if 'deleted' not in search_opts:
|
if 'deleted' not in search_opts:
|
||||||
# Admin hasn't specified deleted filter
|
|
||||||
if 'changes-since' not in search_opts:
|
if 'changes-since' not in search_opts:
|
||||||
# No 'changes-since', so we need to find non-deleted servers
|
# No 'changes-since', so we only want non-deleted servers
|
||||||
search_opts['deleted'] = False
|
search_opts['deleted'] = False
|
||||||
else:
|
|
||||||
# This is the default, but just in case..
|
|
||||||
search_opts['deleted'] = True
|
|
||||||
|
|
||||||
instance_list = self.compute_api.get_all(
|
instance_list = self.compute_api.get_all(context,
|
||||||
context, search_opts=search_opts)
|
search_opts=search_opts)
|
||||||
|
|
||||||
# FIXME(comstud): 'changes-since' is not fully implemented. Where
|
|
||||||
# should this be filtered?
|
|
||||||
|
|
||||||
limited_list = self._limit_items(instance_list, req)
|
limited_list = self._limit_items(instance_list, req)
|
||||||
servers = [self._build_view(req, inst, is_detail)['server']
|
servers = [self._build_view(req, inst, is_detail)['server']
|
||||||
for inst in limited_list]
|
for inst in limited_list]
|
||||||
|
|
||||||
return dict(servers=servers)
|
return dict(servers=servers)
|
||||||
|
|
||||||
@scheduler_api.redirect_handler
|
@scheduler_api.redirect_handler
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ from sqlalchemy.exc import IntegrityError
|
|||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
from sqlalchemy.orm import joinedload_all
|
from sqlalchemy.orm import joinedload_all
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
|
from sqlalchemy.sql.expression import desc
|
||||||
from sqlalchemy.sql.expression import literal_column
|
from sqlalchemy.sql.expression import literal_column
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
@@ -1250,12 +1251,17 @@ def instance_get_all_by_filters(context, filters):
|
|||||||
options(joinedload_all('fixed_ips.network')).\
|
options(joinedload_all('fixed_ips.network')).\
|
||||||
options(joinedload('metadata')).\
|
options(joinedload('metadata')).\
|
||||||
options(joinedload('instance_type')).\
|
options(joinedload('instance_type')).\
|
||||||
filter_by(deleted=can_read_deleted(context))
|
order_by(desc(models.Instance.updated_at))
|
||||||
|
|
||||||
# Make a copy of the filters dictionary to use going forward, as we'll
|
# Make a copy of the filters dictionary to use going forward, as we'll
|
||||||
# be modifying it and we shouldn't affect the caller's use of it.
|
# be modifying it and we shouldn't affect the caller's use of it.
|
||||||
filters = filters.copy()
|
filters = filters.copy()
|
||||||
|
|
||||||
|
if 'changes-since' in filters:
|
||||||
|
changes_since = filters['changes-since']
|
||||||
|
query_prefix = query_prefix.\
|
||||||
|
filter(models.Instance.updated_at > changes_since)
|
||||||
|
|
||||||
if not context.is_admin:
|
if not context.is_admin:
|
||||||
# If we're not admin context, add appropriate filter..
|
# If we're not admin context, add appropriate filter..
|
||||||
if context.project_id:
|
if context.project_id:
|
||||||
@@ -1277,9 +1283,7 @@ def instance_get_all_by_filters(context, filters):
|
|||||||
query_prefix = _exact_match_filter(query_prefix, filter_name,
|
query_prefix = _exact_match_filter(query_prefix, filter_name,
|
||||||
filters.pop(filter_name))
|
filters.pop(filter_name))
|
||||||
|
|
||||||
instances = query_prefix.\
|
instances = query_prefix.all()
|
||||||
filter_by(deleted=can_read_deleted(context)).\
|
|
||||||
all()
|
|
||||||
|
|
||||||
if not instances:
|
if not instances:
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1257,6 +1257,30 @@ class ServersTest(test.TestCase):
|
|||||||
self.assertEqual(len(servers), 1)
|
self.assertEqual(len(servers), 1)
|
||||||
self.assertEqual(servers[0]['id'], 100)
|
self.assertEqual(servers[0]['id'], 100)
|
||||||
|
|
||||||
|
def test_get_servers_allows_changes_since_v1_1(self):
|
||||||
|
def fake_get_all(compute_self, context, search_opts=None):
|
||||||
|
self.assertNotEqual(search_opts, None)
|
||||||
|
self.assertTrue('changes-since' in search_opts)
|
||||||
|
changes_since = datetime.datetime(2011, 1, 24, 17, 8, 1)
|
||||||
|
self.assertEqual(search_opts['changes-since'], changes_since)
|
||||||
|
return [stub_instance(100)]
|
||||||
|
|
||||||
|
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
|
||||||
|
|
||||||
|
params = 'changes-since=2011-01-24T17:08:01Z'
|
||||||
|
req = webob.Request.blank('/v1.1/fake/servers?%s' % params)
|
||||||
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(res.status_int, 200)
|
||||||
|
servers = json.loads(res.body)['servers']
|
||||||
|
self.assertEqual(len(servers), 1)
|
||||||
|
self.assertEqual(servers[0]['id'], 100)
|
||||||
|
|
||||||
|
def test_get_servers_allows_changes_since_bad_value_v1_1(self):
|
||||||
|
params = 'changes-since=asdf'
|
||||||
|
req = webob.Request.blank('/v1.1/fake/servers?%s' % params)
|
||||||
|
res = req.get_response(fakes.wsgi_app())
|
||||||
|
self.assertEqual(res.status_int, 400)
|
||||||
|
|
||||||
def test_get_servers_unknown_or_admin_options1(self):
|
def test_get_servers_unknown_or_admin_options1(self):
|
||||||
"""Test getting servers by admin-only or unknown options.
|
"""Test getting servers by admin-only or unknown options.
|
||||||
This tests when admin_api is off. Make sure the admin and
|
This tests when admin_api is off. Make sure the admin and
|
||||||
|
|||||||
Reference in New Issue
Block a user