1
from mock import call, patch, MagicMock
3
from test_utils import CharmTestCase
5
import nova_compute_utils as utils
7
_reg = utils.register_configs
8
_map = utils.restart_map
10
utils.register_configs = MagicMock()
11
utils.restart_map = MagicMock()
13
import nova_compute_hooks as hooks
15
utils.register_configs = _reg
16
utils.restart_map = _map
19
# charmhelpers.core.hookenv
28
# charmhelpers.core.host
31
'filter_installed_packages',
33
#charmhelpers.contrib.openstack.utils
34
'configure_installation_source',
35
'openstack_upgrade_available',
38
'create_libvirt_secret',
41
'import_authorized_keys',
42
'import_keystone_ca_cert',
43
'initialize_ssh_keys',
45
'do_openstack_upgrade',
47
'neutron_plugin_attribute',
52
'ensure_ceph_keyring',
57
def fake_filter(packages):
61
class NovaComputeRelationsTests(CharmTestCase):
63
super(NovaComputeRelationsTests, self).setUp(hooks,
65
self.config.side_effect = self.test_config.get
66
self.filter_installed_packages.side_effect = fake_filter
68
def test_install_hook(self):
69
repo = 'cloud:precise-grizzly'
70
self.test_config.set('openstack-origin', repo)
71
self.determine_packages.return_value = ['foo', 'bar']
73
self.configure_installation_source.assert_called_with(repo)
74
self.assertTrue(self.apt_update.called)
75
self.apt_install.assert_called_with(['foo', 'bar'], fatal=True)
76
self.execd_preinstall.assert_called()
78
def test_config_changed_with_upgrade(self):
79
self.openstack_upgrade_available.return_value = True
80
hooks.config_changed()
81
self.assertTrue(self.do_openstack_upgrade.called)
83
@patch.object(hooks, 'compute_joined')
84
def test_config_changed_with_migration(self, compute_joined):
85
self.migration_enabled.return_value = True
86
self.test_config.set('migration-auth-type', 'ssh')
87
self.relation_ids.return_value = [
91
hooks.config_changed()
93
call('cloud-compute:0'),
94
call('cloud-compute:1'),
96
self.assertEquals(ex, compute_joined.call_args_list)
98
@patch.object(hooks, 'compute_joined')
99
def test_config_changed_no_upgrade_no_migration(self, compute_joined):
100
self.openstack_upgrade_available.return_value = False
101
self.migration_enabled.return_value = False
102
hooks.config_changed()
103
self.assertFalse(self.do_openstack_upgrade.called)
104
self.assertFalse(compute_joined.called)
106
def test_amqp_joined(self):
108
self.relation_set.assert_called_with(username='nova', vhost='nova')
110
@patch.object(hooks, 'CONFIGS')
111
def test_amqp_changed_missing_relation_data(self, configs):
112
configs.complete_contexts = MagicMock()
113
configs.complete_contexts.return_value = []
115
self.log.assert_called_with(
116
'amqp relation incomplete. Peer not ready?'
119
def _amqp_test(self, configs, quantum=False):
120
configs.complete_contexts = MagicMock()
121
configs.complete_contexts.return_value = ['amqp']
122
configs.write = MagicMock()
124
self.network_manager.return_value = 'quantum'
127
@patch.object(hooks, 'CONFIGS')
128
def test_amqp_changed_with_data_no_quantum(self, configs):
129
self._amqp_test(configs, quantum=False)
130
self.assertEquals([call('/etc/nova/nova.conf')],
131
configs.write.call_args_list)
133
@patch.object(hooks, 'CONFIGS')
134
def test_amqp_changed_with_data_and_quantum(self, configs):
135
self._amqp_test(configs, quantum=True)
136
self.assertEquals([call('/etc/nova/nova.conf'),
137
call('/etc/quantum/quantum.conf')],
138
configs.write.call_args_list)
140
def test_db_joined(self):
141
self.unit_get.return_value = 'nova.foohost.com'
143
self.relation_set.assert_called_with(relation_id=None,
144
nova_database='nova',
145
nova_username='nova',
146
nova_hostname='nova.foohost.com')
147
self.unit_get.assert_called_with('private-address')
149
def test_db_joined_quantum(self):
150
self.unit_get.return_value = 'nova.foohost.com'
151
self.network_manager.return_value = 'quantum'
152
hooks.db_joined(rid='shared-db:0')
153
calls = [call(nova_database='nova',
154
nova_username='nova',
155
nova_hostname='nova.foohost.com',
156
relation_id='shared-db:0'),
157
call(neutron_database='neutron',
158
neutron_username='neutron',
159
neutron_hostname='nova.foohost.com',
160
relation_id='shared-db:0')]
161
[self.assertIn(c, self.relation_set.call_args_list)
163
self.unit_get.assert_called_with('private-address')
165
@patch.object(hooks, 'CONFIGS')
166
def test_db_changed_missing_relation_data(self, configs):
167
configs.complete_contexts = MagicMock()
168
configs.complete_contexts.return_value = []
170
self.log.assert_called_with(
171
'shared-db relation incomplete. Peer not ready?'
174
def _shared_db_test(self, configs, quantum=False):
175
configs.complete_contexts = MagicMock()
176
configs.complete_contexts.return_value = ['shared-db']
177
configs.write = MagicMock()
179
self.network_manager.return_value = 'quantum'
182
@patch.object(hooks, 'CONFIGS')
183
def test_db_changed_with_data_no_quantum(self, configs):
184
self._shared_db_test(configs, quantum=False)
185
self.assertEquals([call('/etc/nova/nova.conf')],
186
configs.write.call_args_list)
188
@patch.object(hooks, 'CONFIGS')
189
def test_db_changed_with_data_and_quantum(self, configs):
190
self.neutron_plugin_attribute.return_value = '/etc/quantum/plugin.conf'
191
self._shared_db_test(configs, quantum=True)
192
ex = [call('/etc/nova/nova.conf'), call('/etc/quantum/plugin.conf')]
193
self.assertEquals(ex, configs.write.call_args_list)
195
@patch.object(hooks, 'CONFIGS')
196
def test_image_service_missing_relation_data(self, configs):
197
configs.complete_contexts = MagicMock()
198
configs.complete_contexts.return_value = []
199
hooks.image_service_changed()
200
self.log.assert_called_with(
201
'image-service relation incomplete. Peer not ready?'
204
@patch.object(hooks, 'CONFIGS')
205
def test_image_service_with_relation_data(self, configs):
206
configs.complete_contexts = MagicMock()
207
configs.write = MagicMock()
208
configs.complete_contexts.return_value = ['image-service']
209
hooks.image_service_changed()
210
configs.write.assert_called_with('/etc/nova/nova.conf')
212
def test_compute_joined_no_migration(self):
213
self.migration_enabled.return_value = False
214
hooks.compute_joined()
215
self.assertFalse(self.relation_set.called)
217
def test_compute_joined_with_ssh_migration(self):
218
self.migration_enabled.return_value = True
219
self.test_config.set('migration-auth-type', 'ssh')
220
self.public_ssh_key.return_value = 'foo'
221
hooks.compute_joined()
222
self.relation_set.assert_called_with(
224
ssh_public_key='foo',
225
migration_auth_type='ssh'
227
hooks.compute_joined(rid='cloud-compute:2')
228
self.relation_set.assert_called_with(
229
relation_id='cloud-compute:2',
230
ssh_public_key='foo',
231
migration_auth_type='ssh'
234
def test_compute_changed(self):
235
hooks.compute_changed()
237
self.import_authorized_keys,
238
self.import_keystone_ca_cert,
240
for func in expected_funcs:
241
self.assertTrue(func.called)
243
def test_ceph_joined(self):
245
self.apt_install.assert_called_with(['ceph-common'], fatal=True)
247
@patch.object(hooks, 'CONFIGS')
248
def test_ceph_changed_missing_relation_data(self, configs):
249
configs.complete_contexts = MagicMock()
250
configs.complete_contexts.return_value = []
252
self.log.assert_called_with(
253
'ceph relation incomplete. Peer not ready?'
256
@patch.object(hooks, 'CONFIGS')
257
def test_ceph_changed_no_keyring(self, configs):
258
configs.complete_contexts = MagicMock()
259
configs.complete_contexts.return_value = ['ceph']
260
self.ensure_ceph_keyring.return_value = False
262
self.log.assert_called_with(
263
'Could not create ceph keyring: peer not ready?'
266
@patch.object(hooks, 'CONFIGS')
267
def test_ceph_changed_with_key_and_relation_data(self, configs):
268
configs.complete_contexts = MagicMock()
269
configs.complete_contexts.return_value = ['ceph']
270
configs.write = MagicMock()
271
self.ensure_ceph_keyring.return_value = True
274
call('/etc/ceph/ceph.conf'),
275
call('/etc/ceph/secret.xml'),
276
call('/etc/nova/nova.conf'),
278
self.assertEquals(ex, configs.write.call_args_list)