1
from mock import MagicMock, patch, call
3
import charmhelpers.core.hookenv as hookenv
4
hookenv.config = MagicMock()
5
import quantum_utils as utils
6
_register_configs = utils.register_configs
7
_restart_map = utils.restart_map
8
utils.register_configs = MagicMock()
9
utils.restart_map = MagicMock()
10
import quantum_hooks as hooks
11
utils.register_configs = _register_configs
12
utils.restart_map = _restart_map
14
from test_utils import CharmTestCase
19
'configure_installation_source',
24
'filter_installed_packages',
29
'do_openstack_upgrade',
30
'openstack_upgrade_available',
46
'update_legacy_ha_files',
47
'install_legacy_ha_files',
49
'get_hacluster_config',
50
'remove_legacy_ha_files',
52
'stop_neutron_ha_monitor_daemon',
57
def passthrough(value):
61
class TestQuantumHooks(CharmTestCase):
64
super(TestQuantumHooks, self).setUp(hooks, TO_PATCH)
65
self.config.side_effect = self.test_config.get
66
self.test_config.set('openstack-origin', 'cloud:precise-havana')
67
self.test_config.set('plugin', 'ovs')
68
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
69
self.b64decode.side_effect = passthrough
70
hookenv.config.side_effect = self.test_config.get
71
hooks.hooks._config_save = False
73
def _call_hook(self, hookname):
75
'hooks/{}'.format(hookname)])
77
def test_install_hook(self):
78
self.valid_plugin.return_value = True
79
_pkgs = ['foo', 'bar']
80
self.filter_installed_packages.return_value = _pkgs
81
self._call_hook('install')
82
self.configure_installation_source.assert_called_with(
83
'cloud:precise-havana'
85
self.apt_update.assert_called_with(fatal=True)
86
self.apt_install.assert_has_calls([
87
call(_pkgs, fatal=True),
88
call(_pkgs, fatal=True),
90
self.assertTrue(self.get_early_packages.called)
91
self.assertTrue(self.get_packages.called)
92
self.assertTrue(self.execd_preinstall.called)
94
def test_install_hook_precise_nocloudarchive(self):
95
self.test_config.set('openstack-origin', 'distro')
96
self._call_hook('install')
97
self.configure_installation_source.assert_called_with(
98
'cloud:precise-folsom'
102
def test_install_hook_invalid_plugin(self, _exit):
103
self.valid_plugin.return_value = False
104
self._call_hook('install')
105
self.assertTrue(self.log.called)
106
_exit.assert_called_with(1)
108
@patch.object(utils, 'git_install_requested')
109
def test_install_hook_git(self, git_requested):
110
git_requested.return_value = True
111
self.valid_plugin.return_value = True
112
_pkgs = ['foo', 'bar']
113
self.filter_installed_packages.return_value = _pkgs
114
repo = 'cloud:trusty-juno'
115
openstack_origin_git = {
117
{'name': 'requirements',
118
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
119
'branch': 'stable/juno'},
121
'repository': 'git://git.openstack.org/openstack/neutron',
122
'branch': 'stable/juno'}
124
'directory': '/mnt/openstack-git',
126
projects_yaml = yaml.dump(openstack_origin_git)
127
self.test_config.set('openstack-origin', repo)
128
self.test_config.set('openstack-origin-git', projects_yaml)
129
self._call_hook('install')
130
self.configure_installation_source.assert_called_with(
133
self.apt_update.assert_called_with(fatal=True)
134
self.apt_install.assert_has_calls([
135
call(_pkgs, fatal=True),
136
call(_pkgs, fatal=True),
138
self.assertTrue(self.get_early_packages.called)
139
self.assertTrue(self.get_packages.called)
140
self.git_install.assert_called_with(projects_yaml)
141
self.assertTrue(self.execd_preinstall.called)
143
@patch.object(hooks, 'git_install_requested')
144
def test_config_changed(self, git_requested):
145
def mock_relids(rel):
147
git_requested.return_value = False
148
self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}')
149
self.openstack_upgrade_available.return_value = True
150
self.valid_plugin.return_value = True
151
self.relation_ids.side_effect = mock_relids
152
_db_joined = self.patch('db_joined')
153
_pgsql_db_joined = self.patch('pgsql_db_joined')
154
_amqp_joined = self.patch('amqp_joined')
155
_amqp_nova_joined = self.patch('amqp_nova_joined')
156
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
157
self._call_hook('config-changed')
158
self.assertTrue(self.do_openstack_upgrade.called)
159
self.assertTrue(self.configure_ovs.called)
160
self.assertTrue(_db_joined.called)
161
self.assertTrue(_pgsql_db_joined.called)
162
self.assertTrue(_amqp_joined.called)
163
self.assertTrue(_amqp_nova_joined.called)
164
self.assertTrue(_zmq_joined.called)
165
self.create_sysctl.assert_called()
167
@patch.object(hooks, 'git_install_requested')
168
def test_config_changed_upgrade(self, git_requested):
169
git_requested.return_value = False
170
self.openstack_upgrade_available.return_value = True
171
self.valid_plugin.return_value = True
172
self._call_hook('config-changed')
173
self.assertTrue(self.do_openstack_upgrade.called)
174
self.assertTrue(self.configure_ovs.called)
176
@patch.object(hooks, 'git_install_requested')
177
def test_config_changed_n1kv(self, git_requested):
178
git_requested.return_value = False
179
self.openstack_upgrade_available.return_value = False
180
self.valid_plugin.return_value = True
181
self.filter_installed_packages.side_effect = lambda p: p
182
self.test_config.set('plugin', 'n1kv')
183
self._call_hook('config-changed')
184
self.apt_install.assert_called_with('neutron-l3-agent')
185
self.test_config.set('enable-l3-agent', False)
186
self._call_hook('config-changed')
187
self.apt_purge.assert_called_with('neutron-l3-agent')
190
@patch.object(hooks, 'git_install_requested')
191
def test_config_changed_invalid_plugin(self, git_requested, _exit):
192
git_requested.return_value = False
193
self.valid_plugin.return_value = False
194
self._call_hook('config-changed')
195
self.assertTrue(self.log.called)
196
_exit.assert_called_with(1)
198
@patch.object(hooks, 'git_install_requested')
199
@patch.object(hooks, 'config_value_changed')
200
def test_config_changed_git(self, config_val_changed, git_requested):
201
def mock_relids(rel):
203
git_requested.return_value = True
204
self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}')
205
self.openstack_upgrade_available.return_value = True
206
self.valid_plugin.return_value = True
207
self.relation_ids.side_effect = mock_relids
208
_db_joined = self.patch('db_joined')
209
_pgsql_db_joined = self.patch('pgsql_db_joined')
210
_amqp_joined = self.patch('amqp_joined')
211
_amqp_nova_joined = self.patch('amqp_nova_joined')
212
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
213
repo = 'cloud:trusty-juno'
214
openstack_origin_git = {
216
{'name': 'requirements',
218
'git://git.openstack.org/openstack/requirements',
219
'branch': 'stable/juno'},
221
'repository': 'git://git.openstack.org/openstack/neutron',
222
'branch': 'stable/juno'}
224
'directory': '/mnt/openstack-git',
226
projects_yaml = yaml.dump(openstack_origin_git)
227
self.test_config.set('openstack-origin', repo)
228
self.test_config.set('openstack-origin-git', projects_yaml)
229
self._call_hook('config-changed')
230
self.git_install.assert_called_with(projects_yaml)
231
self.assertFalse(self.do_openstack_upgrade.called)
232
self.assertTrue(self.configure_ovs.called)
233
self.assertTrue(_db_joined.called)
234
self.assertTrue(_pgsql_db_joined.called)
235
self.assertTrue(_amqp_joined.called)
236
self.assertTrue(_amqp_nova_joined.called)
237
self.assertTrue(_zmq_joined.called)
238
self.create_sysctl.assert_called()
240
def test_upgrade_charm(self):
241
_install = self.patch('install')
242
_config_changed = self.patch('config_changed')
243
self._call_hook('upgrade-charm')
244
self.assertTrue(_install.called)
245
self.assertTrue(_config_changed.called)
247
def test_db_joined(self):
248
self.is_relation_made.return_value = False
249
self.unit_get.return_value = 'myhostname'
250
self._call_hook('shared-db-relation-joined')
251
self.relation_set.assert_called_with(
254
hostname='myhostname',
258
def test_db_joined_with_postgresql(self):
259
self.is_relation_made.return_value = True
261
with self.assertRaises(Exception) as context:
263
self.assertEqual(context.exception.message,
264
'Attempting to associate a mysql database when there '
265
'is already associated a postgresql one')
267
def test_postgresql_db_joined(self):
268
self.unit_get.return_value = 'myhostname'
269
self.is_relation_made.return_value = False
270
self._call_hook('pgsql-db-relation-joined')
271
self.relation_set.assert_called_with(
276
def test_postgresql_joined_with_db(self):
277
self.is_relation_made.return_value = True
279
with self.assertRaises(Exception) as context:
280
hooks.pgsql_db_joined()
281
self.assertEqual(context.exception.message,
282
'Attempting to associate a postgresql database when'
283
' there is already associated a mysql one')
285
def test_amqp_joined(self):
286
self._call_hook('amqp-relation-joined')
287
self.relation_set.assert_called_with(
293
def test_amqp_changed(self):
294
self._call_hook('amqp-relation-changed')
295
self.assertTrue(self.CONFIGS.write_all.called)
297
def test_amqp_departed_no_rel(self):
298
self.CONFIGS.complete_contexts.return_value = []
299
self._call_hook('amqp-relation-departed')
300
self.assertFalse(self.CONFIGS.write_all.called)
302
def test_amqp_departed(self):
303
self.CONFIGS.complete_contexts.return_value = ['amqp']
304
self._call_hook('amqp-relation-departed')
305
self.assertTrue(self.CONFIGS.write_all.called)
307
def test_amqp_nova_joined(self):
308
self._call_hook('amqp-nova-relation-joined')
309
self.relation_set.assert_called_with(
315
def test_amqp_nova_changed_no_rel(self):
316
self.CONFIGS.complete_contexts.return_value = []
317
self._call_hook('amqp-nova-relation-changed')
318
self.assertFalse(self.CONFIGS.write_all.called)
320
def test_amqp_nova_changed(self):
321
self.CONFIGS.complete_contexts.return_value = ['amqp-nova']
322
self._call_hook('amqp-nova-relation-changed')
323
self.assertTrue(self.CONFIGS.write_all.called)
325
def test_shared_db_changed(self):
326
self._call_hook('shared-db-relation-changed')
327
self.assertTrue(self.CONFIGS.write_all.called)
329
def test_pgsql_db_changed(self):
330
self._call_hook('pgsql-db-relation-changed')
331
self.assertTrue(self.CONFIGS.write_all.called)
333
def test_nm_changed(self):
334
self.relation_get.return_value = "cert"
335
self._call_hook('quantum-network-service-relation-changed')
336
self.assertTrue(self.CONFIGS.write_all.called)
337
self.install_ca_cert.assert_called_with('cert')
339
def test_neutron_plugin_changed(self):
340
self.use_l3ha.return_value = True
341
self._call_hook('neutron-plugin-api-relation-changed')
342
self.apt_install.assert_called_with(['keepalived'], fatal=True)
343
self.assertTrue(self.CONFIGS.write_all.called)
345
def test_cluster_departed_nvp(self):
346
self.test_config.set('plugin', 'nvp')
347
self._call_hook('cluster-relation-departed')
348
self.assertTrue(self.log.called)
351
self._call_hook('stop')
352
self.assertTrue(self.stop_services.called)
354
def test_ha_relation_joined(self):
355
self.test_config.set('ha-legacy-mode', True)
356
self._call_hook('ha_relation_joined')
357
self.assertTrue(self.cache_env_data.called)
358
self.assertTrue(self.get_hacluster_config.called)
359
self.assertTrue(self.install_legacy_ha_files.called)
361
def test_ha_relation_departed(self):
362
self.test_config.set('ha-legacy-mode', True)
363
self._call_hook('ha-relation-departed')
364
self.assertTrue(self.remove_legacy_ha_files.called)
365
self.assertTrue(self.stop_neutron_ha_monitor_daemon.called)
367
def test_quantum_network_service_relation_changed(self):
368
self.test_config.set('ha-legacy-mode', True)
369
self._call_hook('quantum-network-service-relation-changed')
370
self.assertTrue(self.cache_env_data.called)