~1chb1n/charms/trusty/swift-proxy/next.1601-test-update1

« back to all changes in this revision

Viewing changes to tests/basic_deployment.py

  • Committer: Corey Bryant
  • Date: 2015-10-05 20:22:22 UTC
  • mfrom: (105.1.11 swift-proxy)
  • Revision ID: corey.bryant@canonical.com-20151005202222-e6hc66n0h3w8csvf
[beisner,r=gnuoy] Amulet test updates and cleanup.

Update amulet tests, enable T-K, V-K, prep for T-L and W-L. Clean up
old lint, remove tests for deprecated releases.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import time
1
2
import amulet
2
3
import swiftclient
3
4
 
7
8
 
8
9
from charmhelpers.contrib.openstack.amulet.utils import (
9
10
    OpenStackAmuletUtils,
10
 
    DEBUG, # flake8: noqa
11
 
    ERROR
 
11
    DEBUG
12
12
)
13
13
 
14
14
# Use DEBUG to turn on debug logging
36
36
           compatible with the local charm (e.g. stable or next).
37
37
           """
38
38
        this_service = {'name': 'swift-proxy'}
39
 
        other_services = [{'name': 'mysql'}, {'name': 'keystone'},
40
 
                          {'name': 'glance'}, {'name': 'swift-storage'}]
 
39
        other_services = [{'name': 'mysql'},
 
40
                          {'name': 'keystone'},
 
41
                          {'name': 'glance'},
 
42
                          {'name': 'swift-storage'}]
41
43
        super(SwiftProxyBasicDeployment, self)._add_services(this_service,
42
44
                                                             other_services)
43
45
 
44
46
    def _add_relations(self):
45
47
        """Add all of the relations for the services."""
46
48
        relations = {
47
 
          'keystone:shared-db': 'mysql:shared-db',
48
 
          'swift-proxy:identity-service': 'keystone:identity-service',
49
 
          'swift-storage:swift-storage': 'swift-proxy:swift-storage',
50
 
          'glance:identity-service': 'keystone:identity-service',
51
 
          'glance:shared-db': 'mysql:shared-db',
52
 
          'glance:object-store': 'swift-proxy:object-store'
 
49
            'keystone:shared-db': 'mysql:shared-db',
 
50
            'swift-proxy:identity-service': 'keystone:identity-service',
 
51
            'swift-storage:swift-storage': 'swift-proxy:swift-storage',
 
52
            'glance:identity-service': 'keystone:identity-service',
 
53
            'glance:shared-db': 'mysql:shared-db',
 
54
            'glance:object-store': 'swift-proxy:object-store'
53
55
        }
54
56
        super(SwiftProxyBasicDeployment, self)._add_relations(relations)
55
57
 
56
58
    def _configure_services(self):
57
59
        """Configure all of the services."""
58
 
        keystone_config = {'admin-password': 'openstack',
59
 
                           'admin-token': 'ubuntutesting'}
60
 
        swift_proxy_config = {'zone-assignment': 'manual',
61
 
                           'replicas': '1',
62
 
                           'swift-hash': 'fdfef9d4-8b06-11e2-8ac0-531c923c8fae'}
63
 
        swift_storage_config = {'zone': '1',
64
 
                                'block-device': 'vdb',
65
 
                                'overwrite': 'true'}
66
 
        configs = {'keystone': keystone_config,
67
 
                   'swift-proxy': swift_proxy_config,
68
 
                   'swift-storage': swift_storage_config}
 
60
        keystone_config = {
 
61
            'admin-password': 'openstack',
 
62
            'admin-token': 'ubuntutesting'
 
63
        }
 
64
        swift_proxy_config = {
 
65
            'zone-assignment': 'manual',
 
66
            'replicas': '1',
 
67
            'swift-hash': 'fdfef9d4-8b06-11e2-8ac0-531c923c8fae'
 
68
        }
 
69
        swift_storage_config = {
 
70
            'zone': '1',
 
71
            'block-device': 'vdb',
 
72
            'overwrite': 'true'
 
73
        }
 
74
        configs = {
 
75
            'keystone': keystone_config,
 
76
            'swift-proxy': swift_proxy_config,
 
77
            'swift-storage': swift_storage_config
 
78
        }
69
79
        super(SwiftProxyBasicDeployment, self)._configure_services(configs)
70
80
 
71
81
    def _initialize_tests(self):
77
87
        self.swift_proxy_sentry = self.d.sentry.unit['swift-proxy/0']
78
88
        self.swift_storage_sentry = self.d.sentry.unit['swift-storage/0']
79
89
 
 
90
        u.log.debug('openstack release val: {}'.format(
 
91
            self._get_openstack_release()))
 
92
        u.log.debug('openstack release str: {}'.format(
 
93
            self._get_openstack_release_string()))
 
94
 
 
95
        # Let things settle a bit before moving forward
 
96
        time.sleep(30)
 
97
 
80
98
        # Authenticate admin with keystone
81
99
        self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
82
100
                                                      user='admin',
87
105
        self.glance = u.authenticate_glance_admin(self.keystone)
88
106
 
89
107
        # Authenticate swift user
90
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
91
 
                                                 'swift-proxy:identity-service')
 
108
        keystone_relation = self.keystone_sentry.relation(
 
109
            'identity-service', 'swift-proxy:identity-service')
92
110
        ep = self.keystone.service_catalog.url_for(service_type='identity',
93
111
                                                   endpoint_type='publicURL')
94
 
        self.swift = swiftclient.Connection(authurl=ep,
95
 
                                user=keystone_relation['service_username'],
96
 
                                key=keystone_relation['service_password'],
97
 
                                tenant_name=keystone_relation['service_tenant'],
98
 
                                auth_version='2.0')
 
112
        self.swift = swiftclient.Connection(
 
113
            authurl=ep,
 
114
            user=keystone_relation['service_username'],
 
115
            key=keystone_relation['service_password'],
 
116
            tenant_name=keystone_relation['service_tenant'],
 
117
            auth_version='2.0')
99
118
 
100
119
        # Create a demo tenant/role/user
101
120
        self.demo_tenant = 'demoTenant'
117
136
                                         password='password',
118
137
                                         tenant=self.demo_tenant)
119
138
 
120
 
    def test_services(self):
 
139
    def test_100_services(self):
121
140
        """Verify the expected services are running on the corresponding
