~brad-marshall/charms/trusty/keystone/haproxy-add-timeout

« back to all changes in this revision

Viewing changes to tests/basic_deployment.py

  • Committer: Ryan Beisner
  • Date: 2015-07-01 20:45:00 UTC
  • mto: This revision was merged to the branch mainline in revision 157.
  • Revision ID: ryan.beisner@canonical.com-20150701204500-2wcorz2342iga7q0
update amulet tests; update metadata tags

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
2
 
 
3
"""
 
4
Basic keystone amulet functional tests.
 
5
"""
 
6
 
3
7
import amulet
4
8
import os
 
9
import time
5
10
import yaml
6
11
 
7
12
from charmhelpers.contrib.openstack.amulet.deployment import (
10
15
 
11
16
from charmhelpers.contrib.openstack.amulet.utils import (
12
17
    OpenStackAmuletUtils,
13
 
    DEBUG, # flake8: noqa
14
 
    ERROR
 
18
    DEBUG,
 
19
    # ERROR
15
20
)
16
21
 
17
22
# Use DEBUG to turn on debug logging
21
26
class KeystoneBasicDeployment(OpenStackAmuletDeployment):
22
27
    """Amulet tests on a basic keystone deployment."""
23
28
 
24
 
    def __init__(self, series=None, openstack=None, source=None, git=False, stable=False):
 
29
    def __init__(self, series=None, openstack=None,
 
30
                 source=None, git=False, stable=False):
25
31
        """Deploy the entire test environment."""
26
 
        super(KeystoneBasicDeployment, self).__init__(series, openstack, source, stable)
 
32
        super(KeystoneBasicDeployment, self).__init__(series, openstack,
 
33
                                                      source, stable)
27
34
        self.git = git
28
35
        self._add_services()
29
36
        self._add_relations()
39
46
           compatible with the local charm (e.g. stable or next).
40
47
           """
41
48
        this_service = {'name': 'keystone'}
42
 
        other_services = [{'name': 'mysql'}, {'name': 'cinder'}]
 
49
        other_services = [{'name': 'mysql'},
 
50
                          {'name': 'cinder'}]
43
51
        super(KeystoneBasicDeployment, self)._add_services(this_service,
44
52
                                                           other_services)
45
53
 
69
77
                'http_proxy': amulet_http_proxy,
70
78
                'https_proxy': amulet_http_proxy,
71
79
            }
72
 
            keystone_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
 
80
            keystone_config['openstack-origin-git'] = \
 
81
                yaml.dump(openstack_origin_git)
73
82
 
74
83
        mysql_config = {'dataset-size': '50%'}
75
84
        cinder_config = {'block-device': 'None'}
76
 
        configs = {'keystone': keystone_config,
77
 
                   'mysql': mysql_config,
78
 
                   'cinder': cinder_config}
 
85
        configs = {
 
86
            'keystone': keystone_config,
 
87
            'mysql': mysql_config,
 
88
            'cinder': cinder_config
 
89
        }
79
90
        super(KeystoneBasicDeployment, self)._configure_services(configs)
80
91
 
81
92
    def _initialize_tests(self):
84
95
        self.mysql_sentry = self.d.sentry.unit['mysql/0']
85
96
        self.keystone_sentry = self.d.sentry.unit['keystone/0']
86
97
        self.cinder_sentry = self.d.sentry.unit['cinder/0']
 
98
        u.log.debug('openstack release val: {}'.format(
 
99
            self._get_openstack_release()))
 
100
        u.log.debug('openstack release str: {}'.format(
 
101
            self._get_openstack_release_string()))
 
102
 
 
103
        # Let things settle a bit before moving forward
 
104
        time.sleep(30)
87
105
 
88
106
        # Authenticate keystone admin
89
107
        self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
100
118
                                                  description='demo tenant',
101
119
                                                  enabled=True)
102
120
            self.keystone.roles.create(name=self.demo_role)
103
 
            self.keystone.users.create(name=self.demo_user, password='password',
 
121
            self.keystone.users.create(name=self.demo_user,
 
122
                                       password='password',
104
123
                                       tenant_id=tenant.id,
105
124
                                       email='demo@demo.com')
106
125
 
107
126
        # Authenticate keystone demo
108
 
        self.keystone_demo = u.authenticate_keystone_user(self.keystone,
109
 
                                                        user=self.demo_user,
110
 
                                                        password='password',
111
 
                                                        tenant=self.demo_tenant)
 
127
        self.keystone_demo = u.authenticate_keystone_user(
 
128
            self.keystone, user=self.demo_user,
 
129
            password='password', tenant=self.demo_tenant)
112
130
 
113
 
    def test_services(self):
 
131
    def test_100_services(self):
114
132
        """Verify the expected services are running on the corresponding
115
133
           service units."""
116
 
        commands = {
117
 
            self.mysql_sentry: ['status mysql'],
118
 
            self.keystone_sentry: ['status keystone'],
119
 
            self.cinder_sentry: ['status cinder-api', 'status cinder-scheduler',
120
 
                                 'status cinder-volume']
 
134
        services = {
 
135
            self.mysql_sentry: ['mysql'],
 
136
            self.keystone_sentry: ['keystone'],
 
137
            self.cinder_sentry: ['cinder-api',
 
138
                                 'cinder-scheduler',
 
139
                                 'cinder-volume']
121
140
        }
122
 
        ret = u.validate_services(commands)
 
141
        ret = u.validate_services_by_name(services)
123
142
        if ret:
124
143
            amulet.raise_status(amulet.FAIL, msg=ret)
125
144
 
126
 
    def test_tenants(self):
 
145
    def test_102_keystone_tenants(self):
127
146
        """Verify all existing tenants."""
128
 
        tenant1 = {'enabled': True,
129
 
                   'description': 'Created by Juju',
130
 
                   'name': 'services',
131
 
                   'id': u.not_null}
132
 
        tenant2 = {'enabled': True,
133
 
                   'description': 'demo tenant',
134
 
                   'name': 'demoTenant',
135
 
                   'id': u.not_null}
136
 
        tenant3 = {'enabled': True,
137
 
                   'description': 'Created by Juju',
138
 
                   'name': 'admin',
139
 
                   'id': u.not_null}
140
 
        expected = [tenant1, tenant2, tenant3]
 
147
        u.log.debug('Checking keystone tenants...')
 
148
        expected = [
 
149
            {'name': 'services',
 
150
             'enabled': True,
 
151
             'description': 'Created by Juju',
 
152
             'id': u.not_null},
 
153
            {'name': 'demoTenant',
 
154
             'enabled': True,
 
155
             'description': 'demo tenant',
 
156
             'id': u.not_null},
 
157
            {'name': 'admin',
 
158
             'enabled': True,
 
159
             'description': 'Created by Juju',
 
160
             'id': u.not_null}
 
161
        ]
141
162
        actual = self.keystone.tenants.list()
142
163
 
143
164
        ret = u.validate_tenant_data(expected, actual)
144
165
        if ret:
145
166
            amulet.raise_status(amulet.FAIL, msg=ret)
146
167
 
147
 
    def test_roles(self):
 
168
    def test_104_keystone_roles(self):
148
169
        """Verify all existing roles."""
149
 
        role1 = {'name': 'demoRole', 'id': u.not_null}
150
 
        role2 = {'name': 'Admin', 'id': u.not_null}
151
 
        expected = [role1, role2]
 
170
        u.log.debug('Checking keystone roles...')
 
171
        expected = [
 
172
            {'name': 'demoRole',
 
173
             'id': u.not_null},
 
174
            {'name': 'Admin',
 
175
             'id': u.not_null}
 
176
        ]
152
177
        actual = self.keystone.roles.list()
153
178
 
154
179
        ret = u.validate_role_data(expected, actual)
155
180
        if ret:
156
181
            amulet.raise_status(amulet.FAIL, msg=ret)
157
182
 
158
 
    def test_users(self):
 
183
    def test_106_keystone_users(self):
159
184
        """Verify all existing roles."""
160
 
        user1 = {'name': 'demoUser',
161
 
                 'enabled': True,
162
 
                 'tenantId': u.not_null,
163
 
                 'id': u.not_null,
164
 
                 'email': 'demo@demo.com'}
165
 
        user2 = {'name': 'admin',
166
 
                 'enabled': True,
167
 
                 'tenantId': u.not_null,
168
 
                 'id': u.not_null,
169
 
                 'email': 'juju@localhost'}
170
 
        user3 = {'name': 'cinder_cinderv2',
171
 
                 'enabled': True,
172
 
                 'tenantId': u.not_null,
173
 
                 'id': u.not_null,
174
 
                 'email': u'juju@localhost'}
175
 
        expected = [user1, user2, user3]
 
185
        u.log.debug('Checking keystone users...')
 
186
        expected = [
 
187
            {'name': 'demoUser',
 
188
             'enabled': True,
 
189
             'tenantId': u.not_null,
 
190
             'id': u.not_null,
 
191
             'email': 'demo@demo.com'},
 
192
            {'name': 'admin',
 
193
             'enabled': True,
 
194
             'tenantId': u.not_null,
 
195
             'id': u.not_null,
 
196
             'email': 'juju@localhost'},
 
197
            {'name': 'cinder_cinderv2',
 
198
             'enabled': True,
 
199
             'tenantId': u.not_null,
 
200
             'id': u.not_null,
 
201
             'email': u'juju@localhost'}
 
202
        ]
176
203
        actual = self.keystone.users.list()
177
204
        ret = u.validate_user_data(expected, actual)
178
205
        if ret:
179
206
            amulet.raise_status(amulet.FAIL, msg=ret)
180
207
 
181
 
    def test_service_catalog(self):
 
208
    def test_108_service_catalog(self):
182
209
        """Verify that the service catalog endpoint data is valid."""
183
 
        endpoint_vol = {'adminURL': u.valid_url,
184
 
                        'region': 'RegionOne',
185
 
                        'publicURL': u.valid_url,
186
 
                        'internalURL': u.valid_url}
187
 
        endpoint_id = {'adminURL': u.valid_url,
188
 
                       'region': 'RegionOne',
189
 
                       'publicURL': u.valid_url,
190
 
                       'internalURL': u.valid_url}
191
 
        if self._get_openstack_release() > self.precise_essex:
192
 
            endpoint_vol['id'] = u.not_null
193
 
            endpoint_id['id'] = u.not_null
194
 
        expected = {'volume': [endpoint_vol], 'identity': [endpoint_id]}
195
 
        actual = self.keystone_demo.service_catalog.get_endpoints()
 
210
        u.log.debug('Checking keystone service catalog...')
 
211
        endpoint_check = {
 
212
            'adminURL': u.valid_url,
 
213
            'id': u.not_null,
 
214
            'region': 'RegionOne',
 
215
            'publicURL': u.valid_url,
 
216
            'internalURL': u.valid_url
 
217
        }
 
218
        expected = {
 
219
            'volume': [endpoint_check],
 
220
            'identity': [endpoint_check]
 
221
        }
 
222
        actual = self.keystone.service_catalog.get_endpoints()
196
223
 
197
224
        ret = u.validate_svc_catalog_endpoint_data(expected, actual)
198
225
        if ret:
199
226
            amulet.raise_status(amulet.FAIL, msg=ret)
200
227
 
201
 
    def test_keystone_endpoint(self):
 
228
    def test_110_keystone_endpoint(self):
202
229
        """Verify the keystone endpoint data."""
 
230
        u.log.debug('Checking keystone api endpoint data...')
203
231
        endpoints = self.keystone.endpoints.list()
204
232
        admin_port = '35357'
205
233
        internal_port = public_port = '5000'
206
 
        expected = {'id': u.not_null,
207
 
                    'region': 'RegionOne',
208
 
                    'adminurl': u.valid_url,
209
 
                    'internalurl': u.valid_url,
210
 
                    'publicurl': u.valid_url,
211
 
                    'service_id': u.not_null}
 
234
        expected = {
 
235
            'id': u.not_null,
 
236
            'region': 'RegionOne',
 
237
            'adminurl': u.valid_url,
 
238
            'internalurl': u.valid_url,
 
239
            'publicurl': u.valid_url,
 
240
            'service_id': u.not_null
 
241
        }
212
242
        ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
213
243
                                       public_port, expected)
214
244
        if ret:
215
245
            amulet.raise_status(amulet.FAIL,
216
246
                                msg='keystone endpoint: {}'.format(ret))
217
247
 
218
 
    def test_cinder_endpoint(self):
 
248
    def test_112_cinder_endpoint(self):
219
249
        """Verify the cinder endpoint data."""
 
250
        u.log.debug('Checking cinder endpoint...')
220
251
        endpoints = self.keystone.endpoints.list()
221
252
        admin_port = internal_port = public_port = '8776'
222
 
        expected = {'id': u.not_null,
223
 
                    'region': 'RegionOne',
224
 
                    'adminurl': u.valid_url,
225
 
                    'internalurl': u.valid_url,
226
 
                    'publicurl': u.valid_url,
227
 
                    'service_id': u.not_null}
 
253
        expected = {
 
254
            'id': u.not_null,
 
255
            'region': 'RegionOne',
 
256
            'adminurl': u.valid_url,
 
257
            'internalurl': u.valid_url,
 
258
            'publicurl': u.valid_url,
 
259
            'service_id': u.not_null
 
260
        }
 
261
 
228
262
        ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
229
263
                                       public_port, expected)
230
264
        if ret:
231
265
            amulet.raise_status(amulet.FAIL,
232
266
                                msg='cinder endpoint: {}'.format(ret))
233
267
 
234
 
    def test_keystone_shared_db_relation(self):
 
268
    def test_200_keystone_mysql_shared_db_relation(self):
235
269
        """Verify the keystone shared-db relation data"""
 
270
        u.log.debug('Checking keystone to mysql db relation data...')
236
271
        unit = self.keystone_sentry
237
272
        relation = ['shared-db', 'mysql:shared-db']
238
273
        expected = {
246
281
            message = u.relation_error('keystone shared-db', ret)
247
282
            amulet.raise_status(amulet.FAIL, msg=message)
248
283
 
249
 
    def test_mysql_shared_db_relation(self):
 
284
    def test_201_mysql_keystone_shared_db_relation(self):
250
285
        """Verify the mysql shared-db relation data"""
 
286
        u.log.debug('Checking mysql to keystone db relation data...')
251
287
        unit = self.mysql_sentry
252
288
        relation = ['shared-db', 'keystone:shared-db']
253
289
        expected_data = {
260
296
            message = u.relation_error('mysql shared-db', ret)
261
297
            amulet.raise_status(amulet.FAIL, msg=message)
262
298
 
263
 
    def test_keystone_identity_service_relation(self):
 
299
    def test_202_keystone_cinder_identity_service_relation(self):
264
300
        """Verify the keystone identity-service relation data"""
 
301
        u.log.debug('Checking keystone to cinder id relation data...')
265
302
        unit = self.keystone_sentry
266
303
        relation = ['identity-service', 'cinder:identity-service']
267
304
        expected = {
283
320
            message = u.relation_error('keystone identity-service', ret)
284
321
            amulet.raise_status(amulet.FAIL, msg=message)
285
322
 
286
 
    def test_cinder_identity_service_relation(self):
 
323
    def test_203_cinder_keystone_identity_service_relation(self):
287
324
        """Verify the cinder identity-service relation data"""
 
325
        u.log.debug('Checking cinder to keystone id relation data...')
288
326
        unit = self.cinder_sentry
289
327
        relation = ['identity-service', 'keystone:identity-service']
290
328
        expected = {
305
343
            message = u.relation_error('cinder identity-service', ret)
306
344
            amulet.raise_status(amulet.FAIL, msg=message)
307
345
 
308
 
    def test_z_restart_on_config_change(self):
309
 
        """Verify that keystone is restarted when the config is changed.
310
 
 
311
 
            Note(coreycb): The method name with the _z_ is a little odd
312
 
            but it forces the test to run last.  It just makes things
313
 
            easier because restarting services requires re-authorization.
314
 
            """
315
 
        self.d.configure('keystone', {'verbose': 'True'})
316
 
        if not u.service_restarted(self.keystone_sentry, 'keystone-all',
317
 
                                  '/etc/keystone/keystone.conf',
318
 
                                  sleep_time=30):
319
 
            self.d.configure('keystone', {'verbose': 'False'})
320
 
            message = "keystone service didn't restart after config change"
321
 
            amulet.raise_status(amulet.FAIL, msg=message)
322
 
        self.d.configure('keystone', {'verbose': 'False'})
323
 
 
324
 
    def test_default_config(self):
325
 
        """Verify the data in the keystone config file's default section,
 
346
    def test_300_keystone_default_config(self):
 
347
        """Verify the data in the keystone config file,
326
348
           comparing some of the variables vs relation data."""
327
 
        unit = self.keystone_sentry
328
 
        conf = '/etc/keystone/keystone.conf'
329
 
        relation = unit.relation('identity-service', 'cinder:identity-service')
330
 
        expected = {'admin_token': relation['admin_token'],
331
 
                    'admin_port': '35347',
332
 
                    'public_port': '4990',
333
 
                    'use_syslog': 'False',
334
 
                    'log_config': '/etc/keystone/logging.conf',
335
 
                    'debug': 'False',
336
 
                    'verbose': 'False'}
337
 
 
338
 
        ret = u.validate_config_data(unit, conf, 'DEFAULT', expected)
339
 
        if ret:
340
 
            message = "keystone config error: {}".format(ret)
341
 
            amulet.raise_status(amulet.FAIL, msg=message)
342
 
 
343
 
    def test_database_config(self):
344
 
        """Verify the data in the keystone config file's database (or sql
345
 
           depending on release) section, comparing vs relation data."""
346
 
        unit = self.keystone_sentry
347
 
        conf = '/etc/keystone/keystone.conf'
348
 
        relation = self.mysql_sentry.relation('shared-db', 'keystone:shared-db')
349
 
        db_uri = "mysql://{}:{}@{}/{}".format('keystone', relation['password'],
350
 
                                              relation['db_host'], 'keystone')
351
 
        expected = {'connection': db_uri, 'idle_timeout': '200'}
352
 
 
353
 
        if self._get_openstack_release() > self.precise_havana:
354
 
            ret = u.validate_config_data(unit, conf, 'database', expected)
 
349
        u.log.debug('Checking keystone config file...')
 
350
        unit = self.keystone_sentry
 
351
        conf = '/etc/keystone/keystone.conf'
 
352
        ks_ci_rel = unit.relation('identity-service',
 
353
                                  'cinder:identity-service')
 
354
        my_ks_rel = self.mysql_sentry.relation('shared-db',
 
355
                                               'keystone:shared-db')
 
356
        db_uri = "mysql://{}:{}@{}/{}".format('keystone',
 
357
                                              my_ks_rel['password'],
 
358
                                              my_ks_rel['db_host'],
 
359
                                              'keystone')
 
360
        expected = {
 
361
            'DEFAULT': {
 
362
                'debug': 'False',
 
363
                'verbose': 'False',
 
364
                'admin_token': ks_ci_rel['admin_token'],
 
365
                'use_syslog': 'False',
 
366
                'log_config': '/etc/keystone/logging.conf',
 
367
                'public_endpoint': u.valid_url,  # get specific
 
368
                'admin_endpoint': u.valid_url,  # get specific
 
369
            },
 
370
            'extra_headers': {
 
371
                'Distribution': 'Ubuntu'
 
372
            },
 
373
            'database': {
 
374
                'connection': db_uri,
 
375
                'idle_timeout': '200'
 
376
            }
 
377
        }
 
378
 
 
379
        if self._get_openstack_release() >= self.trusty_kilo:
 
380
            # Kilo and later
 
381
            expected['eventlet_server'] = {
 
382
                'admin_bind_host': '0.0.0.0',
 
383
                'public_bind_host': '0.0.0.0',
 
384
                'admin_port': '35347',
 
385
                'public_port': '4990',
 
386
            }
355
387
        else:
356
 
            ret = u.validate_config_data(unit, conf, 'sql', expected)
357
 
        if ret:
358
 
            message = "keystone config error: {}".format(ret)
359
 
            amulet.raise_status(amulet.FAIL, msg=message)
 
388
            # Juno and earlier
 
389
            expected['DEFAULT'].update({
 
390
                'admin_port': '35347',
 
391
                'public_port': '4990',
 
392
                'bind_host': '0.0.0.0',
 
393
            })
 
394
 
 
395
        for section, pairs in expected.iteritems():
 
396
            ret = u.validate_config_data(unit, conf, section, pairs)
 
397
            if ret:
 
398
                message = "keystone config error: {}".format(ret)
 
399
                amulet.raise_status(amulet.FAIL, msg=message)
 
400
 
 
401
    def test_302_keystone_logging_config(self):
 
402
        """Verify the data in the keystone logging config file"""
 
403
        u.log.debug('Checking keystone config file...')
 
404
        unit = self.keystone_sentry
 
405
        conf = '/etc/keystone/logging.conf'
 
406
        expected = {
 
407
            'logger_root': {
 
408
                'level': 'WARNING',
 
409
                'handlers': 'file',
 
410
            },
 
411
            'handlers': {
 
412
                'keys': 'production,file,devel'
 
413
            },
 
414
            'handler_file': {
 
415
                'level': 'DEBUG',
 
416
                'args': "('/var/log/keystone/keystone.log', 'a')"
 
417
            }
 
418
        }
 
419
 
 
420
        for section, pairs in expected.iteritems():
 
421
            ret = u.validate_config_data(unit, conf, section, pairs)
 
422
            if ret:
 
423
                message = "keystone logging config error: {}".format(ret)
 
424
                amulet.raise_status(amulet.FAIL, msg=message)
 
425
 
 
426
    def test_900_keystone_restart_on_config_change(self):
 
427
        """Verify that the specified services are restarted when the config
 
428
           is changed."""
 
429
        sentry = self.keystone_sentry
 
430
        juju_service = 'keystone'
 
431
 
 
432
        # Expected default and alternate values
 
433
        set_default = {'use-syslog': 'False'}
 
434
        set_alternate = {'use-syslog': 'True'}
 
435
 
 
436
        # Config file affected by juju set config change
 
437
        conf_file = '/etc/keystone/keystone.conf'
 
438
 
 
439
        # Services which are expected to restart upon config change
 
440
        services = ['keystone-all']
 
441
 
 
442
        # Make config change, check for service restarts
 
443
        u.log.debug('Making config change on {}...'.format(juju_service))
 
444
        self.d.configure(juju_service, set_alternate)
 
445
 
 
446
        sleep_time = 30
 
447
        for s in services:
 
448
            u.log.debug("Checking that service restarted: {}".format(s))
 
449
            if not u.service_restarted(sentry, s,
 
450
                                       conf_file, sleep_time=sleep_time):
 
451
                self.d.configure(juju_service, set_default)
 
452
                msg = "service {} didn't restart after config change".format(s)
 
453
                amulet.raise_status(amulet.FAIL, msg=msg)
 
454
            sleep_time = 0
 
455
 
 
456
        self.d.configure(juju_service, set_default)