1
from mock import MagicMock, patch, call
3
import charmhelpers.core.hookenv as hookenv
4
hookenv.config = MagicMock()
5
import neutron_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()
11
with patch('charmhelpers.core.hookenv.status_set'):
12
import neutron_hooks as hooks
14
utils.register_configs = _register_configs
15
utils.restart_map = _restart_map
17
from test_utils import CharmTestCase
22
'configure_installation_source',
27
'filter_installed_packages',
32
'do_openstack_upgrade',
33
'openstack_upgrade_available',
49
'update_legacy_ha_files',
50
'install_legacy_ha_files',
52
'get_hacluster_config',
53
'remove_legacy_ha_files',
55
'stop_neutron_ha_monitor_daemon',
60
def passthrough(value):
64
class TestQuantumHooks(CharmTestCase):
67
super(TestQuantumHooks, self).setUp(hooks, TO_PATCH)
68
self.config.side_effect = self.test_config.get
69
self.test_config.set('openstack-origin', 'cloud:precise-havana')
70
self.test_config.set('plugin', 'ovs')
71
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
72
self.b64decode.side_effect = passthrough
73
hookenv.config.side_effect = self.test_config.get
74
hooks.hooks._config_save = False
76
def _call_hook(self, hookname):
78
'hooks/{}'.format(hookname)])
80
def test_install_hook(self):
81
self.valid_plugin.return_value = True
82
_pkgs = ['foo', 'bar']
83
self.filter_installed_packages.return_value = _pkgs
84
self._call_hook('install')
85
self.configure_installation_source.assert_called_with(
86
'cloud:precise-havana'
88
self.apt_update.assert_called_with(fatal=True)
89
self.apt_install.assert_has_calls([
90
call(_pkgs, fatal=True),
91
call(_pkgs, fatal=True),
93
self.assertTrue(self.get_early_packages.called)
94
self.assertTrue(self.get_packages.called)
95
self.assertTrue(self.execd_preinstall.called)
97
def test_install_hook_precise_nocloudarchive(self):
98
self.test_config.set('openstack-origin', 'distro')
99
self._call_hook('install')
100
self.configure_installation_source.assert_called_with(
101
'cloud:precise-folsom'
105
def test_install_hook_invalid_plugin(self, _exit):
106
self.valid_plugin.return_value = False
107
self._call_hook('install')
108
self.assertTrue(self.log.called)
109
_exit.assert_called_with(1)
111
@patch.object(utils, 'git_install_requested')
112
def test_install_hook_git(self, git_requested):
113
git_requested.return_value = True
114
self.valid_plugin.return_value = True
115
_pkgs = ['foo', 'bar']
116
self.filter_installed_packages.return_value = _pkgs
117
repo = 'cloud:trusty-juno'
118
openstack_origin_git = {
120
{'name': 'requirements',
121
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
122
'branch': 'stable/juno'},
124
'repository': 'git://git.openstack.org/openstack/neutron',
125
'branch': 'stable/juno'}
127
'directory': '/mnt/openstack-git',
129
projects_yaml = yaml.dump(openstack_origin_git)
130
self.test_config.set('openstack-origin', repo)
131
self.test_config.set('openstack-origin-git', projects_yaml)
132
self._call_hook('install')
133
self.configure_installation_source.assert_called_with(
136
self.apt_update.assert_called_with(fatal=True)
137
self.apt_install.assert_has_calls([
138
call(_pkgs, fatal=True),
139
call(_pkgs, fatal=True),
141
self.assertTrue(self.get_early_packages.called)
142
self.assertTrue(self.get_packages.called)
143
self.git_install.assert_called_with(projects_yaml)
144
self.assertTrue(self.execd_preinstall.called)
146
@patch.object(hooks, 'git_install_requested')
147
def test_config_changed(self, git_requested):
148
def mock_relids(rel):
150
git_requested.return_value = False
151
self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}')
152
self.openstack_upgrade_available.return_value = True
153
self.valid_plugin.return_value = True
154
self.relation_ids.side_effect = mock_relids
155
_db_joined = self.patch('db_joined')
156
_pgsql_db_joined = self.patch('pgsql_db_joined')
157
_amqp_joined = self.patch('amqp_joined')
158
_amqp_nova_joined = self.patch('amqp_nova_joined')
159
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
160
self._call_hook('config-changed')
161
self.assertTrue(self.do_openstack_upgrade.called)
162
self.assertTrue(self.configure_ovs.called)
163
self.assertTrue(_db_joined.called)
164
self.assertTrue(_pgsql_db_joined.called)
165
self.assertTrue(_amqp_joined.called)
166
self.assertTrue(_amqp_nova_joined.called)
167
self.assertTrue(_zmq_joined.called)
168
self.assertTrue(self.create_sysctl.called)
170
@patch.object(hooks, 'git_install_requested')
171
def test_config_changed_upgrade(self, git_requested):
172
git_requested.return_value = False
173
self.openstack_upgrade_available.return_value = True
174
self.valid_plugin.return_value = True
175
self._call_hook('config-changed')
176
self.assertTrue(self.do_openstack_upgrade.called)
177
self.assertTrue(self.configure_ovs.called)
179
@patch.object(hooks, 'git_install_requested')
180
def test_config_changed_n1kv(self, git_requested):
181
git_requested.return_value = False
182
self.openstack_upgrade_available.return_value = False
183
self.valid_plugin.return_value = True
184
self.filter_installed_packages.side_effect = lambda p: p
185
self.test_config.set('plugin', 'n1kv')
186
self._call_hook('config-changed')
187
self.apt_install.assert_called_with('neutron-l3-agent')
188
self.test_config.set('enable-l3-agent', False)
189
self._call_hook('config-changed')
190
self.apt_purge.assert_called_with('neutron-l3-agent')
193
@patch.object(hooks, 'git_install_requested')
194
def test_config_changed_invalid_plugin(self, git_requested, _exit):
195
git_requested.return_value = False
196
self.valid_plugin.return_value = False
197
self._call_hook('config-changed')
198
self.assertTrue(self.log.called)
199
_exit.assert_called_with(1)
201
@patch.object(hooks, 'git_install_requested')
202
@patch.object(hooks, 'config_value_changed')
203
def test_config_changed_git(self, config_val_changed, git_requested):
204
def mock_relids(rel):
206
git_requested.return_value = True
207
self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}')
208
self.openstack_upgrade_available.return_value = True
209
self.valid_plugin.return_value = True
210
self.relation_ids.side_effect = mock_relids
211
_db_joined = self.patch('db_joined')
212
_pgsql_db_joined = self.patch('pgsql_db_joined')
213
_amqp_joined = self.patch('amqp_joined')
214
_amqp_nova_joined = self.patch('amqp_nova_joined')
215
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
216
repo = 'cloud:trusty-juno'
217
openstack_origin_git = {
219
{'name': 'requirements',
221
'git://git.openstack.org/openstack/requirements',
222
'branch': 'stable/juno'},
224
'repository': 'git://git.openstack.org/openstack/neutron',
225
'branch': 'stable/juno'}
227
'directory': '/mnt/openstack-git',
229
projects_yaml = yaml.dump(openstack_origin_git)
230
self.test_config.set('openstack-origin', repo)
231
self.test_config.set('openstack-origin-git', projects_yaml)
232
self._call_hook('config-changed')
233
self.git_install.assert_called_with(projects_yaml)
234
self.assertFalse(self.do_openstack_upgrade.called)
235
self.assertTrue(self.configure_ovs.called)
236
self.assertTrue(_db_joined.called)
237
self.assertTrue(_pgsql_db_joined.called)
238
self.assertTrue(_amqp_joined.called)
239
self.assertTrue(_amqp_nova_joined.called)
240
self.assertTrue(_zmq_joined.called)
241
self.assertTrue(self.create_sysctl.called)
243
def test_upgrade_charm(self):
244
_install = self.patch('install')
245
_config_changed = self.patch('config_changed')
246
self._call_hook('upgrade-charm')
247
self.assertTrue(_install.called)
248
self.assertTrue(_config_changed.called)
250
def test_db_joined(self):
251
self.is_relation_made.return_value = False
252
self.unit_get.return_value = 'myhostname'
253
self._call_hook('shared-db-relation-joined')
254
self.relation_set.assert_called_with(
257
hostname='myhostname',
261
def test_db_joined_with_postgresql(self):
262
self.is_relation_made.return_value = True
264
with self.assertRaises(Exception) as context:
266
self.assertEqual(context.exception.message,
267
'Attempting to associate a mysql database when there '
268
'is already associated a postgresql one')
270
def test_postgresql_db_joined(self):
271
self.unit_get.return_value = 'myhostname'
272
self.is_relation_made.return_value = False
273
self._call_hook('pgsql-db-relation-joined')
274
self.relation_set.assert_called_with(
279
def test_postgresql_joined_with_db(self):
280
self.is_relation_made.return_value = True
282
with self.assertRaises(Exception) as context:
283
hooks.pgsql_db_joined()
284
self.assertEqual(context.exception.message,
285
'Attempting to associate a postgresql database when'
286
' there is already associated a mysql one')
288
def test_amqp_joined(self):
289
self._call_hook('amqp-relation-joined')
290
self.relation_set.assert_called_with(
296
def test_amqp_changed(self):
297
self._call_hook('amqp-relation-changed')
298
self.assertTrue(self.CONFIGS.write_all.called)
300
def test_amqp_departed_no_rel(self):
301
self.CONFIGS.complete_contexts.return_value = []
302
self._call_hook('amqp-relation-departed')
303
self.assertFalse(self.CONFIGS.write_all.called)
305
def test_amqp_departed(self):
306
self.CONFIGS.complete_contexts.return_value = ['amqp']
307
self._call_hook('amqp-relation-departed')
308
self.assertTrue(self.CONFIGS.write_all.called)
310
def test_amqp_nova_joined(self):
311
self._call_hook('amqp-nova-relation-joined')
312
self.relation_set.assert_called_with(
318
def test_amqp_nova_changed_no_rel(self):
319
self.CONFIGS.complete_contexts.return_value = []
320
self._call_hook('amqp-nova-relation-changed')
321
self.assertFalse(self.CONFIGS.write_all.called)
323
def test_amqp_nova_changed(self):
324
self.CONFIGS.complete_contexts.return_value = ['amqp-nova']
325
self._call_hook('amqp-nova-relation-changed')
326
self.assertTrue(self.CONFIGS.write_all.called)
328
def test_shared_db_changed(self):
329
self._call_hook('shared-db-relation-changed')
330
self.assertTrue(self.CONFIGS.write_all.called)
332
def test_pgsql_db_changed(self):
333
self._call_hook('pgsql-db-relation-changed')
334
self.assertTrue(self.CONFIGS.write_all.called)
336
def test_nm_changed(self):
337
self.relation_get.return_value = "cert"
338
self._call_hook('quantum-network-service-relation-changed')
339
self.assertTrue(self.CONFIGS.write_all.called)
340
self.install_ca_cert.assert_called_with('cert')
342
def test_neutron_plugin_changed(self):
343
self.use_l3ha.return_value = True
344
self._call_hook('neutron-plugin-api-relation-changed')
345
self.apt_install.assert_called_with(['keepalived', 'conntrack'],
347
self.assertTrue(self.CONFIGS.write_all.called)
349
def test_cluster_departed_nvp(self):
350
self.test_config.set('plugin', 'nvp')
351
self._call_hook('cluster-relation-departed')
352
self.assertTrue(self.log.called)
355
self._call_hook('stop')
356
self.assertTrue(self.stop_services.called)
358
def test_ha_relation_joined(self):
359
self.test_config.set('ha-legacy-mode', True)
360
self._call_hook('ha_relation_joined')
361
self.assertTrue(self.cache_env_data.called)
362
self.assertTrue(self.get_hacluster_config.called)
363
self.assertTrue(self.install_legacy_ha_files.called)
365
def test_ha_relation_departed(self):
366
self.test_config.set('ha-legacy-mode', True)
367
self._call_hook('ha-relation-departed')
368
self.assertTrue(self.remove_legacy_ha_files.called)
369
self.assertTrue(self.stop_neutron_ha_monitor_daemon.called)
371
def test_quantum_network_service_relation_changed(self):
372
self.test_config.set('ha-legacy-mode', True)
373
self._call_hook('quantum-network-service-relation-changed')
374
self.assertTrue(self.cache_env_data.called)