122
141
           service units."""
123
 
        swift_storage_services = ['status swift-account',
124
 
                                  'status swift-account-auditor',
125
 
                                  'status swift-account-reaper',
126
 
                                  'status swift-account-replicator',
127
 
                                  'status swift-container',
128
 
                                  'status swift-container-auditor',
129
 
                                  'status swift-container-replicator',
130
 
                                  'status swift-container-updater',
131
 
                                  'status swift-object',
132
 
                                  'status swift-object-auditor',
133
 
                                  'status swift-object-replicator',
134
 
                                  'status swift-object-updater']
135
 
        if self._get_openstack_release() >= self.precise_icehouse:
136
 
            swift_storage_services.append('status swift-container-sync')
137
 
 
138
 
        commands = {
139
 
            self.mysql_sentry: ['status mysql'],
140
 
            self.keystone_sentry: ['status keystone'],
141
 
            self.glance_sentry: ['status glance-registry', 'status glance-api'],
142
 
            self.swift_proxy_sentry: ['status swift-proxy'],
 
142
        u.log.debug('Checking system services...')
 
143
        swift_storage_services = ['swift-account',
 
144
                                  'swift-account-auditor',
 
145
                                  'swift-account-reaper',
 
146
                                  'swift-account-replicator',
 
147
                                  'swift-container',
 
148
                                  'swift-container-auditor',
 
149
                                  'swift-container-replicator',
 
150
                                  'swift-container-updater',
 
151
                                  'swift-object',
 
152
                                  'swift-object-auditor',
 
153
                                  'swift-object-replicator',
 
154
                                  'swift-object-updater',
 
155
                                  'swift-container-sync']
 
156
        service_names = {
 
157
            self.mysql_sentry: ['mysql'],
 
158
            self.keystone_sentry: ['keystone'],
 
159
            self.glance_sentry: ['glance-registry',
 
160
                                 'glance-api'],
 
161
            self.swift_proxy_sentry: ['swift-proxy'],
143
162
            self.swift_storage_sentry: swift_storage_services
144
163
        }
145
164
 
146
 
        ret = u.validate_services(commands)
 
165
        ret = u.validate_services_by_name(service_names)
147
166
        if ret:
148
167
            amulet.raise_status(amulet.FAIL, msg=ret)
149
168
 
150
 
    def test_users(self):
 
169
    def test_102_users(self):
151
170
        """Verify all existing roles."""
 
171
        u.log.debug('Checking keystone users...')
152
172
        user1 = {'name': 'demoUser',
153
173
                 'enabled': True,
154
174
                 'tenantId': u.not_null,
176
196
        if ret:
177
197
            amulet.raise_status(amulet.FAIL, msg=ret)
178
198
 
179
 
    def test_service_catalog(self):
 
199
    def test_104_keystone_service_catalog(self):
180
200
        """Verify that the service catalog endpoint data is valid."""
181
 
        endpoint_vol = {'adminURL': u.valid_url,
182
 
                        'region': 'RegionOne',
183
 
                        'publicURL': u.valid_url,
184
 
                        'internalURL': u.valid_url}
 
201
        u.log.debug('Checking keystone service catalog...')
185
202
        endpoint_id = {'adminURL': u.valid_url,
186
203
                       'region': 'RegionOne',
187
204
                       'publicURL': u.valid_url,
188
 
                       'internalURL': u.valid_url}
189
 
        if self._get_openstack_release() >= self.precise_folsom:
190
 
            endpoint_vol['id'] = u.not_null
191
 
            endpoint_id['id'] = u.not_null
 
205
                       'internalURL': u.valid_url,
 
206
                       'id': u.not_null}
 
207
 
192
208
        expected = {'image': [endpoint_id], 'object-store': [endpoint_id],
193
209
                    'identity': [endpoint_id]}
194
210
        actual = self.keystone_demo.service_catalog.get_endpoints()
197
213
        if ret:
198
214
            amulet.raise_status(amulet.FAIL, msg=ret)
199
215
 
200
 
    def test_openstack_object_store_endpoint(self):
 
216
    def test_106_swift_object_store_endpoint(self):
201
217
        """Verify the swift object-store endpoint data."""
 
218
        u.log.debug('Checking keystone endpoint for swift object store...')
202
219
        endpoints = self.keystone.endpoints.list()
203
220
        admin_port = internal_port = public_port = '8080'
204
221
        expected = {'id': u.not_null,
214
231
            message = 'object-store endpoint: {}'.format(ret)
215
232
            amulet.raise_status(amulet.FAIL, msg=message)
216
233
 
217
 
    def test_swift_proxy_identity_service_relation(self):
218
 
        """Verify the swift-proxy to keystone identity-service relation data."""
 
234
    def test_200_swift_proxy_identity_service_relation(self):
 
235
        """Verify the swift-proxy to keystone identity relation data."""
 
236
        u.log.debug('Checking swift-proxy:keystone identity relation...')
219
237
        unit = self.swift_proxy_sentry
220
238
        relation = ['identity-service', 'keystone:identity-service']
221
239
        expected = {
233
251
            message = u.relation_error('swift-proxy identity-service', ret)
234
252
            amulet.raise_status(amulet.FAIL, msg=message)
235
253
 
236
 
    def test_keystone_identity_service_relation(self):
237
 
        """Verify the keystone to swift-proxy identity-service relation data."""
 
254
    def test_202_keystone_identity_service_relation(self):
 
255
        """Verify the keystone to swift-proxy identity relation data."""
 
256
        u.log.debug('Checking keystone:swift-proxy identity relation...')
238
257
        unit = self.keystone_sentry
239
258
        relation = ['identity-service', 'swift-proxy:identity-service']
240
259
        expected = {
257
276
            message = u.relation_error('keystone identity-service', ret)
258
277
            amulet.raise_status(amulet.FAIL, msg=message)
259
278
 
260
 
    def test_swift_storage_swift_storage_relation(self):
 
279
    def test_204_swift_storage_swift_storage_relation(self):
261
280
        """Verify the swift-storage to swift-proxy swift-storage relation
262
281
           data."""
 
282
        u.log.debug('Checking swift:swift-proxy swift-storage relation...')
263
283
        unit = self.swift_storage_sentry
264
284
        relation = ['swift-storage', 'swift-proxy:swift-storage']
265
285
        expected = {
276
296
            message = u.relation_error('swift-storage swift-storage', ret)
277
297
            amulet.raise_status(amulet.FAIL, msg=message)
278
298
 
279
 
    def test_swift_proxy_swift_storage_relation(self):
 
299
    def test_206_swift_proxy_swift_storage_relation(self):
280
300
        """Verify the swift-proxy to swift-storage swift-storage relation
