diff options
-rw-r--r-- | nova/objects/base.py | 2 | ||||
-rw-r--r-- | nova/objects/instance.py | 1 | ||||
-rw-r--r-- | nova/tests/conductor/test_conductor.py | 114 | ||||
-rw-r--r-- | nova/tests/db/test_db_api.py | 78 | ||||
-rw-r--r-- | nova/tests/objects/test_instance.py | 1 |
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() |