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

« back to all changes in this revision

Viewing changes to tests/basic_deployment.py

  • Committer: Subbarayudu Mukkamala
  • Date: 2015-10-27 14:50:30 UTC
  • mfrom: (153 neutron-api-274709)
  • mto: This revision was merged to the branch mainline in revision 155.
  • Revision ID: smukkamala@nuagenetworks.net-20151027145030-3lr5cofupf4tond8
MergeĀ fromĀ lp:~openstack-charmers/charms/trusty/.../next/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
"""
3
 
Basic neutron-api functional test.
4
 
 
5
 
test_* methods are called in sort order.
6
 
 
7
 
Convention to ensure desired test order:
8
 
    1xx service and endpoint checks
9
 
    2xx relation checks
10
 
    3xx config checks
11
 
    4xx functional checks
12
 
    9xx restarts and other final checks
13
 
 
14
 
Common relation definitions:
15
 
  - [ neutron-api, mysql ]
16
 
  - [ neutron-api, rabbitmq-server ]
17
 
  - [ neutron-api, nova-cloud-controller ]
18
 
  - [ neutron-api, neutron-openvswitch ]
19
 
  - [ neutron-api, keystone ]
20
 
  - [ neutron-api, neutron-gateway ]
21
 
 
22
 
Resultant relations of neutron-api service:
23
 
    relations:
24
 
      amqp:
25
 
      - rabbitmq-server
26
 
      cluster:
27
 
      - neutron-api
28
 
      identity-service:
29
 
      - keystone
30
 
      neutron-api:
31
 
      - nova-cloud-controller
32
 
      neutron-plugin-api:  # not inspected due to
33
 
      - neutron-openvswitch  # bug 1421388
34
 
      shared-db:
35
 
      - mysql
36
 
"""
37
 
 
38
1
import amulet
39
2
import os
40
 
import time
41
3
import yaml
42
4
 