281
301
           data."""
 
302
        u.log.debug('Checking swift-proxy:swift swift-storage relation...')
282
303
        unit = self.swift_proxy_sentry
283
304
        relation = ['swift-storage', 'swift-storage:swift-storage']
284
305
        expected = {
293
314
            message = u.relation_error('swift-proxy swift-storage', ret)
294
315
            amulet.raise_status(amulet.FAIL, msg=message)
295
316
 
296
 
    def test_glance_object_store_relation(self):
 
317
    def test_208_glance_object_store_relation(self):
297
318
        """Verify the glance to swift-proxy object-store relation data."""
 
319
        u.log.debug('Checking glance:swift-proxy object-store relation...')
298
320
        unit = self.glance_sentry
299
321
        relation = ['object-store', 'swift-proxy:object-store']
300
 
        expected = { 'private-address': u.valid_ip }
 
322
        expected = {'private-address': u.valid_ip}
301
323
 
302
324
        ret = u.validate_relation_data(unit, relation, expected)
303
325
        if ret:
304
326
            message = u.relation_error('glance object-store', ret)
305
327
            amulet.raise_status(amulet.FAIL, msg=message)
306
328
 
307
 
    def test_swift_proxy_object_store_relation(self):
 
329
    def test_210_swift_proxy_object_store_relation(self):
308
330
        """Verify the swift-proxy to glance object-store relation data."""
 
331
        u.log.debug('Checking swift-proxy:glance object-store relation...')
309
332
        unit = self.swift_proxy_sentry
310
333
        relation = ['object-store', 'glance:object-store']
311
334
        expected = {'private-address': u.valid_ip}
314
337
            message = u.relation_error('swift-proxy object-store', ret)
315
338
            amulet.raise_status(amulet.FAIL, msg=message)
316
339
 
317
 
    def test_z_restart_on_config_change(self):
 
340
    def test_300_swift_config(self):
 
341
        """Verify the data in the swift-hash section of the swift config
 
342
           file."""
 
343
        u.log.debug('Checking swift config...')
 
344
        unit = self.swift_storage_sentry
 
345
        conf = '/etc/swift/swift.conf'
 
346
        swift_proxy_relation = self.swift_proxy_sentry.relation(
 
347
            'swift-storage', 'swift-storage:swift-storage')
 
348
        expected = {
 
349
            'swift_hash_path_suffix': swift_proxy_relation['swift_hash']
 
350
        }
 
351
 
 
352
        ret = u.validate_config_data(unit, conf, 'swift-hash', expected)
 
353
        if ret:
 
354
            message = "swift config error: {}".format(ret)
 
355
            amulet.raise_status(amulet.FAIL, msg=message)
 
356
 
 
357
    def test_302_proxy_server_config(self):
 
358
        """Verify the data in the proxy-server config file."""
 
359
        u.log.debug('Checking swift proxy-server config...')
 
360
        unit = self.swift_proxy_sentry
 
361
        conf = '/etc/swift/proxy-server.conf'
 
362
        keystone_relation = self.keystone_sentry.relation(
 
363
            'identity-service', 'swift-proxy:identity-service')
 
364
        swift_proxy_relation = unit.relation(
 
365
            'identity-service', 'keystone:identity-service')
 
366
        swift_proxy_ip = swift_proxy_relation['private-address']
 
367
        auth_host = keystone_relation['auth_host']
 
368
        auth_protocol = keystone_relation['auth_protocol']
 
369
 
 
370
        expected = {
 
371
            'DEFAULT': {
 
372
                'bind_port': '8070',
 
373
                'user': 'swift',
 
374
                'log_name': 'swift',
 
375
                'log_facility': 'LOG_LOCAL0',
 
376
                'log_level': 'INFO',
 
377
                'log_headers': 'False',
 
378
                'log_address': '/dev/log'
 
379
            },
 
380
            'pipeline:main': {
 
381
                'pipeline': 'gatekeeper healthcheck proxy-logging cache '
 
382
                            'swift3 s3token container_sync bulk tempurl '
 
383
                            'slo dlo formpost authtoken keystoneauth '
 
384
                            'staticweb container-quotas account-quotas '
 
385
                            'proxy-logging proxy-server'
 
386
            },
 
387
            'app:proxy-server': {
 
388
                'use': 'egg:swift#proxy',
 
389
                'allow_account_management': 'true',
 
390
                'account_autocreate': 'true',
 
391
                'node_timeout': '60',
 
392
                'recoverable_node_timeout': '30'
 
393
            },
 
394
            'filter:tempauth': {
 
395
                'use': 'egg:swift#tempauth',
 
396
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
 
397
                                    'AUTH_system'.format(swift_proxy_ip)
 
398
            },
 
399
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
 
400
            'filter:cache': {
 
401
                'use': 'egg:swift#memcache',
 
402
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
 
403
            },
 
404
            'filter:account-quotas': {'use': 'egg:swift#account_quotas'},
 
405
            'filter:container-quotas': {'use': 'egg:swift#container_quotas'},
 
406
            'filter:proxy-logging': {'use': 'egg:swift#proxy_logging'},
 
407
            'filter:staticweb': {'use': 'egg:swift#staticweb'},
 
408
            'filter:bulk': {'use': 'egg:swift#bulk'},
 
409
            'filter:slo': {'use': 'egg:swift#slo'},
 
410
            'filter:dlo': {'use': 'egg:swift#dlo'},
 
411
            'filter:formpost': {'use': 'egg:swift#formpost'},
 
412
            'filter:tempurl': {'use': 'egg:swift#tempurl'},
 
413
            'filter:container_sync': {'use': 'egg:swift#container_sync'},
 
414
            'filter:gatekeeper': {'use': 'egg:swift#gatekeeper'},
 
415
            'filter:keystoneauth': {
 
416
                'use': 'egg:swift#keystoneauth',
 
417
                'operator_roles': 'Member,Admin'
 
418
            },
 
419
            'filter:authtoken': {
 
420
                'auth_uri': '{}://{}:{}'.format(
 
421
                    auth_protocol,
 
422
                    auth_host,
 
423
                    keystone_relation['service_port']),
 
424
                'admin_tenant_name': keystone_relation['service_tenant'],
 
425
                'admin_user': keystone_relation['service_username'],
 
426
                'admin_password': keystone_relation['service_password'],
 
427
                'delay_auth_decision': 'true',
 
428
                'signing_dir': '/var/cache/swift',
 
429
                'cache': 'swift.cache'
 
430
            },
 
431
            'filter:swift3': {'use': 'egg:swift3#swift3'}
 
432
        }
 
433
 
 
434
        if self._get_openstack_release() >= self.trusty_kilo:
 
435
            # Kilo and later
 
436
            expected['filter:authtoken'].update({
 
437
                'paste.filter_factory': 'keystonemiddleware.auth_token:'
 
438
                                        'filter_factory',
 
439
                'identity_uri': '{}://{}:{}'.format(
 
440
                    auth_protocol,
 
441
                    auth_host,
 
442
                    keystone_relation['auth_port']),
 
443
            })
 
444
            expected['filter:s3token'] = {
 
445
                # No section commonality with J and earlier
 
446
                'paste.filter_factory': 'keystonemiddleware.s3_token'
 
447
                                        ':filter_factory',
 
448
                'auth_uri': '{}://{}:{}'.format(
 
449
                    auth_protocol,
 
450
                    auth_host,
 
451
                    keystone_relation['service_port']),
 
452
                'identity_uri': '{}://{}:{}'.format(
 
453
                    auth_protocol,
 
454
                    auth_host,
 
455
                    keystone_relation['auth_port']),
 
456
            }
 
457
        else:
 
458
            # Juno and earlier
 
459
            expected['filter:authtoken'].update({
 
460
                'paste.filter_factory': 'keystoneclient.middleware.'
 
461
                                        'auth_token:filter_factory',
 
462
                'auth_host': auth_host,
 
463
                'auth_port': keystone_relation['auth_port'],
 
464
                'auth_protocol': auth_protocol,
 
465
            })
 
466
            expected['filter:s3token'] = {
 
467
                # No section commonality with K and later
 
468
                'paste.filter_factory': 'keystoneclient.middleware.'
 
469
                                        's3_token:filter_factory',
 
470
                'auth_port': keystone_relation['auth_port'],
 
471
                'auth_host': keystone_relation['auth_host'],
 
472
                'service_host': keystone_relation['service_host'],
 
473
                'service_port': keystone_relation['service_port'],
 
474
                'auth_protocol': keystone_relation['auth_protocol'],
 
475
                'auth_token': keystone_relation['admin_token'],
 
476
                'admin_token': keystone_relation['admin_token']
 
477
            }
 
478
 
 
479
        for section, pairs in expected.iteritems():
 
480
            ret = u.validate_config_data(unit, conf, section, pairs)
 
481
            if ret:
 
482
                message = "proxy-server config error: {}".format(ret)
 
483
                amulet.raise_status(amulet.FAIL, msg=message)
 
484
 
 
485
    def test_400_swift_backed_image_create(self):
 
486
        """Create an instance in glance, which is backed by swift, and validate
 
