diff options
| author | Armando Migliaccio <armando.migliaccio@eu.citrix.com> | 2012-01-13 16:46:37 +0000 |
|---|---|---|
| committer | Armando Migliaccio <armando.migliaccio@eu.citrix.com> | 2012-01-17 18:47:56 +0000 |
| commit | b76cc2f4426aef4422c5a4a6ad0a412a2cc4cbc3 (patch) | |
| tree | 96f532ed1b80e2a7839a21224d12abee067d26fe /nova/tests | |
| parent | 61b0c08b7cfe68ca3d567e05dd0bc333658cdc77 (diff) | |
blueprint host-aggregates
This is the first of a series of commits that add the host-aggregates capability,
as described on the blueprint page.
This commit, more precisely, introduces changes to the Nova model: model classes
related to aggregates have been added, as well as DB API methods to interact with
the model; a sqlalchemy migration script plus a bunch of tests are also part of
this changeset.
Commits that will follow are going to add:
- Extensions to OSAPI Admin, and related python_novaclient mappings
- Implementation of the XenAPI virt layer
- Integration of OSAPI and virt layer, via the compute_api
- smoketests
- openstack-manuals documentation
These commits will be pushed for review not necessarily in this exact order.
Change-Id: Iceb27609dc53bf4305c02d7cbc436fba4c4a7256
Diffstat (limited to 'nova/tests')
| -rw-r--r-- | nova/tests/test_db_api.py | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index 356be7a58..29e1a0520 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -22,6 +22,7 @@ import datetime from nova import test from nova import context +from nova import exception from nova import db from nova import flags from nova import utils @@ -257,3 +258,266 @@ class DbApiTestCase(test.TestCase): instance_faults = db.instance_fault_get_by_instance_uuids(ctxt, uuids) expected = {uuids[0]: [], uuids[1]: []} self.assertEqual(expected, instance_faults) + + +def _get_fake_aggr_values(): + return {'name': 'fake_aggregate', + 'availability_zone': 'fake_avail_zone', } + + +def _get_fake_aggr_metadata(): + return {'fake_key1': 'fake_value1', + 'fake_key2': 'fake_value2'} + + +def _get_fake_aggr_hosts(): + return ['foo.openstack.org'] + + +def _create_aggregate(context=context.get_admin_context(), + values=_get_fake_aggr_values(), + metadata=_get_fake_aggr_metadata()): + return db.aggregate_create(context, values, metadata) + + +def _create_aggregate_with_hosts(context=context.get_admin_context(), + values=_get_fake_aggr_values(), + metadata=_get_fake_aggr_metadata(), + hosts=_get_fake_aggr_hosts()): + result = _create_aggregate(context=context, + values=values, metadata=metadata) + for host in hosts: + db.aggregate_host_add(context, result.id, host) + return result + + +class AggregateDBApiTestCase(test.TestCase): + def setUp(self): + super(AggregateDBApiTestCase, self).setUp() + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, self.project_id) + + def tearDown(self): + super(AggregateDBApiTestCase, self).tearDown() + + def test_aggregate_create(self): + """Ensure aggregate can be created with no metadata.""" + result = _create_aggregate(metadata=None) + self.assertEqual(result['operational_state'], 'building') + + def test_aggregate_create_raise_exist_exc(self): + """Ensure aggregate names are distinct.""" + _create_aggregate(metadata=None) + self.assertRaises(exception.AggregateNameExists, + _create_aggregate, metadata=None) + + def test_aggregate_get_raise_not_found(self): + """Ensure AggregateNotFound is raised when getting an aggregate.""" + ctxt = context.get_admin_context() + # this does not exist! + aggregate_id = 1 + self.assertRaises(exception.AggregateNotFound, + db.aggregate_get, + ctxt, aggregate_id) + + def test_aggregate_metadata_get_raise_not_found(self): + """Ensure AggregateNotFound is raised when getting metadata.""" + ctxt = context.get_admin_context() + # this does not exist! + aggregate_id = 1 + self.assertRaises(exception.AggregateNotFound, + db.aggregate_metadata_get, + ctxt, aggregate_id) + + def test_aggregate_create_with_metadata(self): + """Ensure aggregate can be created with metadata.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt) + expected_metadata = db.aggregate_metadata_get(ctxt, result['id']) + self.assertDictMatch(expected_metadata, _get_fake_aggr_metadata()) + + def test_aggregate_create_low_privi_context(self): + """Ensure right context is applied when creating aggregate.""" + self.assertRaises(exception.AdminRequired, + db.aggregate_create, + self.context, _get_fake_aggr_values()) + + def test_aggregate_delete_raise_not_found(self): + """Ensure AggregateNotFound is raised when deleting an aggregate.""" + ctxt = context.get_admin_context() + # this does not exist! + aggregate_id = 1 + self.assertRaises(exception.AggregateNotFound, + db.aggregate_delete, + ctxt, aggregate_id) + + def test_aggregate_delete(self): + """Ensure we can delete an aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt, metadata=None) + db.aggregate_delete(ctxt, result['id']) + expected = db.aggregate_get_all(ctxt, read_deleted='no') + self.assertEqual(0, len(expected)) + + def test_aggregate_update(self): + """Ensure an aggregate can be updated.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt, metadata=None) + new_values = _get_fake_aggr_values() + new_values['availability_zone'] = 'different_avail_zone' + updated = db.aggregate_update(ctxt, 1, new_values) + self.assertNotEqual(result.availability_zone, + updated.availability_zone) + + def test_aggregate_update_with_metadata(self): + """Ensure an aggregate can be updated with metadata.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt, metadata=None) + values = _get_fake_aggr_values() + values['metadata'] = _get_fake_aggr_metadata() + db.aggregate_update(ctxt, 1, values) + expected = db.aggregate_metadata_get(ctxt, result.id) + self.assertDictMatch(_get_fake_aggr_metadata(), expected) + + def test_aggregate_update_with_existing_metadata(self): + """Ensure an aggregate can be updated with existing metadata.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt) + values = _get_fake_aggr_values() + values['metadata'] = _get_fake_aggr_metadata() + values['metadata']['fake_key1'] = 'foo' + db.aggregate_update(ctxt, 1, values) + expected = db.aggregate_metadata_get(ctxt, result.id) + self.assertDictMatch(values['metadata'], expected) + + def test_aggregate_update_raise_not_found(self): + """Ensure AggregateNotFound is raised when updating an aggregate.""" + ctxt = context.get_admin_context() + # this does not exist! + aggregate_id = 1 + new_values = _get_fake_aggr_values() + self.assertRaises(exception.AggregateNotFound, + db.aggregate_update, ctxt, aggregate_id, new_values) + + def test_aggregate_get_all(self): + """Ensure we can get all aggregates.""" + ctxt = context.get_admin_context() + counter = 3 + for c in xrange(counter): + _create_aggregate(context=ctxt, + values={'name': 'fake_aggregate_%d' % c, + 'availability_zone': 'fake_avail_zone'}, + metadata=None) + results = db.aggregate_get_all(ctxt) + self.assertEqual(len(results), counter) + + def test_aggregate_get_all_non_deleted(self): + """Ensure we get only non-deleted aggregates.""" + ctxt = context.get_admin_context() + add_counter = 5 + remove_counter = 2 + aggregates = [] + for c in xrange(1, add_counter): + values = {'name': 'fake_aggregate_%d' % c, + 'availability_zone': 'fake_avail_zone'} + aggregates.append(_create_aggregate(context=ctxt, + values=values, metadata=None)) + for c in xrange(1, remove_counter): + db.aggregate_delete(ctxt, aggregates[c - 1].id) + results = db.aggregate_get_all(ctxt, read_deleted='no') + self.assertEqual(len(results), add_counter - remove_counter) + + def test_aggregate_metadata_add(self): + """Ensure we can add metadata for the aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt, metadata=None) + metadata = _get_fake_aggr_metadata() + db.aggregate_metadata_add(ctxt, result.id, metadata) + expected = db.aggregate_metadata_get(ctxt, result.id) + self.assertDictMatch(metadata, expected) + + def test_aggregate_metadata_update(self): + """Ensure we can update metadata for the aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt) + metadata = _get_fake_aggr_metadata() + key = metadata.keys()[0] + db.aggregate_metadata_delete(ctxt, result.id, key) + new_metadata = {key: 'foo'} + db.aggregate_metadata_add(ctxt, result.id, new_metadata) + expected = db.aggregate_metadata_get(ctxt, result.id) + metadata[key] = 'foo' + self.assertDictMatch(metadata, expected) + + def test_aggregate_metadata_delete(self): + """Ensure we can delete metadata for the aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt, metadata=None) + metadata = _get_fake_aggr_metadata() + db.aggregate_metadata_add(ctxt, result.id, metadata) + db.aggregate_metadata_delete(ctxt, result.id, metadata.keys()[0]) + expected = db.aggregate_metadata_get(ctxt, result.id) + del metadata[metadata.keys()[0]] + self.assertDictMatch(metadata, expected) + + def test_aggregate_metadata_delete_raise_not_found(self): + """Ensure AggregateMetadataNotFound is raised when deleting.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt) + self.assertRaises(exception.AggregateMetadataNotFound, + db.aggregate_metadata_delete, + ctxt, result.id, 'foo_key') + + def test_aggregate_host_add(self): + """Ensure we can add host to the aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate_with_hosts(context=ctxt, metadata=None) + expected = db.aggregate_host_get_all(ctxt, result.id) + self.assertEqual(_get_fake_aggr_hosts(), expected) + + def test_aggregate_host_add_duplicate_raise_conflict(self): + """Ensure we cannot add host to distinct aggregates.""" + ctxt = context.get_admin_context() + _create_aggregate_with_hosts(context=ctxt, metadata=None) + self.assertRaises(exception.AggregateHostConflict, + _create_aggregate_with_hosts, ctxt, + values={'name': 'fake_aggregate2', + 'availability_zone': 'fake_avail_zone2', }, + metadata=None) + + def test_aggregate_host_add_duplicate_raise_exist_exc(self): + """Ensure we cannot add host to the same aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate_with_hosts(context=ctxt, metadata=None) + self.assertRaises(exception.AggregateHostExists, + db.aggregate_host_add, + ctxt, result.id, _get_fake_aggr_hosts()[0]) + + def test_aggregate_host_add_raise_not_found(self): + """Ensure AggregateFound when adding a host.""" + ctxt = context.get_admin_context() + # this does not exist! + aggregate_id = 1 + host = _get_fake_aggr_hosts()[0] + self.assertRaises(exception.AggregateNotFound, + db.aggregate_host_add, + ctxt, aggregate_id, host) + + def test_aggregate_host_delete(self): + """Ensure we can add host to the aggregate.""" + ctxt = context.get_admin_context() + result = _create_aggregate_with_hosts(context=ctxt, metadata=None) + db.aggregate_host_delete(ctxt, result.id, + _get_fake_aggr_hosts()[0]) + expected = db.aggregate_host_get_all(ctxt, result.id, + read_deleted='no') + self.assertEqual(0, len(expected)) + + def test_aggregate_host_delete_raise_not_found(self): + """Ensure AggregateHostNotFound is raised when deleting a host.""" + ctxt = context.get_admin_context() + result = _create_aggregate(context=ctxt) + self.assertRaises(exception.AggregateHostNotFound, + db.aggregate_host_delete, + ctxt, result.id, _get_fake_aggr_hosts()[0]) |