43
5
from charmhelpers.contrib.openstack.amulet.deployment import (
46
8
 
47
9
from charmhelpers.contrib.openstack.amulet.utils import (
48
10
    OpenStackAmuletUtils,
49
 
    DEBUG, # flake8: noqa
50
 
    ERROR
 
11
    DEBUG,
 
12
    # ERROR
51
13
)
52
14
 
53
15
# Use DEBUG to turn on debug logging
67
29
        self._add_relations()
68
30
        self._configure_services()
69
31
        self._deploy()
 
32
 
 
33
        u.log.info('Waiting on extended status checks...')
 
34
        exclude_services = ['mysql']
 
35
        self._auto_wait_for_status(exclude_services=exclude_services)
 
36
 
70
37
        self._initialize_tests()
71
38
 
72
39
    def _add_services(self):
78
45
           """
79
46
        this_service = {'name': 'neutron-api'}
80
47
        other_services = [{'name': 'mysql'},
81
 
                          {'name': 'rabbitmq-server'}, {'name': 'keystone'},
 
48
                          {'name': 'rabbitmq-server'},
 
49
                          {'name': 'keystone'},
 
50
                          {'name': 'glance'},  # to satisfy workload status
82
51
                          {'name': 'neutron-openvswitch'},
83
52
                          {'name': 'nova-cloud-controller'},
84
53
                          {'name': 'neutron-gateway'},
94
63
            'neutron-api:neutron-api': 'nova-cloud-controller:neutron-api',
95
64
            'neutron-api:neutron-plugin-api': 'neutron-gateway:'
96
65
                                              'neutron-plugin-api',
97
 
            'neutron-api:neutron-plugin-api': 'neutron-openvswitch:'
98
 
                                              'neutron-plugin-api',
99
66
            'neutron-api:identity-service': 'keystone:identity-service',
100
67
            'keystone:shared-db': 'mysql:shared-db',
101
 
            'nova-compute:neutron-plugin': 'neutron-openvswitch:neutron-plugin',
 
68
            'nova-compute:neutron-plugin': 'neutron-openvswitch:'
 
69
                                           'neutron-plugin',
102
70
            'nova-cloud-controller:shared-db': 'mysql:shared-db',
 
71
            'neutron-gateway:amqp': 'rabbitmq-server:amqp',
 
72
            'nova-cloud-controller:amqp': 'rabbitmq-server:amqp',
 
73
            'nova-compute:amqp': 'rabbitmq-server:amqp',
 
74
            'neutron-openvswitch:amqp': 'rabbitmq-server:amqp',
 
75
            'nova-cloud-controller:identity-service': 'keystone:'
 
76
                                                      'identity-service',
 
77
            'nova-cloud-controller:cloud-compute': 'nova-compute:'
 
78
                                                   'cloud-compute',
 
79
            'glance:identity-service': 'keystone:identity-service',
 
80
            'glance:shared-db': 'mysql:shared-db',
 
81
            'glance:amqp': 'rabbitmq-server:amqp',
 
82
            'nova-compute:image-service': 'glance:image-service',
 
83
            'nova-cloud-controller:image-service': 'glance:image-service',
 
84
        }
 
85
 
 
86
        # NOTE(beisner): relate this separately due to the resulting
 
87
        # duplicate dictionary key if included in the relations dict.
 
88
        relations_more = {
 
89
            'neutron-api:neutron-plugin-api': 'neutron-openvswitch:'
 
90
                                              'neutron-plugin-api',
103
91
        }
104
92
        super(NeutronAPIBasicDeployment, self)._add_relations(relations)
 
93
        super(NeutronAPIBasicDeployment, self)._add_relations(relations_more)
105
94
 
106
95
    def _configure_services(self):
107
96
        """Configure all of the services."""
115
104
                openstack_origin_git = {
116
105
                    'repositories': [
117
106
                        {'name': 'requirements',
118
 
                         'repository': 'git://github.com/openstack/requirements',
 
107
                         'repository': 'git://github.com/openstack/requirements',  # noqa
119
108
                         'branch': branch},
120
109
                        {'name': 'neutron-fwaas',
121
 
                         'repository': 'git://github.com/openstack/neutron-fwaas',
 
110
                         'repository': 'git://github.com/openstack/neutron-fwaas',  # noqa
122
111
                         'branch': branch},
123
112
                        {'name': 'neutron-lbaas',
124
 
                         'repository': 'git://github.com/openstack/neutron-lbaas',
 
113
                         'repository': 'git://github.com/openstack/neutron-lbaas',  # noqa
125
114
                         'branch': branch},
126
115
                        {'name': 'neutron-vpnaas',
127
 
                         'repository': 'git://github.com/openstack/neutron-vpnaas',
 
116
                         'repository': 'git://github.com/openstack/neutron-vpnaas',  # noqa
128
117
                         'branch': branch},
129
118
                        {'name': 'neutron',
130
119
                         'repository': 'git://github.com/openstack/neutron',
154
143
                    'http_proxy': amulet_http_proxy,
155
144
                    'https_proxy': amulet_http_proxy,
156
145
                }
157
 
            neutron_api_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
 
146
            neutron_api_config['openstack-origin-git'] = \
 
147
                yaml.dump(openstack_origin_git)
 
148
 
158
149
        keystone_config = {'admin-password': 'openstack',
159
150
                           'admin-token': 'ubuntutesting'}
160
151
        nova_cc_config = {'network-manager': 'Quantum',
171
162
        self.keystone_sentry = self.d.sentry.unit['keystone/0']
172
163
        self.rabbitmq_sentry = self.d.sentry.unit['rabbitmq-server/0']
173
164
        self.nova_cc_sentry = self.d.sentry.unit['nova-cloud-controller/0']
174
 
        self.neutron_gateway_sentry = self.d.sentry.unit['neutron-gateway/0']
 
165
        self.neutron_gw_sentry = self.d.sentry.unit['neutron-gateway/0']
175
166
        self.neutron_api_sentry = self.d.sentry.unit['neutron-api/0']
 
167
        self.neutron_ovs_sentry = self.d.sentry.unit['neutron-openvswitch/0']
176
168
        self.nova_compute_sentry = self.d.sentry.unit['nova-compute/0']
 
169
 
177
170
        u.log.debug('openstack release val: {}'.format(
178
171
            self._get_openstack_release()))
179
172
        u.log.debug('openstack release str: {}'.format(
180
173
            self._get_openstack_release_string()))
181
 
        # Let things settle a bit before moving forward
182
 
        time.sleep(30)
183
 
 
184
174
 
185
175
    def test_100_services(self):
186
176
        """Verify the expected services are running on the corresponding
187
177
           service units."""
188
178
        u.log.debug('Checking status of system services...')
189
 
        # Fails vivid-kilo, bug 1454754
190
 
        neutron_api_services = ['status neutron-server']
191
 
        neutron_services = ['status neutron-dhcp-agent',
192
 
                            'status neutron-lbaas-agent',
193
 
                            'status neutron-metadata-agent',
194
 
                            'status neutron-plugin-openvswitch-agent',
195
 
                            'status neutron-ovs-cleanup']
 
179
        neutron_api_services = ['neutron-server']
 
180
        neutron_services = ['neutron-dhcp-agent',
 
181
                            'neutron-lbaas-agent',
 
182
                            'neutron-metadata-agent',
 
183
                            'neutron-plugin-openvswitch-agent',
 
184
                            'neutron-ovs-cleanup']
196
185
 
197
186
        if self._get_openstack_release() <= self.trusty_juno:
198
 
            neutron_services.append('status neutron-vpn-agent')
 
187
            neutron_services.append('neutron-vpn-agent')
199
188
 
200
189
        if self._get_openstack_release() < self.trusty_kilo:
201
190
            # Juno or earlier
202
 
            neutron_services.append('status neutron-metering-agent')
203
 
 
204
 
        nova_cc_services = ['status nova-api-ec2',
205
 
                            'status nova-api-os-compute',
206
 
                            'status nova-objectstore',
207
 
                            'status nova-cert',
208
 
                            'status nova-scheduler',
209
 
                            'status nova-conductor']
210
 
 
211
 
        commands = {
212
 
            self.mysql_sentry: ['status mysql'],
213
 
            self.keystone_sentry: ['status keystone'],
 
191
            neutron_services.append('neutron-metering-agent')
 
192
 
 
193
        nova_cc_services = ['nova-api-ec2',
 
194
                            'nova-api-os-compute',
 
195
                            'nova-objectstore',
 
196
                            'nova-cert',
 
197
                            'nova-scheduler',
 
198
                            'nova-conductor']
 
199
 
 
200
        services = {
 
201
            self.mysql_sentry: ['mysql'],
 
202
            self.keystone_sentry: ['keystone'],
214
203
            self.nova_cc_sentry: nova_cc_services,
215
 
            self.neutron_gateway_sentry: neutron_services,
 
204
            self.neutron_gw_sentry: neutron_services,
216
205
            self.neutron_api_sentry: neutron_api_services,
217
206
        }
218
207
 
219
 
        ret = u.validate_services(commands)
 
208
        ret = u.validate_services_by_name(services)
220
209
        if ret:
221
210
            amulet.raise_status(amulet.FAIL, msg=ret)
222
211
 
223
212
    def test_200_neutron_api_shared_db_relation(self):
224
213
        """Verify the neutron-api to mysql shared-db relation data"""
225
 
        u.log.debug('Checking neutron-api:mysql relation data...')
 
214
        u.log.debug('Checking neutron-api:mysql db relation data...')
226
215
        unit = self.neutron_api_sentry
227
216
        relation = ['shared-db', 'mysql:shared-db']
228
217
        expected = {
239
228
 
240
229
    def test_201_shared_db_neutron_api_relation(self):
241
230
        """Verify the mysql to neutron-api shared-db relation data"""
242
 
        u.log.debug('Checking mysql:neutron-api relation data...')
 
231
        u.log.debug('Checking mysql:neutron-api db relation data...')
243
232
        unit = self.mysql_sentry
244
233
        relation = ['shared-db', 'neutron-api:shared-db']
245
234
        expected = {
246
235
            'db_host': u.valid_ip,
247
236
            'private-address': u.valid_ip,
 
237
            'password': u.not_null
248
238
        }
249
239
 
250
 
        if self._get_openstack_release() == self.precise_icehouse:
251
 
            # Precise
252
 
            expected['allowed_units'] = 'nova-cloud-controller/0 neutron-api/0'
253
 
        else:
254
 
            # Not Precise
255
 
            expected['allowed_units'] = 'neutron-api/0'
256
 
 
257
240
        ret = u.validate_relation_data(unit, relation, expected)
258
 
        rel_data = unit.relation('shared-db', 'neutron-api:shared-db')
259
 
        if ret or 'password' not in rel_data:
 
241
        if ret:
260
242
            message = u.relation_error('mysql shared-db', ret)
261
243
            amulet.raise_status(amulet.FAIL, msg=message)
262
244
 
281
263
        u.log.debug('Checking amqp:neutron-api relation data...')
282
264
        unit = self.rabbitmq_sentry
283
265
        relation = ['amqp', 'neutron-api:amqp']
284
 
        rel_data = unit.relation('amqp', 'neutron-api:amqp')
285
266
        expected = {
286
267
            'hostname': u.valid_ip,
287
268
            'private-address': u.valid_ip,
 
269
            'password': u.not_null
288
270
        }
289
271
 
290
272
        ret = u.validate_relation_data(unit, relation, expected)
291
 
        if ret or not 'password' in rel_data:
 
273
        if ret:
292
274
            message = u.relation_error('rabbitmq amqp', ret)
293
275
            amulet.raise_status(amulet.FAIL, msg=message)
294
276
 
295
 
    def test_204_neutron_api_identity_relation(self):
 
277
    def test_204_neutron_api_keystone_identity_relation(self):
296
278
        """Verify the neutron-api to keystone identity-service relation data"""
297
 
        u.log.debug('Checking neutron-api:keystone relation data...')
 
279
        u.log.debug('Checking neutron-api:keystone id relation data...')
298
280
        unit = self.neutron_api_sentry
299
281
        relation = ['identity-service', 'keystone:identity-service']
300
282
        api_ip = unit.relation('identity-service',
301
283
                               'keystone:identity-service')['private-address']
302
 
        api_endpoint = "http://%s:9696" % (api_ip)
 
284
        api_endpoint = 'http://{}:9696'.format(api_ip)
303
285
        expected = {
304
286
            'private-address': u.valid_ip,
305
287
            'quantum_region': 'RegionOne',
316
298
 
317
299
    def test_205_keystone_neutron_api_identity_relation(self):
318
300
        """Verify the keystone to neutron-api identity-service relation data"""
319
 
        u.log.debug('Checking keystone:neutron-api relation data...')
 
301
        u.log.debug('Checking keystone:neutron-api id relation data...')
320
302
        unit = self.keystone_sentry
321
303
        relation = ['identity-service', 'neutron-api:identity-service']
322
 
        id_relation = unit.relation('identity-service',
323
 
                                    'neutron-api:identity-service')
324
 
        id_ip = id_relation['private-address']
 
304
        rel_ks_id = unit.relation('identity-service',
 
305
                                  'neutron-api:identity-service')
 
306
        id_ip = rel_ks_id['private-address']
325
307
        expected = {
326
308
            'admin_token': 'ubuntutesting',
327
309
            'auth_host': id_ip,
335
317
            message = u.relation_error('neutron-api identity-service', ret)
336
318
            amulet.raise_status(amulet.FAIL, msg=message)
337
319
 
338
 
    def test_206_neutron_api_plugin_relation(self):
 
320
    def test_206_neutron_api_neutron_ovs_plugin_api_relation(self):
339
321
        """Verify neutron-api to neutron-openvswitch neutron-plugin-api"""
340
 
        u.log.debug('Checking neutron-api:neutron-ovs relation data...')
 
322
        u.log.debug('Checking neutron-api:neutron-ovs plugin-api '
 
323
                    'relation data...')
341
324
        unit = self.neutron_api_sentry
342
325
        relation = ['neutron-plugin-api',
343
326
                    'neutron-openvswitch:neutron-plugin-api']
 
327
 
 
328
        u.log.debug(unit.relation(relation[0], relation[1]))
 
329
        expected = {
 
330
            'auth_host': u.valid_ip,
 
331
            'auth_port': '35357',
 
332
            'auth_protocol': 'http',
 
333
            'enable-dvr': 'False',
 
334
            'enable-l3ha': 'False',
 
335
            'l2-population': 'True',
 
336
            'neutron-security-groups': 'False',
 
337
            'overlay-network-type': 'gre',
 
338
            'private-address': u.valid_ip,
 
339
            'region': 'RegionOne',
 
340
            'service_host': u.valid_ip,
 
341
            'service_password': u.not_null,
 
342
            'service_port': '5000',
 
343
            'service_protocol': 'http',
 
344
            'service_tenant': 'services',
 
345
            'service_username': 'quantum',
 
346
        }
 
347
        ret = u.validate_relation_data(unit, relation, expected)
 
348
        if ret:
 
349
            message = u.relation_error(
 
350
                'neutron-api neutron-ovs neutronplugin-api', ret)
 
351
            amulet.raise_status(amulet.FAIL, msg=message)
 
352
 
 
353
    def test_207_neutron_ovs_neutron_api_plugin_api_relation(self):
 
354
        """Verify neutron-openvswitch to neutron-api neutron-plugin-api"""
 
355
        u.log.debug('Checking neutron-ovs:neutron-api plugin-api '
 
356
                    'relation data...')
 
357
        unit = self.neutron_ovs_sentry
 
358
        relation = ['neutron-plugin-api',
 
359
                    'neutron-api:neutron-plugin-api']
344
360
        expected = {
345
361
            'private-address': u.valid_ip,
346
362
        }
349
365
            message = u.relation_error('neutron-api neutron-plugin-api', ret)
350
366
            amulet.raise_status(amulet.FAIL, msg=message)
351
367
 
352
 
    def test_207_neutron_api_novacc_relation(self):
 
368
    def test_208_neutron_api_novacc_relation(self):
353
369
        """Verify the neutron-api to nova-cloud-controller relation data"""
354
370
        u.log.debug('Checking neutron-api:novacc relation data...')
355
371
        unit = self.neutron_api_sentry
356
372
        relation = ['neutron-api', 'nova-cloud-controller:neutron-api']
357
373
        api_ip = unit.relation('identity-service',
358
374
                               'keystone:identity-service')['private-address']
359
 
        api_endpoint = "http://%s:9696" % (api_ip)
 
375
        api_endpoint = 'http://{}:9696'.format(api_ip)
360
376
        expected = {
361
377
            'private-address': api_ip,
362
378
            'neutron-plugin': 'ovs',
368
384
            message = u.relation_error('neutron-api neutron-api', ret)
369
385
            amulet.raise_status(amulet.FAIL, msg=message)
370
386
 
371
 
    def test_208_novacc_neutron_api_relation(self):
 
387
    def test_209_novacc_neutron_api_relation(self):
372
388
        """Verify the nova-cloud-controller to neutron-api relation data"""
373
389
        u.log.debug('Checking novacc:neutron-api relation data...')
374
390
        unit = self.nova_cc_sentry
375
391
        relation = ['neutron-api', 'neutron-api:neutron-api']
376
392
        cc_ip = unit.relation('neutron-api',
377
393
                              'neutron-api:neutron-api')['private-address']
378
 
        cc_endpoint = "http://%s:8774/v2" % (cc_ip)
 
394
        cc_endpoint = 'http://{}:8774/v2'.format(cc_ip)
379
395
        expected = {
380
396
            'private-address': cc_ip,
381
397
            'nova_url': cc_endpoint,
385
401
            message = u.relation_error('nova-cc neutron-api', ret)
386
402
            amulet.raise_status(amulet.FAIL, msg=message)
387
403
 
388
 
    # XXX Test missing to examine the relation data neutron-openvswitch is
389
 
    #     receiving. Current;y this data cannot be interegated due to
390
 
    #     Bug#1421388
391
 
 
392
 
    def test_900_restart_on_config_change(self):
393
 
        """Verify that the specified services are restarted when the config
394
 
           is changed.
395
 
 
396
 
           Note(coreycb): The method name with the _z_ is a little odd
397
 
           but it forces the test to run last.  It just makes things
398
 
           easier because restarting services requires re-authorization.
399
 
           """
400
 
        u.log.debug('Checking novacc neutron-api relation data...')
401
 
        conf = '/etc/neutron/neutron.conf'
402
 
        services = ['neutron-server']
403
 
        u.log.debug('Making config change on neutron-api service...')
404
 
        self.d.configure('neutron-api', {'use-syslog': 'True'})
405
 
        stime = 60
406
 
        for s in services:
407
 
            u.log.debug("Checking that service restarted: {}".format(s))
408
 
            if not u.service_restarted(self.neutron_api_sentry, s, conf,
409
 
                                       pgrep_full=True, sleep_time=stime):
410
 
                self.d.configure('neutron-api', {'use-syslog': 'False'})
411
 
                msg = "service {} didn't restart after config change".format(s)
412
 
                amulet.raise_status(amulet.FAIL, msg=msg)
413
 
            stime = 0
414
 
        self.d.configure('neutron-api', {'use-syslog': 'False'})
415
 
 
416
404
    def test_300_neutron_config(self):
417
405
        """Verify the data in the neutron config file."""
418
406
        u.log.debug('Checking neutron.conf config file data...')
421
409
                                                   'neutron-api:neutron-api')
422
410
        rabbitmq_relation = self.rabbitmq_sentry.relation('amqp',
423
411
                                                          'neutron-api:amqp')
424
 
        ks_rel = self.keystone_sentry.relation('identity-service',
425
 
                                               'neutron-api:identity-service')
 
412
        rel_napi_ks = self.keystone_sentry.relation(
 
413
            'identity-service', 'neutron-api:identity-service')
426
414
 
427
 
        nova_auth_url = '%s://%s:%s/v2.0' % (ks_rel['auth_protocol'],
428
 
                                             ks_rel['auth_host'],
429
 
                                             ks_rel['auth_port'])
430
 
        db_relation = self.mysql_sentry.relation('shared-db',
 
415
        nova_auth_url = '{}://{}:{}/v2.0'.format(rel_napi_ks['auth_protocol'],
 
416
                                                 rel_napi_ks['auth_host'],
 
417
                                                 rel_napi_ks['auth_port'])
 
418
        rel_napi_db = self.mysql_sentry.relation('shared-db',
431
419
                                                 'neutron-api:shared-db')
432
 
        db_conn = 'mysql://neutron:%s@%s/neutron' % (db_relation['password'],
433
 
                                                     db_relation['db_host'])
 
420
        db_conn = 'mysql://neutron:{}@{}/neutron'.format(
 
421
            rel_napi_db['password'], rel_napi_db['db_host'])
 
422
 
434
423
        conf = '/etc/neutron/neutron.conf'
435
424
        expected = {
436
425
            'DEFAULT': {
439
428
                'bind_port': '9686',
440
429
                'nova_url': cc_relation['nova_url'],
441
430
                'nova_region_name': 'RegionOne',
442
 
                'nova_admin_username': ks_rel['service_username'],
443
 
                'nova_admin_tenant_id': ks_rel['service_tenant_id'],
444
 
                'nova_admin_password': ks_rel['service_password'],
 
431
                'nova_admin_username': rel_napi_ks['service_username'],
 
432
                'nova_admin_tenant_id': rel_napi_ks['service_tenant_id'],
 
433
                'nova_admin_password': rel_napi_ks['service_password'],
445
434
                'nova_admin_auth_url': nova_auth_url,
446
435
            },
447
436
            'keystone_authtoken': {
448
437
                'signing_dir': '/var/cache/neutron',
449
438
                'admin_tenant_name': 'services',
450
439
                'admin_user': 'quantum',
451
 
                'admin_password': ks_rel['service_password'],
 
440
                'admin_password': rel_napi_ks['service_password'],
452
441
            },
453
442
            'database': {
454
443
                'connection': db_conn,
457
446
 
458
447
        if self._get_openstack_release() >= self.trusty_kilo:
459
448
            # Kilo or later
460
 
            expected.update(
461
 
                {
462
 
                    'oslo_messaging_rabbit': {
463
 
                        'rabbit_userid': 'neutron',
464
 
                        'rabbit_virtual_host': 'openstack',
465
 
                        'rabbit_password': rabbitmq_relation['password'],
466
 
                        'rabbit_host': rabbitmq_relation['hostname']
467
 
                    }
468
 
                }
469
 
            )
 
449
            expected['oslo_messaging_rabbit'] = {
 
450
                'rabbit_userid': 'neutron',
 
451
                'rabbit_virtual_host': 'openstack',
 
452
                'rabbit_password': rabbitmq_relation['password'],
 
453
                'rabbit_host': rabbitmq_relation['hostname']
 
454
            }
470
455
        else:
471
456
            # Juno or earlier
472
 
            expected['DEFAULT'].update(
473
 
                {
474
 
                    'rabbit_userid': 'neutron',
475
 
                    'rabbit_virtual_host': 'openstack',
476
 
                    'rabbit_password': rabbitmq_relation['password'],
477
 
                    'rabbit_host': rabbitmq_relation['hostname']
478
 
                }
479
 
            )
480
 
            expected['keystone_authtoken'].update(
481
 
                {
482
 
                    'service_protocol': ks_rel['service_protocol'],
483
 
                    'service_host': ks_rel['service_host'],
484
 
                    'service_port': ks_rel['service_port'],
485
 
                    'auth_host': ks_rel['auth_host'],
486
 
                    'auth_port': ks_rel['auth_port'],
487
 
                    'auth_protocol':  ks_rel['auth_protocol']
488
 
                }
489
 
            )
 
457
            expected['DEFAULT'].update({
 
458
                'rabbit_userid': 'neutron',
 
459
                'rabbit_virtual_host': 'openstack',
 
460
                'rabbit_password': rabbitmq_relation['password'],
 
461
                'rabbit_host': rabbitmq_relation['hostname']
 
462
            })
 
463
            expected['keystone_authtoken'].update({
 
464
                'service_protocol': rel_napi_ks['service_protocol'],
 
465
                'service_host': rel_napi_ks['service_host'],
 
466
                'service_port': rel_napi_ks['service_port'],
 
467
                'auth_host': rel_napi_ks['auth_host'],
 
468
                'auth_port': rel_napi_ks['auth_port'],
 
469
                'auth_protocol':  rel_napi_ks['auth_protocol']
 
470
            })
490
471
 
491
472
        for section, pairs in expected.iteritems():
492
473
            ret = u.validate_config_data(unit, conf, section, pairs)
504
485
 
505
486
        expected = {
506
487
            'ml2': {
507
 
                'type_drivers': 'gre,vlan,flat',
508
 
                'tenant_network_types': 'gre,vlan,flat',
 
488
                'type_drivers': 'gre,vlan,flat,local',
 
489
                'tenant_network_types': 'gre,vlan,flat,local',
509
490
            },
510
491
            'ml2_type_gre': {
511
492
                'tunnel_id_ranges': '1:1000'
527
508
 
528
509
        if self._get_openstack_release() >= self.trusty_kilo:
529
510
            # Kilo or later
530
 
            expected['ml2'].update(
531
 
                {
532
 
                    'mechanism_drivers': 'openvswitch,l2population'
533
 
                }
534
 
            )
 
511
            expected['ml2'].update({
 
512
                'mechanism_drivers': 'openvswitch,l2population'
 
513
            })
535
514
        else:
536
515
            # Juno or earlier
537
 
            expected['ml2'].update(
538
 
                {
539
 
                    'mechanism_drivers': 'openvswitch,hyperv,l2population'
540
 
                }
541
 
            )
 
516
            expected['ml2'].update({
 
517
                'mechanism_drivers': 'openvswitch,hyperv,l2population'
 
518
            })
542
519
 
543
520
        for section, pairs in expected.iteritems():
544
521
            ret = u.validate_config_data(unit, conf, section, pairs)
545
522
            if ret:
546
523
                message = "ml2 config error: {}".format(ret)
547
524
                amulet.raise_status(amulet.FAIL, msg=message)
 
525
 
 
526
    def test_900_restart_on_config_change(self):
 
527
        """Verify that the specified services are restarted when the
 
528
        config is changed."""
 
529
 
 
530
        sentry = self.neutron_api_sentry
 
531
        juju_service = 'neutron-api'
 
532
 
 
533
        # Expected default and alternate values
 
534
        set_default = {'debug': 'False'}
 
535
        set_alternate = {'debug': 'True'}
 
536
 
 
537
        # Services which are expected to restart upon config change,
 
538
        # and corresponding config files affected by the change
 
539
        services = {'neutron-server': '/etc/neutron/neutron.conf'}
 
540
 
 
541
        # Make config change, check for service restarts
 
542
        u.log.debug('Making config change on {}...'.format(juju_service))
 
543
        mtime = u.get_sentry_time(sentry)
 
544
        self.d.configure(juju_service, set_alternate)
 
545
 
 
546
        for s, conf_file in services.iteritems():
 
547
            u.log.debug("Checking that service restarted: {}".format(s))
 
548
            if not u.validate_service_config_changed(sentry, mtime, s,
 
549
                                                     conf_file,
 
550
                                                     retry_count=4,
 
551
                                                     retry_sleep_time=20,
 
552
                                                     sleep_time=20):
 
553
                self.d.configure(juju_service, set_default)
 
554
                msg = "service {} didn't restart after config change".format(s)
 
555
                amulet.raise_status(amulet.FAIL, msg=msg)
 
556
 
 
557
        self.d.configure(juju_service, set_default)
 
558
        u.log.debug('OK')