487
        that some of the metadata for the image match in glance and swift."""
 
488
        u.log.debug('Checking swift objects and containers with a '
 
489
                    'swift-backed glance image...')
 
490
 
 
491
        # Create swift-backed glance image
 
492
        img_new = u.create_cirros_image(self.glance, "cirros-image-1")
 
493
        img_id = img_new.id
 
494
        img_md5 = img_new.checksum
 
495
        img_size = img_new.size
 
496
 
 
497
        # Validate that swift object's checksum/size match that from glance
 
498
        headers, containers = self.swift.get_account()
 
499
        if len(containers) != 1:
 
500
            msg = "Expected 1 swift container, found {}".format(
 
501
                len(containers))
 
502
            amulet.raise_status(amulet.FAIL, msg=msg)
 
503
 
 
504
        container_name = containers[0].get('name')
 
505
 
 
506
        headers, objects = self.swift.get_container(container_name)
 
507
        if len(objects) != 1:
 
508
            msg = "Expected 1 swift object, found {}".format(len(objects))
 
509
            amulet.raise_status(amulet.FAIL, msg=msg)
 
510
 
 
511
        swift_object_size = objects[0].get('bytes')
 
512
        swift_object_md5 = objects[0].get('hash')
 
513
 
 
514
        if img_size != swift_object_size:
 
515
            msg = "Glance image size {} != swift object size {}".format(
 
516
                img_size, swift_object_size)
 
517
            amulet.raise_status(amulet.FAIL, msg=msg)
 
518
 
 
519
        if img_md5 != swift_object_md5:
 
520
            msg = "Glance image hash {} != swift object hash {}".format(
 
521
                img_md5, swift_object_md5)
 
522
            amulet.raise_status(amulet.FAIL, msg=msg)
 
523
 
 
524
        # Cleanup
 
525
        u.delete_resource(self.glance.images, img_id, msg="glance image")
 
526
        u.log.info('OK')
 
527
 
 
528
    def test_900_restart_on_config_change(self):
318
529
        """Verify that the specified services are restarted when the config
319
 
           is changed.
320
 
 
321
 
           Note(coreycb): The method name with the _z_ is a little odd
322
 
           but it forces the test to run last.  It just makes things
323
 
           easier because restarting services requires re-authorization.
324
 
           """
325
 
        svc = 'swift-proxy'
326
 
        self.d.configure('swift-proxy', {'node-timeout': '90'})
327
 
 
328
 
        if not u.service_restarted(self.swift_proxy_sentry, svc,
329
 
                                   '/etc/swift/proxy-server.conf'):
330
 
            self.d.configure('swift-proxy', {'node-timeout': '60'})
331
 
            msg = "service {} didn't restart after config change".format(svc)
332
 
            amulet.raise_status(amulet.FAIL, msg=msg)
333
 
 
334
 
        self.d.configure('swift-proxy', {'node-timeout': '60'})
335
 
 
336
 
    def test_z_no_restart_on_config_change_when_paused(self):
 
530
           is changed."""
 
531
        u.log.info('Checking that conf files and system services respond '
 
532
                   'to a charm config change...')
 
533
 
 
534
        sentry = self.swift_proxy_sentry
 
535
        juju_service = 'swift-proxy'
 
536
 
 
537
        # Process names, corresponding conf files
 
538
        services = {'swift-proxy-server': '/etc/swift/proxy-server.conf'}
 
539
 
 
540
        # Expected default and alternate values
 
541
        set_default = {'node-timeout': '60'}
 
542
        set_alternate = {'node-timeout': '90'}
 
543
 
 
544
        # Make config change, check for service restarts
 
545
        u.log.debug('Making config change on {}...'.format(juju_service))
 
