summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-02-22 03:22:30 +0000
committerGerrit Code Review <review@openstack.org>2012-02-22 03:22:30 +0000
commitc4ff7ef07c50deccf3cb7877ecab2245724f3091 (patch)
tree0a2266b6c9d162251b213fbb2dfe96ad47ec040f /nova/tests
parent11d82fc7d4d17b6edf435633501ddf7a44d6adf5 (diff)
parent424f32f04d9c6c97f684782b35e1c25fbf83ce05 (diff)
Merge "blueprint host-aggregates: xenapi implementation"
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/test_compute.py108
-rw-r--r--nova/tests/test_db_api.py56
-rw-r--r--nova/tests/test_virt_drivers.py8
-rw-r--r--nova/tests/test_xenapi.py147
4 files changed, 283 insertions, 36 deletions
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index d6d54227f..5ee74df8e 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -3153,6 +3153,8 @@ def _create_service_entries(context, values={'avail_zone1': ['fake_host1',
class ComputeAPIAggrTestCase(test.TestCase):
+ """This is for unit coverage of aggregate-related methods
+ defined in nova.compute.api."""
def setUp(self):
super(ComputeAPIAggrTestCase, self).setUp()
@@ -3164,9 +3166,16 @@ class ComputeAPIAggrTestCase(test.TestCase):
def tearDown(self):
super(ComputeAPIAggrTestCase, self).tearDown()
+ def test_create_invalid_availability_zone(self):
+ """Ensure InvalidAggregateAction is raised with wrong avail_zone."""
+ self.assertRaises(exception.InvalidAggregateAction,
+ self.api.create_aggregate,
+ self.context, 'fake_aggr', 'fake_avail_zone')
+
def test_update_aggregate_metadata(self):
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
- 'fake_availability_zone')
+ 'fake_zone')
metadata = {'foo_key1': 'foo_value1',
'foo_key2': 'foo_value2', }
aggr = self.api.update_aggregate_metadata(self.context, aggr['id'],
@@ -3178,8 +3187,9 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_delete_aggregate(self):
"""Ensure we can delete an aggregate."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
- 'fake_availability_zone')
+ 'fake_zone')
self.api.delete_aggregate(self.context, aggr['id'])
expected = db.aggregate_get(self.context, aggr['id'],
read_deleted='yes')
@@ -3188,10 +3198,10 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_delete_non_empty_aggregate(self):
"""Ensure InvalidAggregateAction is raised when non empty aggregate."""
- aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
- 'fake_availability_zone')
_create_service_entries(self.context,
{'fake_availability_zone': ['fake_host']})
+ aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
+ 'fake_availability_zone')
self.api.add_host_to_aggregate(self.context, aggr['id'], 'fake_host')
self.assertRaises(exception.InvalidAggregateAction,
self.api.delete_aggregate, self.context, aggr['id'])
@@ -3242,9 +3252,9 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_add_host_to_aggregate_invalid_dismissed_status(self):
"""Ensure InvalidAggregateAction is raised when aggregate is
deleted."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context,
'fake_aggregate', 'fake_zone')
- _create_service_entries(self.context, {'fake_zone': ['fake_host']})
# let's mock the fact that the aggregate is dismissed!
status = {'operational_state': aggregate_states.DISMISSED}
db.aggregate_update(self.context, aggr['id'], status)
@@ -3255,9 +3265,9 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_add_host_to_aggregate_invalid_error_status(self):
"""Ensure InvalidAggregateAction is raised when aggregate is
in error."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context,
'fake_aggregate', 'fake_zone')
- _create_service_entries(self.context, {'fake_zone': ['fake_host']})
# let's mock the fact that the aggregate is in error!
status = {'operational_state': aggregate_states.ERROR}
db.aggregate_update(self.context, aggr['id'], status)
@@ -3267,17 +3277,19 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_add_host_to_aggregate_zones_mismatch(self):
"""Ensure InvalidAggregateAction is raised when zones don't match."""
- _create_service_entries(self.context, {'fake_zoneX': ['fake_host']})
+ _create_service_entries(self.context, {'fake_zoneX': ['fake_host1'],
+ 'fake_zoneY': ['fake_host2']})
aggr = self.api.create_aggregate(self.context,
'fake_aggregate', 'fake_zoneY')
self.assertRaises(exception.InvalidAggregateAction,
self.api.add_host_to_aggregate,
- self.context, aggr['id'], 'fake_host')
+ self.context, aggr['id'], 'fake_host1')
def test_add_host_to_aggregate_raise_not_found(self):
"""Ensure ComputeHostNotFound is raised when adding invalid host."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
- 'fake_availability_zone')
+ 'fake_zone')
self.assertRaises(exception.ComputeHostNotFound,
self.api.add_host_to_aggregate,
self.context, aggr['id'], 'invalid_host')
@@ -3325,9 +3337,9 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_remove_host_from_aggregate_invalid_dismissed_status(self):
"""Ensure InvalidAggregateAction is raised when aggregate is
deleted."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context,
'fake_aggregate', 'fake_zone')
- _create_service_entries(self.context, {'fake_zone': ['fake_host']})
# let's mock the fact that the aggregate is dismissed!
status = {'operational_state': aggregate_states.DISMISSED}
db.aggregate_update(self.context, aggr['id'], status)
@@ -3338,9 +3350,9 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_remove_host_from_aggregate_invalid_changing_status(self):
"""Ensure InvalidAggregateAction is raised when aggregate is
changing."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context,
'fake_aggregate', 'fake_zone')
- _create_service_entries(self.context, {'fake_zone': ['fake_host']})
# let's mock the fact that the aggregate is changing!
status = {'operational_state': aggregate_states.CHANGING}
db.aggregate_update(self.context, aggr['id'], status)
@@ -3350,13 +3362,85 @@ class ComputeAPIAggrTestCase(test.TestCase):
def test_remove_host_from_aggregate_raise_not_found(self):
"""Ensure ComputeHostNotFound is raised when removing invalid host."""
+ _create_service_entries(self.context, {'fake_zone': ['fake_host']})
aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
- 'fake_availability_zone')
+ 'fake_zone')
self.assertRaises(exception.ComputeHostNotFound,
self.api.remove_host_from_aggregate,
self.context, aggr['id'], 'invalid_host')
+class ComputeAggrTestCase(BaseTestCase):
+ """This is for unit coverage of aggregate-related methods
+ defined in nova.compute.manager."""
+
+ def setUp(self):
+ super(ComputeAggrTestCase, self).setUp()
+ self.context = context.get_admin_context()
+ values = {'name': 'test_aggr',
+ 'availability_zone': 'test_zone', }
+ self.aggr = db.aggregate_create(self.context, values)
+
+ def tearDown(self):
+ super(ComputeAggrTestCase, self).tearDown()
+
+ def test_add_aggregate_host(self):
+ def fake_driver_add_to_aggregate(context, aggregate, host):
+ fake_driver_add_to_aggregate.called = True
+ return {"foo": "bar"}
+ self.stubs.Set(self.compute.driver, "add_to_aggregate",
+ fake_driver_add_to_aggregate)
+
+ self.compute.add_aggregate_host(self.context, self.aggr.id, "host")
+ self.assertTrue(fake_driver_add_to_aggregate.called)
+
+ def test_add_aggregate_host_raise_err(self):
+ """Ensure the undo operation works correctly on add."""
+ def fake_driver_add_to_aggregate(context, aggregate, host):
+ raise exception.AggregateError
+ self.stubs.Set(self.compute.driver, "add_to_aggregate",
+ fake_driver_add_to_aggregate)
+
+ state = {'operational_state': aggregate_states.ACTIVE}
+ db.aggregate_update(self.context, self.aggr.id, state)
+ db.aggregate_host_add(self.context, self.aggr.id, 'fake_host')
+
+ self.assertRaises(exception.AggregateError,
+ self.compute.add_aggregate_host,
+ self.context, self.aggr.id, "fake_host")
+ excepted = db.aggregate_get(self.context, self.aggr.id)
+ self.assertEqual(excepted.operational_state, aggregate_states.ERROR)
+ self.assertEqual(excepted.hosts, [])
+
+ def test_remove_aggregate_host(self):
+ def fake_driver_remove_from_aggregate(context, aggregate, host):
+ fake_driver_remove_from_aggregate.called = True
+ self.assertEqual("host", host, "host")
+ return {"foo": "bar"}
+ self.stubs.Set(self.compute.driver, "remove_from_aggregate",
+ fake_driver_remove_from_aggregate)
+
+ self.compute.remove_aggregate_host(self.context, self.aggr.id, "host")
+ self.assertTrue(fake_driver_remove_from_aggregate.called)
+
+ def test_remove_aggregate_host_raise_err(self):
+ """Ensure the undo operation works correctly on remove."""
+ def fake_driver_remove_from_aggregate(context, aggregate, host):
+ raise exception.AggregateError
+ self.stubs.Set(self.compute.driver, "remove_from_aggregate",
+ fake_driver_remove_from_aggregate)
+
+ state = {'operational_state': aggregate_states.ACTIVE}
+ db.aggregate_update(self.context, self.aggr.id, state)
+
+ self.assertRaises(exception.AggregateError,
+ self.compute.remove_aggregate_host,
+ self.context, self.aggr.id, "fake_host")
+ excepted = db.aggregate_get(self.context, self.aggr.id)
+ self.assertEqual(excepted.operational_state, aggregate_states.ERROR)
+ self.assertEqual(excepted.hosts, ['fake_host'])
+
+
class ComputePolicyTestCase(BaseTestCase):
def setUp(self):
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py
index 3353ea737..4cb17d958 100644
--- a/nova/tests/test_db_api.py
+++ b/nova/tests/test_db_api.py
@@ -267,6 +267,30 @@ class DbApiTestCase(test.TestCase):
expected = {uuids[0]: [], uuids[1]: []}
self.assertEqual(expected, instance_faults)
+ def test_dns_registration(self):
+ domain1 = 'test.domain.one'
+ domain2 = 'test.domain.two'
+ testzone = 'testzone'
+ ctxt = context.get_admin_context()
+
+ db.dnsdomain_register_for_zone(ctxt, domain1, testzone)
+ domain_ref = db.dnsdomain_get(ctxt, domain1)
+ zone = domain_ref.availability_zone
+ scope = domain_ref.scope
+ self.assertEqual(scope, 'private')
+ self.assertEqual(zone, testzone)
+
+ db.dnsdomain_register_for_project(ctxt, domain2,
+ self.project_id)
+ domain_ref = db.dnsdomain_get(ctxt, domain2)
+ project = domain_ref.project_id
+ scope = domain_ref.scope
+ self.assertEqual(project, self.project_id)
+ self.assertEqual(scope, 'public')
+
+ db.dnsdomain_unregister(ctxt, domain1)
+ db.dnsdomain_unregister(ctxt, domain2)
+
def _get_fake_aggr_values():
return {'name': 'fake_aggregate',
@@ -351,6 +375,14 @@ class AggregateDBApiTestCase(test.TestCase):
db.aggregate_create,
self.context, _get_fake_aggr_values())
+ def test_aggregate_get(self):
+ """Ensure we can get aggregate with all its relations."""
+ ctxt = context.get_admin_context()
+ result = _create_aggregate_with_hosts(context=ctxt)
+ expected = db.aggregate_get(ctxt, result.id)
+ self.assertEqual(_get_fake_aggr_hosts(), expected.hosts)
+ self.assertEqual(_get_fake_aggr_metadata(), expected.metadetails)
+
def test_aggregate_delete_raise_not_found(self):
"""Ensure AggregateNotFound is raised when deleting an aggregate."""
ctxt = context.get_admin_context()
@@ -541,30 +573,6 @@ class AggregateDBApiTestCase(test.TestCase):
db.aggregate_host_delete,
ctxt, result.id, _get_fake_aggr_hosts()[0])
- def test_dns_registration(self):
- domain1 = 'test.domain.one'
- domain2 = 'test.domain.two'
- testzone = 'testzone'
- ctxt = context.get_admin_context()
-
- db.dnsdomain_register_for_zone(ctxt, domain1, testzone)
- domain_ref = db.dnsdomain_get(ctxt, domain1)
- zone = domain_ref.availability_zone
- scope = domain_ref.scope
- self.assertEqual(scope, 'private')
- self.assertEqual(zone, testzone)
-
- db.dnsdomain_register_for_project(ctxt, domain2,
- self.project_id)
- domain_ref = db.dnsdomain_get(ctxt, domain2)
- project = domain_ref.project_id
- scope = domain_ref.scope
- self.assertEqual(project, self.project_id)
- self.assertEqual(scope, 'public')
-
- db.dnsdomain_unregister(ctxt, domain1)
- db.dnsdomain_unregister(ctxt, domain2)
-
class CapacityTestCase(test.TestCase):
def setUp(self):
diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py
index 41c5d118e..70d54db9a 100644
--- a/nova/tests/test_virt_drivers.py
+++ b/nova/tests/test_virt_drivers.py
@@ -401,6 +401,14 @@ class _VirtDriverTestCase(test.TestCase):
def test_host_power_action_startup(self):
self.connection.host_power_action('a useless argument?', 'startup')
+ @catch_notimplementederror
+ def test_add_to_aggregate(self):
+ self.connection.add_to_aggregate(self.ctxt, 'aggregate', 'host')
+
+ @catch_notimplementederror
+ def test_remove_from_aggregate(self):
+ self.connection.remove_from_aggregate(self.ctxt, 'aggregate', 'host')
+
class AbstractDriverTestCase(_VirtDriverTestCase):
def setUp(self):
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index d72365e5c..b08bbd69c 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -31,6 +31,7 @@ from nova import flags
from nova import log as logging
from nova import test
from nova import utils
+from nova.compute import aggregate_states
from nova.compute import instance_types
from nova.compute import power_state
from nova import exception
@@ -1741,3 +1742,149 @@ class XenAPISRSelectionTestCase(test.TestCase):
expected = helper.safe_find_sr(session)
self.assertEqual(session.call_xenapi('pool.get_default_SR', pool_ref),
expected)
+
+
+class XenAPIAggregateTestCase(test.TestCase):
+ """Unit tests for aggregate operations."""
+ def setUp(self):
+ super(XenAPIAggregateTestCase, self).setUp()
+ self.stubs = stubout.StubOutForTesting()
+ self.flags(xenapi_connection_url='http://test_url',
+ xenapi_connection_username='test_user',
+ xenapi_connection_password='test_pass',
+ instance_name_template='%d',
+ firewall_driver='nova.virt.xenapi.firewall.'
+ 'Dom0IptablesFirewallDriver',
+ host='host')
+ xenapi_fake.reset()
+ stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
+ self.context = context.get_admin_context()
+ self.conn = xenapi_conn.get_connection(False)
+ self.fake_metadata = {'master_compute': 'host'}
+
+ def tearDown(self):
+ super(XenAPIAggregateTestCase, self).tearDown()
+ self.stubs.UnsetAll()
+
+ def test_add_to_aggregate_called(self):
+ def fake_add_to_aggregate(context, aggregate, host):
+ fake_add_to_aggregate.called = True
+ self.stubs.Set(self.conn._pool,
+ "add_to_aggregate",
+ fake_add_to_aggregate)
+
+ self.conn.add_to_aggregate(None, None, None)
+ self.assertTrue(fake_add_to_aggregate.called)
+
+ def test_add_to_aggregate_for_first_host_sets_metadata(self):
+ def fake_init_pool(id, name):
+ fake_init_pool.called = True
+ self.stubs.Set(self.conn._pool, "_init_pool", fake_init_pool)
+
+ aggregate = self._aggregate_setup()
+ self.conn._pool.add_to_aggregate(self.context, aggregate, "host")
+ result = db.aggregate_get(self.context, aggregate.id)
+ self.assertTrue(fake_init_pool.called)
+ self.assertDictMatch(self.fake_metadata, result.metadetails)
+ self.assertEqual(aggregate_states.ACTIVE, result.operational_state)
+
+ def test_join_slave(self):
+ """Ensure join_slave gets called when the request gets to master."""
+ def fake_join_slave(id, compute_uuid, host, url, user, password):
+ fake_join_slave.called = True
+ self.stubs.Set(self.conn._pool, "_join_slave", fake_join_slave)
+
+ aggregate = self._aggregate_setup(hosts=['host', 'host2'],
+ metadata=self.fake_metadata)
+ self.conn._pool.add_to_aggregate(self.context, aggregate, "host2",
+ compute_uuid='fake_uuid',
+ url='fake_url',
+ user='fake_user',
+ passwd='fake_pass',
+ xenhost_uuid='fake_uuid')
+ self.assertTrue(fake_join_slave.called)
+
+ def test_add_to_aggregate_first_host(self):
+ def fake_pool_set_name_label(self, session, pool_ref, name):
+ fake_pool_set_name_label.called = True
+ self.stubs.Set(xenapi_fake.SessionBase, "pool_set_name_label",
+ fake_pool_set_name_label)
+ self.conn._session.call_xenapi("pool.create", {"name": "asdf"})
+
+ values = {"name": 'fake_aggregate',
+ "availability_zone": 'fake_zone'}
+ result = db.aggregate_create(self.context, values)
+ db.aggregate_host_add(self.context, result.id, "host")
+ aggregate = db.aggregate_get(self.context, result.id)
+ self.assertEqual(["host"], aggregate.hosts)
+ self.assertEqual({}, aggregate.metadetails)
+
+ self.conn._pool.add_to_aggregate(self.context, aggregate, "host")
+ self.assertTrue(fake_pool_set_name_label.called)
+
+ def test_remove_from_aggregate_called(self):
+ def fake_remove_from_aggregate(context, aggregate, host):
+ fake_remove_from_aggregate.called = True
+ self.stubs.Set(self.conn._pool,
+ "remove_from_aggregate",
+ fake_remove_from_aggregate)
+
+ self.conn.remove_from_aggregate(None, None, None)
+ self.assertTrue(fake_remove_from_aggregate.called)
+
+ def test_remove_from_empty_aggregate(self):
+ values = {"name": 'fake_aggregate',
+ "availability_zone": 'fake_zone'}
+ result = db.aggregate_create(self.context, values)
+ self.assertRaises(exception.AggregateError,
+ self.conn._pool.remove_from_aggregate,
+ None, result, "test_host")
+
+ def test_remove_slave(self):
+ """Ensure eject slave gets called."""
+ def fake_eject_slave(id, compute_uuid, host_uuid):
+ fake_eject_slave.called = True
+ self.stubs.Set(self.conn._pool, "_eject_slave", fake_eject_slave)
+
+ self.fake_metadata['host2'] = 'fake_host2_uuid'
+ aggregate = self._aggregate_setup(hosts=['host', 'host2'],
+ metadata=self.fake_metadata)
+ self.conn._pool.remove_from_aggregate(self.context, aggregate, "host2")
+ self.assertTrue(fake_eject_slave.called)
+
+ def test_remove_master_solo(self):
+ """Ensure metadata are cleared after removal."""
+ def fake_clear_pool(id):
+ fake_clear_pool.called = True
+ self.stubs.Set(self.conn._pool, "_clear_pool", fake_clear_pool)
+
+ aggregate = self._aggregate_setup(aggr_state=aggregate_states.ACTIVE,
+ metadata=self.fake_metadata)
+ self.conn._pool.remove_from_aggregate(self.context, aggregate, "host")
+ result = db.aggregate_get(self.context, aggregate.id)
+ self.assertTrue(fake_clear_pool.called)
+ self.assertDictMatch({}, result.metadetails)
+ self.assertEqual(aggregate_states.ACTIVE, result.operational_state)
+
+ def test_remote_master_non_empty_pool(self):
+ """Ensure AggregateError is raised if removing the master."""
+ aggregate = self._aggregate_setup(aggr_state=aggregate_states.ACTIVE,
+ hosts=['host', 'host2'],
+ metadata=self.fake_metadata)
+ self.assertRaises(exception.AggregateError,
+ self.conn._pool.remove_from_aggregate,
+ self.context, aggregate, "host")
+
+ def _aggregate_setup(self, aggr_name='fake_aggregate',
+ aggr_zone='fake_zone',
+ aggr_state=aggregate_states.CREATED,
+ hosts=['host'], metadata=None):
+ values = {"name": aggr_name,
+ "availability_zone": aggr_zone,
+ "operational_state": aggr_state, }
+ result = db.aggregate_create(self.context, values)
+ for host in hosts:
+ db.aggregate_host_add(self.context, result.id, host)
+ if metadata:
+ db.aggregate_metadata_add(self.context, result.id, metadata)
+ return db.aggregate_get(self.context, result.id)