summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorArmando Migliaccio <armando.migliaccio@eu.citrix.com>2012-01-13 16:46:37 +0000
committerArmando Migliaccio <armando.migliaccio@eu.citrix.com>2012-01-17 18:47:56 +0000
commitb76cc2f4426aef4422c5a4a6ad0a412a2cc4cbc3 (patch)
tree96f532ed1b80e2a7839a21224d12abee067d26fe /nova/tests
parent61b0c08b7cfe68ca3d567e05dd0bc333658cdc77 (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.py264
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])