546
        mtime = u.get_sentry_time(sentry)
 
547
        self.d.configure(juju_service, set_alternate)
 
548
 
 
549
        sleep_time = 40
 
550
        for s, conf_file in services.iteritems():
 
551
            u.log.debug("Checking that service restarted: {}".format(s))
 
552
            if not u.validate_service_config_changed(sentry, mtime, s,
 
553
                                                     conf_file,
 
554
                                                     sleep_time=sleep_time):
 
555
                self.d.configure(juju_service, set_default)
 
556
                msg = "service {} didn't restart after config change".format(s)
 
557
                amulet.raise_status(amulet.FAIL, msg=msg)
 
558
            sleep_time = 0
 
559
 
 
560
        self.d.configure(juju_service, set_default)
 
561
 
 
562
    def test_901_no_restart_on_config_change_when_paused(self):
337
563
        """Verify that the specified services are not restarted when the config
338
564
           is changed and the unit is paused."""
339
565
        u.log.info('Checking that system services do not get restarted  '
414
640
                   " (got {} instead)".format(message))
415
641
            amulet.raise_status(amulet.FAIL, msg=msg)
416
642
 
417
 
    def test_z_pause_resume_actions(self):
 
643
    def test_902_pause_resume_actions(self):
418
644
        """Pause and then resume swift-proxy."""
419
645
        u.log.debug('Checking pause/resume actions...')
420
646
        self._test_pause()
421
647
        self._test_resume()
422
 
 
423
 
    def test_swift_config(self):
424
 
        """Verify the data in the swift config file."""
425
 
        unit = self.swift_proxy_sentry
426
 
        conf = '/etc/swift/swift.conf'
427
 
        swift_proxy_relation = unit.relation('swift-storage',
428
 
                                             'swift-storage:swift-storage')
429
 
        expected = {
430
 
            'swift_hash_path_suffix': swift_proxy_relation['swift_hash']
431
 
        }
432
 
 
433
 
        ret = u.validate_config_data(unit, conf, 'swift-hash', expected)
434
 
        if ret:
435
 
            message = "swift config error: {}".format(ret)
436
 
            amulet.raise_status(amulet.FAIL, msg=message)
437
 
 
438
 
    def test_proxy_server_icehouse_config(self):
439
 
        """Verify the data in the proxy-server config file."""
440
 
        if self._get_openstack_release() < self.precise_icehouse:
441
 
            return
442
 
 
443
 
        unit = self.swift_proxy_sentry
444
 
        conf = '/etc/swift/proxy-server.conf'
445
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
446
 
                                                 'swift-proxy:identity-service')
447
 
        swift_proxy_relation = unit.relation('identity-service',
448
 
                                             'keystone:identity-service')
449
 
        swift_proxy_ip = swift_proxy_relation['private-address']
450
 
        auth_host = keystone_relation['auth_host']
451
 
        auth_protocol = keystone_relation['auth_protocol']
452
 
 
453
 
        expected = {
454
 
            'DEFAULT': {
455
 
                'bind_port': '8070',
456
 
                'user': 'swift',
457
 
                'log_name': 'swift',
458
 
                'log_facility': 'LOG_LOCAL0',
459
 
                'log_level': 'INFO',
460
 
                'log_headers': 'False',
461
 
                'log_address': '/dev/log'
462
 
            },
463
 
            'pipeline:main': {
464
 
                'pipeline': 'gatekeeper healthcheck proxy-logging cache swift3 '
465
 
                            's3token container_sync bulk tempurl slo dlo '
466
 
                            'formpost authtoken keystoneauth staticweb '
467
 
                            'container-quotas account-quotas proxy-logging '
468
 
                            'proxy-server'
469
 
            },
470
 
            'app:proxy-server': {
471
 
                'use': 'egg:swift#proxy',
472
 
                'allow_account_management': 'true',
473
 
                'account_autocreate': 'true',
474
 
                'node_timeout': '60',
475
 
                'recoverable_node_timeout': '30'
476
 
            },
477
 
            'filter:tempauth': {
478
 
                'use': 'egg:swift#tempauth',
479
 
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
480
 
                                    'AUTH_system'.format(swift_proxy_ip)
481
 
            },
482
 
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
483
 
            'filter:cache': {
484
 
                'use': 'egg:swift#memcache',
485
 
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
486
 
            },
487
 
            'filter:account-quotas': {'use': 'egg:swift#account_quotas'},
488
 
            'filter:container-quotas': {'use': 'egg:swift#container_quotas'},
489
 
            'filter:proxy-logging': {'use': 'egg:swift#proxy_logging'},
490
 
            'filter:staticweb': {'use': 'egg:swift#staticweb'},
491
 
            'filter:bulk': {'use': 'egg:swift#bulk'},
492
 
            'filter:slo': {'use': 'egg:swift#slo'},
493
 
            'filter:dlo': {'use': 'egg:swift#dlo'},
494
 
            'filter:formpost': {'use': 'egg:swift#formpost'},
495
 
            'filter:tempurl': {'use': 'egg:swift#tempurl'},
496
 
            'filter:container_sync': {'use': 'egg:swift#container_sync'},
497
 
            'filter:gatekeeper': {'use': 'egg:swift#gatekeeper'},
498
 
            'filter:keystoneauth': {
499
 
                'use': 'egg:swift#keystoneauth',
500
 
                'operator_roles': 'Member,Admin'
501
 
            },
502
 
            'filter:authtoken': {
503
 
                'paste.filter_factory': 'keystoneclient.middleware.'
504
 
                                        'auth_token:filter_factory',
505
 
                'auth_host': auth_host,
506
 
                'auth_port': keystone_relation['auth_port'],
507
 
                'auth_protocol': auth_protocol,
508
 
                'auth_uri': '{}://{}:{}'.format(auth_protocol, auth_host,
509
 
                                             keystone_relation['service_port']),
510
 
                'admin_tenant_name': keystone_relation['service_tenant'],
511
 
                'admin_user': keystone_relation['service_username'],
512
 
                'admin_password': keystone_relation['service_password'],
513
 
                'delay_auth_decision': 'true',
514
 
                'signing_dir': '/var/cache/swift',
515
 
                'cache': 'swift.cache'
516
 
            },
517
 
            'filter:s3token': {
518
 
                'paste.filter_factory': 'keystoneclient.middleware.'
519
 
                                        's3_token:filter_factory',
520
 
                'service_host': keystone_relation['service_host'],
521
 
                'service_port': keystone_relation['service_port'],
522
 
                'auth_port': keystone_relation['auth_port'],
523
 
                'auth_host': keystone_relation['auth_host'],
524
 
                'auth_protocol': keystone_relation['auth_protocol'],
525
 
                'auth_token': keystone_relation['admin_token'],
526
 
                'admin_token': keystone_relation['admin_token']
527
 
            },
528
 
            'filter:swift3': {'use': 'egg:swift3#swift3'}
529
 
        }
