~james-page/charms/trusty/neutron-openvswitch/lp1531102

« back to all changes in this revision

Viewing changes to unit_tests/test_neutron_ovs_utils.py

Deploy from source

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
 
from mock import MagicMock, patch
 
2
from mock import MagicMock, patch, call
3
3
from collections import OrderedDict
4
4
import charmhelpers.contrib.openstack.templating as templating
5
5
 
6
6
templating.OSConfigRenderer = MagicMock()
7
7
 
8
8
import neutron_ovs_utils as nutils
 
9
import neutron_ovs_context
9
10
 
10
11
from test_utils import (
11
12
    CharmTestCase,
15
16
 
16
17
 
17
18
TO_PATCH = [
 
19
    'add_bridge',
 
20
    'add_bridge_port',
 
21
    'config',
18
22
    'os_release',
19
23
    'neutron_plugin_attribute',
 
24
    'full_restart',
 
25
    'service_restart',
 
26
    'service_running',
 
27
    'ExternalPortContext',
20
28
]
21
29
 
22
30
head_pkg = 'linux-headers-3.15.0-5-generic'
23
31
 
 
32
openstack_origin_git = \
 
33
    """repositories:
 
34
         - {name: requirements,
 
35
            repository: 'git://git.openstack.org/openstack/requirements',
 
36
            branch: stable/juno}
 
37
         - {name: neutron,
 
38
            repository: 'git://git.openstack.org/openstack/neutron',
 
39
            branch: stable/juno}"""
 
40
 
24
41
 
25
42
def _mock_npa(plugin, attr, net_manager=None):
26
43
    plugins = {
38
55
    return plugins[plugin][attr]
39
56
 
40
57
 
 
58
class DummyContext():
 
59
 
 
60
    def __init__(self, return_value):
 
61
        self.return_value = return_value
 
62
 
 
63
    def __call__(self):
 
64
        return self.return_value
 
65
 
 
66
 
41
67
class TestNeutronOVSUtils(CharmTestCase):
42
68
 
43
69
    def setUp(self):
44
70
        super(TestNeutronOVSUtils, self).setUp(nutils, TO_PATCH)
45
71
        self.neutron_plugin_attribute.side_effect = _mock_npa
 
72
        self.config.side_effect = self.test_config.get
46
73
 
47
74
    def tearDown(self):
48
75
        # Reset cached cache
49
76
        hookenv.cache = {}
50
77
 
 
78
    @patch.object(nutils, 'use_dvr')
 
79
    @patch.object(nutils, 'git_install_requested')
51
80
    @patch.object(charmhelpers.contrib.openstack.neutron, 'os_release')
52
81
    @patch.object(charmhelpers.contrib.openstack.neutron, 'headers_package')
53
 
    def test_determine_packages(self, _head_pkgs, _os_rel):
 
82
    def test_determine_packages(self, _head_pkgs, _os_rel, _git_requested,
 
83
                                _use_dvr):
 
84
        _git_requested.return_value = False
 
85
        _use_dvr.return_value = False
54
86
        _os_rel.return_value = 'trusty'
55
87
        _head_pkgs.return_value = head_pkg
56
88
        pkg_list = nutils.determine_packages()
57
89
        expect = [['neutron-plugin-openvswitch-agent'], [head_pkg]]
58
90
        self.assertItemsEqual(pkg_list, expect)
59
91
 
60
 
    def test_register_configs(self):
 
92
    @patch.object(nutils, 'use_dvr')
 
93
    def test_register_configs(self, _use_dvr):
61
94
        class _mock_OSConfigRenderer():
62
95
            def __init__(self, templates_dir=None, openstack_release=None):
63
96
                self.configs = []
67
100
                self.configs.append(config)
68
101
                self.ctxts.append(ctxt)
69
102
 
 
103
        _use_dvr.return_value = False
70
104
        self.os_release.return_value = 'trusty'
71
105
        templating.OSConfigRenderer.side_effect = _mock_OSConfigRenderer
72
106
        _regconfs = nutils.register_configs()
75
109
                 '/etc/init/os-charm-phy-nic-mtu.conf']
76
110
        self.assertItemsEqual(_regconfs.configs, confs)
77
111
 
78
 
    def test_resource_map(self):
79
 
        _map = nutils.resource_map()
80
 
        confs = [nutils.NEUTRON_CONF]
81
 
        [self.assertIn(q_conf, _map.keys()) for q_conf in confs]
82
 
 
83
 
    def test_restart_map(self):
 
112
    @patch.object(nutils, 'use_dvr')
 
113
    def test_resource_map(self, _use_dvr):
 
114
        _use_dvr.return_value = False
 
115
        _map = nutils.resource_map()
 
116
        svcs = ['neutron-plugin-openvswitch-agent']
 
117
        confs = [nutils.NEUTRON_CONF]
 
118
        [self.assertIn(q_conf, _map.keys()) for q_conf in confs]
 
119
        self.assertEqual(_map[nutils.NEUTRON_CONF]['services'], svcs)
 
120
 
 
121
    @patch.object(nutils, 'use_dvr')
 
122
    def test_resource_map_dvr(self, _use_dvr):
 
123
        _use_dvr.return_value = True
 
124
        _map = nutils.resource_map()
 
125
        svcs = ['neutron-plugin-openvswitch-agent', 'neutron-metadata-agent',
 
126
                'neutron-l3-agent']
 
127
        confs = [nutils.NEUTRON_CONF]
 
128
        [self.assertIn(q_conf, _map.keys()) for q_conf in confs]
 
129
        self.assertEqual(_map[nutils.NEUTRON_CONF]['services'], svcs)
 
130
 
 
131
    @patch.object(nutils, 'use_dvr')
 
132
    def test_restart_map(self, _use_dvr):
 
133
        _use_dvr.return_value = False
84
134
        _restart_map = nutils.restart_map()
85
135
        ML2CONF = "/etc/neutron/plugins/ml2/ml2_conf.ini"
86
136
        expect = OrderedDict([
92
142
        for item in _restart_map:
93
143
            self.assertTrue(item in _restart_map)
94
144
            self.assertTrue(expect[item] == _restart_map[item])
 
145
 
 
146
    @patch.object(nutils, 'use_dvr')
 
147
    @patch('charmhelpers.contrib.openstack.context.config')
 
148
    def test_configure_ovs_ovs_data_port(self, mock_config, _use_dvr):
 
149
        _use_dvr.return_value = False
 
150
        mock_config.side_effect = self.test_config.get
 
151
        self.config.side_effect = self.test_config.get
 
152
        self.ExternalPortContext.return_value = \
 
153
            DummyContext(return_value=None)
 
154
        # Test back-compatibility i.e. port but no bridge (so br-data is
 
155
        # assumed)
 
156
        self.test_config.set('data-port', 'eth0')
 
157
        nutils.configure_ovs()
 
158
        self.add_bridge.assert_has_calls([
 
159
            call('br-int'),
 
160
            call('br-ex'),
 
161
            call('br-data')
 
162
        ])
 
163
        self.assertTrue(self.add_bridge_port.called)
 
164
 
 
165
        # Now test with bridge:port format
 
166
        self.test_config.set('data-port', 'br-foo:eth0')
 
167
        self.add_bridge.reset_mock()
 
168
        self.add_bridge_port.reset_mock()
 
169
        nutils.configure_ovs()
 
170
        self.add_bridge.assert_has_calls([
 
171
            call('br-int'),
 
172
            call('br-ex'),
 
173
            call('br-data')
 
174
        ])
 
175
        # Not called since we have a bogus bridge in data-ports
 
176
        self.assertFalse(self.add_bridge_port.called)
 
177
 
 
178
    @patch.object(nutils, 'use_dvr')
 
179
    @patch('charmhelpers.contrib.openstack.context.config')
 
180
    def test_configure_ovs_starts_service_if_required(self, mock_config,
 
181
                                                      _use_dvr):
 
182
        _use_dvr.return_value = False
 
183
        mock_config.side_effect = self.test_config.get
 
184
        self.config.return_value = 'ovs'
 
185
        self.service_running.return_value = False
 
186
        nutils.configure_ovs()
 
187
        self.assertTrue(self.full_restart.called)
 
188
 
 
189
    @patch.object(nutils, 'use_dvr')
 
190
    @patch('charmhelpers.contrib.openstack.context.config')
 
191
    def test_configure_ovs_doesnt_restart_service(self, mock_config, _use_dvr):
 
192
        _use_dvr.return_value = False
 
193
        mock_config.side_effect = self.test_config.get
 
194
        self.config.side_effect = self.test_config.get
 
195
        self.service_running.return_value = True
 
196
        nutils.configure_ovs()
 
197
        self.assertFalse(self.full_restart.called)
 
198
 
 
199
    @patch.object(nutils, 'use_dvr')
 
200
    @patch('charmhelpers.contrib.openstack.context.config')
 
201
    def test_configure_ovs_ovs_ext_port(self, mock_config, _use_dvr):
 
202
        _use_dvr.return_value = True
 
203
        mock_config.side_effect = self.test_config.get
 
204
        self.config.side_effect = self.test_config.get
 
205
        self.test_config.set('ext-port', 'eth0')
 
206
        self.ExternalPortContext.return_value = \
 
207
            DummyContext(return_value={'ext_port': 'eth0'})
 
208
        nutils.configure_ovs()
 
209
        self.add_bridge.assert_has_calls([
 
210
            call('br-int'),
 
211
            call('br-ex'),
 
212
            call('br-data')
 
213
        ])
 
214
        self.add_bridge_port.assert_called_with('br-ex', 'eth0')
 
215
 
 
216
    @patch.object(neutron_ovs_context, 'DVRSharedSecretContext')
 
217
    def test_get_shared_secret(self, _dvr_secret_ctxt):
 
218
        _dvr_secret_ctxt.return_value = \
 
219
            DummyContext(return_value={'shared_secret': 'supersecret'})
 
220
        self.assertEqual(nutils.get_shared_secret(), 'supersecret')
 
221
 
 
222
    @patch.object(nutils, 'git_install_requested')
 
223
    @patch.object(nutils, 'git_clone_and_install')
 
224
    @patch.object(nutils, 'git_post_install')
 
225
    @patch.object(nutils, 'git_pre_install')
 
226
    def test_git_install(self, git_pre, git_post, git_clone_and_install,
 
227
                         git_requested):
 
228
        projects_yaml = openstack_origin_git
 
229
        git_requested.return_value = True
 
230
        nutils.git_install(projects_yaml)
 
231
        self.assertTrue(git_pre.called)
 
232
        git_clone_and_install.assert_called_with(openstack_origin_git,
 
233
                                                 core_project='neutron')
 
234
        self.assertTrue(git_post.called)
 
235
 
 
236
    @patch.object(nutils, 'mkdir')
 
237
    @patch.object(nutils, 'write_file')
 
238
    @patch.object(nutils, 'add_user_to_group')
 
239
    @patch.object(nutils, 'add_group')
 
240
    @patch.object(nutils, 'adduser')
 
241
    def test_git_pre_install(self, adduser, add_group, add_user_to_group,
 
242
                             write_file, mkdir):
 
243
        nutils.git_pre_install()
 
244
        adduser.assert_called_with('neutron', shell='/bin/bash',
 
245
                                   system_user=True)
 
246
        add_group.assert_called_with('neutron', system_group=True)
 
247
        add_user_to_group.assert_called_with('neutron', 'neutron')
 
248
        expected = [
 
249
            call('/etc/neutron', owner='neutron',
 
250
                 group='neutron', perms=0700, force=False),
 
251
            call('/etc/neutron/rootwrap.d', owner='neutron',
 
252
                 group='neutron', perms=0700, force=False),
 
253
            call('/var/lib/neutron', owner='neutron',
 
254
                 group='neutron', perms=0700, force=False),
 
255
            call('/var/lib/neutron/lock', owner='neutron',
 
256
                 group='neutron', perms=0700, force=False),
 
257
            call('/var/log/neutron', owner='neutron',
 
258
                 group='neutron', perms=0700, force=False),
 
259
        ]
 
260
        self.assertEquals(mkdir.call_args_list, expected)
 
261
        expected = [
 
262
            call('/var/log/neutron/server.log', '', owner='neutron',
 
263
                 group='neutron', perms=0600),
 
264
        ]
 
265
        self.assertEquals(write_file.call_args_list, expected)
 
266
 
 
267
    @patch.object(nutils, 'git_src_dir')
 
268
    @patch.object(nutils, 'service_restart')
 
269
    @patch.object(nutils, 'render')
 
270
    @patch('os.path.join')
 
271
    @patch('shutil.copyfile')
 
272
    def test_git_post_install(self, copyfile, join, render,
 
273
                              service_restart, git_src_dir):
 
274
        projects_yaml = openstack_origin_git
 
275
        join.return_value = 'joined-string'
 
276
        nutils.git_post_install(projects_yaml)
 
277
        expected = [
 
278
            call('joined-string', '/etc/neutron/rootwrap.d/debug.filters'),
 
279
            call('joined-string', '/etc/neutron/policy.json'),
 
280
            call('joined-string', '/etc/neutron/rootwrap.conf'),
 
281
        ]
 
282
        copyfile.assert_has_calls(expected, any_order=True)
 
283
        neutron_ovs_agent_context = {
 
284
            'service_description': 'Neutron OpenvSwitch Plugin Agent',
 
285
            'charm_name': 'neutron-openvswitch',
 
286
            'process_name': 'neutron-openvswitch-agent',
 
287
            'cleanup_process_name': 'neutron-ovs-cleanup',
 
288
            'plugin_config': '/etc/neutron/plugins/ml2/ml2_conf.ini',
 
289
            'log_file': '/var/log/neutron/openvswitch-agent.log',
 
290
        }
 
291
        neutron_ovs_cleanup_context = {
 
292
            'service_description': 'Neutron OpenvSwitch Cleanup',
 
293
            'charm_name': 'neutron-openvswitch',
 
294
            'process_name': 'neutron-ovs-cleanup',
 
295
            'log_file': '/var/log/neutron/ovs-cleanup.log',
 
296
        }
 
297
        expected = [
 
298
            call('neutron_sudoers', '/etc/sudoers.d/neutron_sudoers', {},
 
299
                 perms=0o440),
 
300
            call('upstart/neutron-plugin-openvswitch-agent.upstart',
 
301
                 '/etc/init/neutron-plugin-openvswitch-agent.conf',
 
302
                 neutron_ovs_agent_context, perms=0o644),
 
303
            call('upstart/neutron-ovs-cleanup.upstart',
 
304
                 '/etc/init/neutron-ovs-cleanup.conf',
 
305
                 neutron_ovs_cleanup_context, perms=0o644),
 
306
        ]
 
307
        self.assertEquals(render.call_args_list, expected)
 
308
        expected = [
 
309
            call('neutron-plugin-openvswitch-agent'),
 
310
        ]
 
311
        self.assertEquals(service_restart.call_args_list, expected)