summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/objects/base.py2
-rw-r--r--nova/objects/instance.py1
-rw-r--r--nova/tests/conductor/test_conductor.py114
-rw-r--r--nova/tests/db/test_db_api.py78
-rw-r--r--nova/tests/objects/test_instance.py1
5 files changed, 84 insertions, 112 deletions
diff --git a/nova/objects/base.py b/nova/objects/base.py
index 2e0797477..ec1ada6aa 100644
--- a/nova/objects/base.py
+++ b/nova/objects/base.py
@@ -311,7 +311,7 @@ class NovaObject(object):
raise NotImplementedError('Cannot save anything in the base class')
def obj_what_changed(self):
- """Returns a list of fields that have been modified."""
+ """Returns a set of fields that have been modified."""
return self._changed_fields
def obj_reset_changes(self, fields=None):
diff --git a/nova/objects/instance.py b/nova/objects/instance.py
index aec6fe968..cd08c4c4f 100644
--- a/nova/objects/instance.py
+++ b/nova/objects/instance.py
@@ -256,6 +256,7 @@ class Instance(base.NovaObject):
if (hasattr(self, base.get_attrname(field)) and
self[field] != current[field]):
self[field] = current[field]
+ self.obj_reset_changes()
def obj_load_attr(self, attrname):
extra = []
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
index 195890b75..7a33cfbb9 100644
--- a/nova/tests/conductor/test_conductor.py
+++ b/nova/tests/conductor/test_conductor.py
@@ -14,8 +14,6 @@
"""Tests for the conductor service."""
-import datetime
-
import mox
from nova.api.ec2 import ec2utils
@@ -376,99 +374,33 @@ class _BaseTestCase(object):
self.assertEqual(result, 'fake-usage')
def test_vol_usage_update(self):
- # the vol_usage_update method sends the volume usage notifications
- # as well as updating the database
- now = datetime.datetime(1, 1, 1)
- self.mox.StubOutWithMock(timeutils, 'utcnow')
- # nova.context
- timeutils.utcnow().AndReturn(0)
- # vol_usage_update 1
- timeutils.utcnow().AndReturn(now)
- # openstack.common.notifier
- timeutils.utcnow().AndReturn(now)
- self.mox.ReplayAll()
-
- inst = self._create_fake_instance({
- 'project_id': 'fake-project_id',
- 'user_id': 'fake-user_id',
- })
-
- self.conductor.vol_usage_update(self.context, 'fake-vol',
- 22, 33, 44, 55, inst,
- '2013-06-05T16:53:27.0', False)
-
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 1)
- msg = test_notifier.NOTIFICATIONS[0]
- payload = msg['payload']
- self.assertEquals(payload['instance_id'], inst['uuid'])
- self.assertEquals(payload['user_id'], 'fake-user_id')
- self.assertEquals(payload['tenant_id'], 'fake-project_id')
- self.assertEquals(payload['reads'], 22)
- self.assertEquals(payload['read_bytes'], 33)
- self.assertEquals(payload['writes'], 44)
- self.assertEquals(payload['write_bytes'], 55)
- self.assertEquals(payload['availability_zone'], 'fake-az')
- self.assertEquals(payload['last_refreshed'], '0001-01-01 00:00:00')
-
- # We need to unset and verify that we call the timutils.utcnow method
- # correctly now, as this method gets called as part of the setup
- # for the ConductorAPITestCase testcase.
- self.mox.UnsetStubs()
- self.mox.VerifyAll()
-
- def test_vol_usage_update_again(self):
- # Test updating the volume usage a second time and make sure that
- # the database queries to update and generate the volume usage
- # event payload continue to work
- now = datetime.datetime(1, 1, 1, 0, 0, 0)
- self.mox.StubOutWithMock(timeutils, 'utcnow')
- # nova.context
- timeutils.utcnow().AndReturn(0)
-
- # vol_usage_update call
- timeutils.utcnow().AndReturn(now)
- # openstack.common.notifier
- timeutils.utcnow().AndReturn(now)
-
- now2 = datetime.datetime(1, 1, 1, 0, 1, 0)
- # vol_usage_update second call
- timeutils.utcnow().AndReturn(now2)
- # openstack.common.notifier
- timeutils.utcnow().AndReturn(now2)
+ self.mox.StubOutWithMock(db, 'vol_usage_update')
+ self.mox.StubOutWithMock(test_notifier, 'notify')
+ self.mox.StubOutWithMock(compute_utils, 'usage_volume_info')
+
+ fake_inst = {'uuid': 'fake-uuid',
+ 'project_id': 'fake-project',
+ 'user_id': 'fake-user',
+ 'availability_zone': 'fake-az',
+ }
+
+ db.vol_usage_update(self.context, 'fake-vol', 22, 33, 44, 55,
+ fake_inst['uuid'],
+ fake_inst['project_id'],
+ fake_inst['user_id'],
+ fake_inst['availability_zone'],
+ False, mox.IgnoreArg()).AndReturn('fake-usage')
+ compute_utils.usage_volume_info('fake-usage').AndReturn('fake-info')
+ notifier_api.notify(self.context,
+ 'conductor.%s' % self.conductor_manager.host,
+ 'volume.usage', notifier_api.INFO,
+ 'fake-info')
self.mox.ReplayAll()
- inst = self._create_fake_instance({
- 'project_id': 'fake-project_id',
- 'user_id': 'fake-user_id',
- })
-
- self.conductor.vol_usage_update(self.context, 'fake-vol',
- 22, 33, 44, 55, inst,
- '2013-06-05T16:53:27.0', False)
-
self.conductor.vol_usage_update(self.context, 'fake-vol',
- 122, 133, 144, 155, inst,
- '2013-06-05T16:53:27.0', False)
-
- self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
- msg = test_notifier.NOTIFICATIONS[1]
- payload = msg['payload']
- self.assertEquals(payload['instance_id'], inst['uuid'])
- self.assertEquals(payload['user_id'], 'fake-user_id')
- self.assertEquals(payload['tenant_id'], 'fake-project_id')
- self.assertEquals(payload['reads'], 122)
- self.assertEquals(payload['read_bytes'], 133)
- self.assertEquals(payload['writes'], 144)
- self.assertEquals(payload['write_bytes'], 155)
- self.assertEquals(payload['availability_zone'], 'fake-az')
- self.assertEquals(payload['last_refreshed'], '0001-01-01 00:01:00')
-
- # We need to unset and verify that we call the timutils.utcnow method
- # correctly now, as this method gets called as part of the setup
- # for the ConductorAPITestCase testcase.
- self.mox.UnsetStubs()
- self.mox.VerifyAll()
+ 22, 33, 44, 55, fake_inst,
+ 'fake-update-time', False)
def test_compute_node_create(self):
self.mox.StubOutWithMock(db, 'compute_node_create')
diff --git a/nova/tests/db/test_db_api.py b/nova/tests/db/test_db_api.py
index df5561ae0..7f68dfbc4 100644
--- a/nova/tests/db/test_db_api.py
+++ b/nova/tests/db/test_db_api.py
@@ -151,26 +151,6 @@ class DbApiTestCase(DbTestCase):
self.flags(osapi_compute_unique_server_name_scope=None)
- def test_instance_metadata_get_all_query(self):
- self.create_instance_with_args(metadata={'foo': 'bar'})
- self.create_instance_with_args(metadata={'baz': 'quux'})
-
- result = db.instance_metadata_get_all(self.context, [])
- self.assertEqual(2, len(result))
-
- result = db.instance_metadata_get_all(self.context,
- [{'key': 'foo'}])
- self.assertEqual(1, len(result))
-
- result = db.instance_metadata_get_all(self.context,
- [{'value': 'quux'}])
- self.assertEqual(1, len(result))
-
- result = db.instance_metadata_get_all(self.context,
- [{'value': 'quux'},
- {'key': 'foo'}])
- self.assertEqual(2, len(result))
-
def test_ec2_ids_not_found_are_printable(self):
def check_exc_format(method):
try:
@@ -1619,6 +1599,64 @@ class SecurityGroupTestCase(test.TestCase, ModelsObjectComparatorMixin):
'default'))
+class InstanceMetadataTestCase(test.TestCase):
+
+ """Tests for db.api.instance_metadata_* methods."""
+
+ def setUp(self):
+ super(InstanceMetadataTestCase, self).setUp()
+ self.ctxt = context.get_admin_context()
+
+ def test_instance_metadata_get(self):
+ instance = db.instance_create(self.ctxt, {'metadata':
+ {'key': 'value'}})
+ self.assertEqual({'key': 'value'}, db.instance_metadata_get(
+ self.ctxt, instance['uuid']))
+
+ def test_instance_metadata_get_all(self):
+ instances = []
+ expected = []
+ for i in range(2):
+ instances.append(db.instance_create(self.ctxt,
+ {'metadata': {'key%d' % i: 'value%d' % i}}))
+ expected.append({'instance_id': instances[i]['uuid'],
+ 'key': 'key%d' % i, 'value': 'value%d' % i})
+ self.assertEqual(expected, db.instance_metadata_get_all(self.ctxt, []))
+ self.assertEqual(expected[:1], db.instance_metadata_get_all(self.ctxt,
+ [{'key': 'key0'}]))
+ self.assertEqual(expected[1:2], db.instance_metadata_get_all(self.ctxt,
+ [{'value': 'value1'}]))
+ self.assertEqual(expected[:2], db.instance_metadata_get_all(self.ctxt,
+ [{'value': 'value1'},
+ {'key': 'key0'}]))
+
+ def test_instance_metadata_delete(self):
+ instance = db.instance_create(self.ctxt,
+ {'metadata': {'key': 'val',
+ 'key1': 'val1'}})
+ db.instance_metadata_delete(self.ctxt, instance['uuid'], 'key1')
+ self.assertEqual({'key': 'val'}, db.instance_metadata_get(
+ self.ctxt, instance['uuid']))
+
+ def test_instance_metadata_update(self):
+ instance = db.instance_create(self.ctxt, {'host': 'h1',
+ 'project_id': 'p1', 'metadata': {'key': 'value'}})
+
+ # This should add new key/value pair
+ metadata = db.instance_metadata_update(
+ self.ctxt, instance['uuid'],
+ {'new_key': 'new_value'}, False)
+ metadata = db.instance_metadata_get(self.ctxt, instance['uuid'])
+ self.assertEqual(metadata, {'key': 'value', 'new_key': 'new_value'})
+
+ # This should leave only one key/value pair
+ metadata = db.instance_metadata_update(
+ self.ctxt, instance['uuid'],
+ {'new_key': 'new_value'}, True)
+ metadata = db.instance_metadata_get(self.ctxt, instance['uuid'])
+ self.assertEqual(metadata, {'new_key': 'new_value'})
+
+
class ServiceTestCase(test.TestCase, ModelsObjectComparatorMixin):
def setUp(self):
super(ServiceTestCase, self).setUp()
diff --git a/nova/tests/objects/test_instance.py b/nova/tests/objects/test_instance.py
index a9238a924..efd0bcdf9 100644
--- a/nova/tests/objects/test_instance.py
+++ b/nova/tests/objects/test_instance.py
@@ -163,6 +163,7 @@ class _TestInstanceObject(object):
inst.refresh()
self.assertEqual(inst.host, 'new-host')
self.assertRemotes()
+ self.assertEqual(set([]), inst.obj_what_changed())
def test_save(self):
ctxt = context.get_admin_context()