530
 
 
531
 
        for section, pairs in expected.iteritems():
532
 
            ret = u.validate_config_data(unit, conf, section, pairs)
533
 
            if ret:
534
 
                message = "proxy-server config error: {}".format(ret)
535
 
                amulet.raise_status(amulet.FAIL, msg=message)
536
 
 
537
 
    def test_proxy_server_havana_config(self):
538
 
        """Verify the data in the proxy-server config file."""
539
 
        if self._get_openstack_release() != self.precise_havana:
540
 
            return
541
 
 
542
 
        unit = self.swift_proxy_sentry
543
 
        conf = '/etc/swift/proxy-server.conf'
544
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
545
 
                                                 'swift-proxy:identity-service')
546
 
        swift_proxy_relation = unit.relation('identity-service',
547
 
                                             'keystone:identity-service')
548
 
        swift_proxy_ip = swift_proxy_relation['private-address']
549
 
        auth_host = keystone_relation['auth_host']
550
 
        auth_protocol = keystone_relation['auth_protocol']
551
 
 
552
 
        expected = {
553
 
            'DEFAULT': {
554
 
                'bind_port': '8070',
555
 
                'user': 'swift'
556
 
            },
557
 
            'pipeline:main': {
558
 
                'pipeline': 'healthcheck cache swift3 authtoken '
559
 
                            'keystoneauth container-quotas account-quotas '
560
 
                            'proxy-server'
561
 
            },
562
 
            'app:proxy-server': {
563
 
                'use': 'egg:swift#proxy',
564
 
                'allow_account_management': 'true',
565
 
                'account_autocreate': 'true',
566
 
                'node_timeout': '60',
567
 
                'recoverable_node_timeout': '30'
568
 
            },
569
 
            'filter:tempauth': {
570
 
                'use': 'egg:swift#tempauth',
571
 
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
572
 
                                    'AUTH_system'.format(swift_proxy_ip)
573
 
            },
574
 
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
575
 
            'filter:cache': {
576
 
                'use': 'egg:swift#memcache',
577
 
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
578
 
            },
579
 
            'filter:account-quotas': {'use': 'egg:swift#account_quotas'},
580
 
            'filter:container-quotas': {'use': 'egg:swift#container_quotas'},
581
 
            'filter:keystoneauth': {
582
 
                'use': 'egg:swift#keystoneauth',
583
 
                'operator_roles': 'Member,Admin'
584
 
            },
585
 
            'filter:authtoken': {
586
 
                'paste.filter_factory': 'keystoneclient.middleware.'
587
 
                                        'auth_token:filter_factory',
588
 
                'auth_host': auth_host,
589
 
                'auth_port': keystone_relation['auth_port'],
590
 
                'auth_protocol': auth_protocol,
591
 
                'auth_uri': '{}://{}:{}'.format(auth_protocol, auth_host,
592
 
                                             keystone_relation['service_port']),
593
 
                'admin_tenant_name': keystone_relation['service_tenant'],
594
 
                'admin_user': keystone_relation['service_username'],
595
 
                'admin_password': keystone_relation['service_password'],
596
 
                'delay_auth_decision': 'true',
597
 
                'signing_dir': '/var/cache/swift',
598
 
                'cache': 'swift.cache'
599
 
            },
600
 
            'filter:s3token': {
601
 
                'paste.filter_factory': 'keystone.middleware.s3_token:'
602
 
                                        'filter_factory',
603
 
                'service_host': keystone_relation['service_host'],
604
 
                'service_port': keystone_relation['service_port'],
605
 
                'auth_port': keystone_relation['auth_port'],
606
 
                'auth_host': keystone_relation['auth_host'],
607
 
                'auth_protocol': keystone_relation['auth_protocol'],
608
 
                'auth_token': keystone_relation['admin_token'],
609
 
                'admin_token': keystone_relation['admin_token'],
610
 
                'service_protocol': keystone_relation['service_protocol']
611
 
            },
612
 
            'filter:swift3': {'use': 'egg:swift3#swift3'}
613
 
        }
614
 
 
615
 
        for section, pairs in expected.iteritems():
616
 
            ret = u.validate_config_data(unit, conf, section, pairs)
617
 
            if ret:
618
 
                message = "proxy-server config error: {}".format(ret)
619
 
                amulet.raise_status(amulet.FAIL, msg=message)
620
 
 
621
 
    def test_proxy_server_grizzly_config(self):
622
 
        """Verify the data in the proxy-server config file."""
623
 
        if self._get_openstack_release() != self.precise_grizzly:
624
 
            return
625
 
 
626
 
        unit = self.swift_proxy_sentry
627
 
        conf = '/etc/swift/proxy-server.conf'
628
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
629
 
                                                 'swift-proxy:identity-service')
630
 
        swift_proxy_relation = unit.relation('identity-service',
631
 
                                             'keystone:identity-service')
632
 
        swift_proxy_ip = swift_proxy_relation['private-address']
633
 
        auth_host = keystone_relation['auth_host']
634
 
        auth_protocol = keystone_relation['auth_protocol']
635
 
 
636
 
        expected = {
637
 
            'DEFAULT': {
638
 
                'bind_port': '8070',
639
 
                'user': 'swift'
640
 
            },
641
 
            'pipeline:main': {
642
 
                'pipeline': 'healthcheck cache swift3 s3token authtoken '
643
 
                            'keystone container-quotas account-quotas '
644
 
                            'proxy-server'
645
 
            },
646
 
            'app:proxy-server': {
647
 
                'use': 'egg:swift#proxy',
648
 
                'allow_account_management': 'true',
649
 
                'account_autocreate': 'true',
650
 
                'node_timeout': '60',
651
 
                'recoverable_node_timeout': '30'
652
 
            },
653
 
            'filter:tempauth': {
654
 
                'use': 'egg:swift#tempauth',
655
 
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
656
 
                                    'AUTH_system'.format(swift_proxy_ip)
657
 
            },
658
 
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
659
 
            'filter:cache': {
660
 
                'use': 'egg:swift#memcache',
661
 
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
662
 
            },
663
 
            'filter:account-quotas': {'use': 'egg:swift#account_quotas'},
664
 
            'filter:container-quotas': {'use': 'egg:swift#container_quotas'},
665
 
            'filter:keystone': {
666
 
                'paste.filter_factory': 'swift.common.middleware.'
667
 
                                        'keystoneauth:filter_factory',
668
 
                'operator_roles': 'Member,Admin'
669
 
            },
670
 
            'filter:authtoken': {
671
 
                'paste.filter_factory': 'keystone.middleware.auth_token:'
672
 
                                        'filter_factory',
673
 
                'auth_host': auth_host,
674
 
                'auth_port': keystone_relation['auth_port'],
675
 
                'auth_protocol': auth_protocol,
676
 
                'auth_uri': '{}://{}:{}'.format(auth_protocol, auth_host,
677
 
                                             keystone_relation['service_port']),
678
 
                'admin_tenant_name': keystone_relation['service_tenant'],
679
 
                'admin_user': keystone_relation['service_username'],
680
 
                'admin_password': keystone_relation['service_password'],
681
 
                'delay_auth_decision': 'true',
682
 
                'signing_dir': '/var/cache/swift'
683
 
            },
684
 
            'filter:s3token': {
685
 
                'paste.filter_factory': 'keystone.middleware.s3_token:'
686
 
                                        'filter_factory',
687
 
                'service_host': keystone_relation['service_host'],
688
 
                'service_port': keystone_relation['service_port'],
689
 
                'auth_port': keystone_relation['auth_port'],
690
 
                'auth_host': keystone_relation['auth_host'],
691
 
                'auth_protocol': keystone_relation['auth_protocol'],
692
 
                'auth_token': keystone_relation['admin_token'],
693
 
                'admin_token': keystone_relation['admin_token'],
694
 
                'service_protocol': keystone_relation['service_protocol']
695
 
            },
696
 
            'filter:swift3': {'use': 'egg:swift3#swift3'}
697
 
        }
698
 
 
699
 
        for section, pairs in expected.iteritems():
700
 
            ret = u.validate_config_data(unit, conf, section, pairs)
701
 
            if ret:
702
 
                message = "proxy-server config error: {}".format(ret)
703
 
                amulet.raise_status(amulet.FAIL, msg=message)
704
 
 
705
 
    def test_proxy_server_folsom_config(self):
706
 
        """Verify the data in the proxy-server config file."""
707
 
        if self._get_openstack_release() != self.precise_folsom:
708
 
            return
709
 
 
710
 
        unit = self.swift_proxy_sentry
711
 
        conf = '/etc/swift/proxy-server.conf'
712
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
713
 
                                                 'swift-proxy:identity-service')
714
 
        swift_proxy_relation = unit.relation('identity-service',
715
 
                                             'keystone:identity-service')
716
 
        swift_proxy_ip = swift_proxy_relation['private-address']
717
 
        auth_host = keystone_relation['auth_host']
718
 
        auth_protocol = keystone_relation['auth_protocol']
719
 
 
720
 
        expected = {
721
 
            'DEFAULT': {
722
 
                'bind_port': '8070',
723
 
                'user': 'swift'
724
 
            },
725
 
            'pipeline:main': {
726
 
                'pipeline': 'healthcheck cache swift3 s3token authtoken '
727
 
                            'keystone proxy-server'
728
 
            },
729
 
            'app:proxy-server': {
730
 
                'use': 'egg:swift#proxy',
731
 
                'allow_account_management': 'true',
732
 
                'account_autocreate': 'true',
733
 
                'node_timeout': '60',
734
 
                'recoverable_node_timeout': '30'
735
 
            },
736
 
            'filter:tempauth': {
737
 
                'use': 'egg:swift#tempauth',
738
 
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
739
 
                                    'AUTH_system'.format(swift_proxy_ip)
740
 
            },
741
 
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
742
 
            'filter:cache': {
743
 
                'use': 'egg:swift#memcache',
744
 
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
745
 
            },
746
 
            'filter:keystone': {
747
 
                'paste.filter_factory': 'keystone.middleware.swift_auth:'
748
 
                                        'filter_factory',
749
 
                'operator_roles': 'Member,Admin'
750
 
            },
751
 
            'filter:authtoken': {
752
 
                'paste.filter_factory': 'keystone.middleware.auth_token:'
753
 
                                        'filter_factory',
754
 
                'auth_host': auth_host,
755
 
                'auth_port': keystone_relation['auth_port'],
756
 
                'auth_protocol': auth_protocol,
757
 
                'auth_uri': '{}://{}:{}'.format(auth_protocol, auth_host,
758
 
                                             keystone_relation['service_port']),
759
 
                'admin_tenant_name': keystone_relation['service_tenant'],
760
 
                'admin_user': keystone_relation['service_username'],
761
 
                'admin_password': keystone_relation['service_password'],
762
 
                'delay_auth_decision': '1'
763
 
            },
764
 
            'filter:s3token': {
765
 
                'paste.filter_factory': 'keystone.middleware.s3_token:'
766
 
                                        'filter_factory',
767
 
                'service_host': keystone_relation['service_host'],
768
 
                'service_port': keystone_relation['service_port'],
769
 
                'auth_port': keystone_relation['auth_port'],
770
 
                'auth_host': keystone_relation['auth_host'],
771
 
                'auth_protocol': keystone_relation['auth_protocol'],
772
 
                'auth_token': keystone_relation['admin_token'],
773
 
                'admin_token': keystone_relation['admin_token'],
774
 
                'service_protocol': keystone_relation['service_protocol']
775
 
            },
776
 
            'filter:swift3': {'use': 'egg:swift#swift3'}
777
 
        }
778
 
 
779
 
        for section, pairs in expected.iteritems():
780
 
            ret = u.validate_config_data(unit, conf, section, pairs)
781
 
            if ret:
782
 
                message = "proxy-server config error: {}".format(ret)
783
 
                amulet.raise_status(amulet.FAIL, msg=message)
784
 
 
785
 
    def test_proxy_server_essex_config(self):
786
 
        """Verify the data in the proxy-server config file."""
787
 
        if self._get_openstack_release() != self.precise_essex:
788
 
            return
789
 
 
790
 
        unit = self.swift_proxy_sentry
791
 
        conf = '/etc/swift/proxy-server.conf'
792
 
        keystone_relation = self.keystone_sentry.relation('identity-service',
793
 
                                                 'swift-proxy:identity-service')
794
 
        swift_proxy_relation = unit.relation('identity-service',
795
 
                                             'keystone:identity-service')
796
 
        swift_proxy_ip = swift_proxy_relation['private-address']
797
 
        auth_host = keystone_relation['auth_host']
798
 
        auth_protocol = keystone_relation['auth_protocol']
799
 
 
800
 
        expected = {
801
 
            'DEFAULT': {
802
 
                'bind_port': '8070',
803
 
                'user': 'swift'
804
 
            },
805
 
            'pipeline:main': {
806
 
                'pipeline': 'healthcheck cache swift3 s3token authtoken '
807
 
                            'keystone proxy-server'
808
 
            },
809
 
            'app:proxy-server': {
810
 
                'use': 'egg:swift#proxy',
811
 
                'allow_account_management': 'true',
812
 
                'account_autocreate': 'true',
813
 
                'node_timeout': '60',
814
 
                'recoverable_node_timeout': '30'
815
 
            },
816
 
            'filter:tempauth': {
817
 
                'use': 'egg:swift#tempauth',
818
 
                'user_system_root': 'testpass .admin https://{}:8080/v1/'
819
 
                                    'AUTH_system'.format(swift_proxy_ip)
820
 
            },
821
 
            'filter:healthcheck': {'use': 'egg:swift#healthcheck'},
822
 
            'filter:cache': {
823
 
                'use': 'egg:swift#memcache',
824
 
                'memcache_servers': '{}:11211'.format(swift_proxy_ip)
825
 
            },
826
 
            'filter:keystone': {
827
 
                'paste.filter_factory': 'keystone.middleware.swift_auth:'
828
 
                                        'filter_factory',
829
 
                'operator_roles': 'Member,Admin'
830
 
            },
831
 
            'filter:authtoken': {
832
 
                'paste.filter_factory': 'keystone.middleware.auth_token:'
833
 
                                        'filter_factory',
834
 
                'auth_host': auth_host,
835
 
                'auth_port': keystone_relation['auth_port'],
836
 
                'auth_protocol': auth_protocol,
837
 
                'auth_uri': '{}://{}:{}'.format(auth_protocol, auth_host,
838
 
                                         keystone_relation['service_port']),
839
 
                'admin_tenant_name': keystone_relation['service_tenant'],
840
 
                'admin_user': keystone_relation['service_username'],
841
 
                'admin_password': keystone_relation['service_password'],
842
 
                'delay_auth_decision': '1'
843
 
            },
844
 
            'filter:s3token': {
845
 
                'paste.filter_factory': 'keystone.middleware.s3_token:'
846
 
                                        'filter_factory',
847
 
                'service_host': keystone_relation['service_host'],
848
 
                'service_port': keystone_relation['service_port'],
849
 
                'auth_port': keystone_relation['auth_port'],
850
 
                'auth_host': keystone_relation['auth_host'],
851
 
                'auth_protocol': keystone_relation['auth_protocol'],
852
 
                'auth_token': keystone_relation['admin_token'],
853
 
                'admin_token': keystone_relation['admin_token'],
854
 
                'service_protocol': keystone_relation['service_protocol']
855
 
            },
856
 
            'filter:swift3': {'use': 'egg:swift#swift3'}
857
 
        }
858
 
 
859
 
        for section, pairs in expected.iteritems():
860
 
            ret = u.validate_config_data(unit, conf, section, pairs)
861
 
            if ret:
862
 
                message = "proxy-server config error: {}".format(ret)
863
 
                amulet.raise_status(amulet.FAIL, msg=message)
864
 
 
865
 
    def test_image_create(self):
866
 
        """Create an instance in glance, which is backed by swift, and validate
867
 
           that some of the metadata for the image match in glance and swift."""
868
 
        # NOTE(coreycb): Skipping failing test on folsom until resolved. On
869
 
        #                folsom only, uploading an image to glance gets 400 Bad
870
 
        #                Request - Error uploading image: (error): [Errno 111]
871
 
        #                ECONNREFUSED (HTTP 400)
872
 
        if self._get_openstack_release() == self.precise_folsom:
873
 
            u.log.error("Skipping failing test until resolved")
874
 
            return
875
 
 
876
 
        # Create glance image
877
 
        image = u.create_cirros_image(self.glance, "cirros-image")
878
 
        if not image:
879
 
            amulet.raise_status(amulet.FAIL, msg="Image create failed")
880
 
 
881
 
        # Validate that cirros image exists in glance and get its checksum/size
882
 
        images = list(self.glance.images.list())
883
 
        if len(images) != 1:
884
 
            msg = "Expected 1 glance image, found {}".format(len(images))
885
 
            amulet.raise_status(amulet.FAIL, msg=msg)
886
 
 
887
 
        if images[0].name != 'cirros-image':
888
 
            message = "cirros image does not exist"
889
 
            amulet.raise_status(amulet.FAIL, msg=message)
890
 
 
891
 
        glance_image_md5 = image.checksum
892
 
        glance_image_size = image.size
893
 
 
894
 
        # Validate that swift object's checksum/size match that from glance
895
 
        headers, containers = self.swift.get_account()
896
 
        if len(containers) != 1:
897
 
            msg = "Expected 1 swift container, found {}".format(len(containers))
898
 
            amulet.raise_status(amulet.FAIL, msg=msg)
899
 
 
900
 
        container_name = containers[0].get('name')
901
 
 
902
 
        headers, objects = self.swift.get_container(container_name)
903
 
        if len(objects) != 1:
904
 
            msg = "Expected 1 swift object, found {}".format(len(objects))
905
 
            amulet.raise_status(amulet.FAIL, msg=msg)
906
 
 
907
 
        swift_object_size = objects[0].get('bytes')
908
 
        swift_object_md5 = objects[0].get('hash')
909
 
 
910
 
        if glance_image_size != swift_object_size:
911
 
            msg = "Glance image size {} != swift object size {}".format( \
912
 
                                           glance_image_size, swift_object_size)
913
 
            amulet.raise_status(amulet.FAIL, msg=msg)
914
 
 
915
 
        if glance_image_md5 != swift_object_md5:
916
 
            msg = "Glance image hash {} != swift object hash {}".format( \
917
 
                                             glance_image_md5, swift_object_md5)
918
 
            amulet.raise_status(amulet.FAIL, msg=msg)
919
 
 
920
 
        # Cleanup
921
 
        u.delete_image(self.glance, image)