4
from charmhelpers.contrib.openstack.amulet.deployment import (
5
OpenStackAmuletDeployment
7
from charmhelpers.contrib.openstack.amulet.utils import ( # noqa
13
# Use DEBUG to turn on debug logging
14
u = OpenStackAmuletUtils(ERROR)
17
class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
18
"""Amulet tests on a basic ceph-radosgw deployment."""
20
def __init__(self, series=None, openstack=None, source=None, stable=False):
21
"""Deploy the entire test environment."""
22
super(CephRadosGwBasicDeployment, self).__init__(series, openstack,
26
self._configure_services()
28
self._initialize_tests()
30
def _add_services(self):
33
Add the services that we're testing, where ceph-radosgw is local,
34
and the rest of the service are from lp branches that are
35
compatible with the local charm (e.g. stable or next).
37
this_service = {'name': 'ceph-radosgw'}
38
other_services = [{'name': 'ceph', 'units': 3}, {'name': 'mysql'},
39
{'name': 'keystone'}, {'name': 'rabbitmq-server'},
40
{'name': 'nova-compute'}, {'name': 'glance'},
42
super(CephRadosGwBasicDeployment, self)._add_services(this_service,
45
def _add_relations(self):
46
"""Add all of the relations for the services."""
48
'nova-compute:shared-db': 'mysql:shared-db',
49
'nova-compute:amqp': 'rabbitmq-server:amqp',
50
'nova-compute:image-service': 'glance:image-service',
51
'nova-compute:ceph': 'ceph:client',
52
'keystone:shared-db': 'mysql:shared-db',
53
'glance:shared-db': 'mysql:shared-db',
54
'glance:identity-service': 'keystone:identity-service',
55
'glance:amqp': 'rabbitmq-server:amqp',
56
'glance:ceph': 'ceph:client',
57
'cinder:shared-db': 'mysql:shared-db',
58
'cinder:identity-service': 'keystone:identity-service',
59
'cinder:amqp': 'rabbitmq-server:amqp',
60
'cinder:image-service': 'glance:image-service',
61
'cinder:ceph': 'ceph:client',
62
'ceph-radosgw:mon': 'ceph:radosgw',
63
'ceph-radosgw:identity-service': 'keystone:identity-service'
65
super(CephRadosGwBasicDeployment, self)._add_relations(relations)
67
def _configure_services(self):
68
"""Configure all of the services."""
69
keystone_config = {'admin-password': 'openstack',
70
'admin-token': 'ubuntutesting'}
71
mysql_config = {'dataset-size': '50%'}
72
cinder_config = {'block-device': 'None', 'glance-api-version': '2'}
75
'auth-supported': 'none',
76
'fsid': '6547bd3e-1397-11e2-82e5-53567c8d32dc',
77
'monitor-secret': 'AQCXrnZQwI7KGBAAiPofmKEXKxu5bUzoYLVkbQ==',
78
'osd-reformat': 'yes',
79
'ephemeral-unmount': '/mnt',
80
'osd-devices': '/dev/vdb /srv/ceph'
83
configs = {'keystone': keystone_config,
84
'mysql': mysql_config,
85
'cinder': cinder_config,
87
super(CephRadosGwBasicDeployment, self)._configure_services(configs)
89
def _initialize_tests(self):
90
"""Perform final initialization before tests get run."""
91
# Access the sentries for inspecting service units
92
self.mysql_sentry = self.d.sentry.unit['mysql/0']
93
self.keystone_sentry = self.d.sentry.unit['keystone/0']
94
self.rabbitmq_sentry = self.d.sentry.unit['rabbitmq-server/0']
95
self.nova_compute_sentry = self.d.sentry.unit['nova-compute/0']
96
self.glance_sentry = self.d.sentry.unit['glance/0']
97
self.cinder_sentry = self.d.sentry.unit['cinder/0']
98
self.ceph0_sentry = self.d.sentry.unit['ceph/0']
99
self.ceph1_sentry = self.d.sentry.unit['ceph/1']
100
self.ceph2_sentry = self.d.sentry.unit['ceph/2']
101
self.ceph_radosgw_sentry = self.d.sentry.unit['ceph-radosgw/0']
103
# Authenticate admin with keystone
104
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
106
password='openstack',
109
# Authenticate admin with glance endpoint
110
self.glance = u.authenticate_glance_admin(self.keystone)
112
# Create a demo tenant/role/user
113
self.demo_tenant = 'demoTenant'
114
self.demo_role = 'demoRole'
115
self.demo_user = 'demoUser'
116
if not u.tenant_exists(self.keystone, self.demo_tenant):
117
tenant = self.keystone.tenants.create(tenant_name=self.demo_tenant,
118
description='demo tenant',
120
self.keystone.roles.create(name=self.demo_role)
121
self.keystone.users.create(name=self.demo_user,
124
email='demo@demo.com')
126
# Authenticate demo user with keystone
127
self.keystone_demo = u.authenticate_keystone_user(self.keystone,
132
# Authenticate demo user with nova-api
133
self.nova_demo = u.authenticate_nova_user(self.keystone,
138
def _ceph_osd_id(self, index):
139
"""Produce a shell command that will return a ceph-osd id."""
140
return "`initctl list | grep 'ceph-osd ' | awk 'NR=={} {{ print $2 }}' | grep -o '[0-9]*'`".format(index + 1) # noqa
142
def test_services(self):
143
"""Verify the expected services are running on the service units."""
144
ceph_services = ['status ceph-mon-all',
145
'status ceph-mon id=`hostname`']
147
self.mysql_sentry: ['status mysql'],
148
self.rabbitmq_sentry: ['sudo service rabbitmq-server status'],
149
self.nova_compute_sentry: ['status nova-compute'],
150
self.keystone_sentry: ['status keystone'],
151
self.glance_sentry: ['status glance-registry',
152
'status glance-api'],
153
self.cinder_sentry: ['status cinder-api',
154
'status cinder-scheduler',
155
'status cinder-volume'],
156
self.ceph_radosgw_sentry: ['status radosgw-all']
158
ceph_osd0 = 'status ceph-osd id={}'.format(self._ceph_osd_id(0))
159
ceph_osd1 = 'status ceph-osd id={}'.format(self._ceph_osd_id(1))
160
ceph_services.extend([ceph_osd0, ceph_osd1, 'status ceph-osd-all'])
161
commands[self.ceph0_sentry] = ceph_services
162
commands[self.ceph1_sentry] = ceph_services
163
commands[self.ceph2_sentry] = ceph_services
165
ret = u.validate_services(commands)
167
amulet.raise_status(amulet.FAIL, msg=ret)
169
def test_ceph_radosgw_ceph_relation(self):
170
"""Verify the ceph-radosgw to ceph relation data."""
171
unit = self.ceph_radosgw_sentry
172
relation = ['mon', 'ceph:radosgw']
174
'private-address': u.valid_ip
177
ret = u.validate_relation_data(unit, relation, expected)
179
message = u.relation_error('ceph-radosgw to ceph', ret)
180
amulet.raise_status(amulet.FAIL, msg=message)
182
def test_ceph0_ceph_radosgw_relation(self):
183
"""Verify the ceph0 to ceph-radosgw relation data."""
184
unit = self.ceph0_sentry
185
relation = ['radosgw', 'ceph-radosgw:mon']
187
'private-address': u.valid_ip,
188
'radosgw_key': u.not_null,
190
'ceph-public-address': u.valid_ip,
191
'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
194
ret = u.validate_relation_data(unit, relation, expected)
196
message = u.relation_error('ceph0 to ceph-radosgw', ret)
197
amulet.raise_status(amulet.FAIL, msg=message)
199
def test_ceph1_ceph_radosgw_relation(self):
200
"""Verify the ceph1 to ceph-radosgw relation data."""
201
unit = self.ceph1_sentry
202
relation = ['radosgw', 'ceph-radosgw:mon']
204
'private-address': u.valid_ip,
205
'radosgw_key': u.not_null,
207
'ceph-public-address': u.valid_ip,
208
'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
211
ret = u.validate_relation_data(unit, relation, expected)
213
message = u.relation_error('ceph1 to ceph-radosgw', ret)
214
amulet.raise_status(amulet.FAIL, msg=message)
216
def test_ceph2_ceph_radosgw_relation(self):
217
"""Verify the ceph2 to ceph-radosgw relation data."""
218
unit = self.ceph2_sentry
219
relation = ['radosgw', 'ceph-radosgw:mon']
221
'private-address': u.valid_ip,
222
'radosgw_key': u.not_null,
224
'ceph-public-address': u.valid_ip,
225
'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
228
ret = u.validate_relation_data(unit, relation, expected)
230
message = u.relation_error('ceph2 to ceph-radosgw', ret)
231
amulet.raise_status(amulet.FAIL, msg=message)
233
def test_ceph_radosgw_keystone_relation(self):
234
"""Verify the ceph-radosgw to keystone relation data."""
235
unit = self.ceph_radosgw_sentry
236
relation = ['identity-service', 'keystone:identity-service']
239
'region': 'RegionOne',
240
'public_url': u.valid_url,
241
'internal_url': u.valid_url,
242
'private-address': u.valid_ip,
243
'requested_roles': 'Member,Admin',
244
'admin_url': u.valid_url
247
ret = u.validate_relation_data(unit, relation, expected)
249
message = u.relation_error('ceph-radosgw to keystone', ret)
250
amulet.raise_status(amulet.FAIL, msg=message)
252
def test_keystone_ceph_radosgw_relation(self):
253
"""Verify the keystone to ceph-radosgw relation data."""
254
unit = self.keystone_sentry
255
relation = ['identity-service', 'ceph-radosgw:identity-service']
257
'service_protocol': 'http',
258
'service_tenant': 'services',
259
'admin_token': 'ubuntutesting',
260
'service_password': u.not_null,
261
'service_port': '5000',
262
'auth_port': '35357',
263
'auth_protocol': 'http',
264
'private-address': u.valid_ip,
265
'https_keystone': 'False',
266
'auth_host': u.valid_ip,
267
'service_username': 'swift',
268
'service_tenant_id': u.not_null,
269
'service_host': u.valid_ip
272
ret = u.validate_relation_data(unit, relation, expected)
274
message = u.relation_error('keystone to ceph-radosgw', ret)
275
amulet.raise_status(amulet.FAIL, msg=message)
277
def test_ceph_config(self):
278
"""Verify the data in the ceph config file."""
279
unit = self.ceph_radosgw_sentry
280
conf = '/etc/ceph/ceph.conf'
281
keystone_sentry = self.keystone_sentry
282
relation = keystone_sentry.relation('identity-service',
283
'ceph-radosgw:identity-service')
284
keystone_ip = relation['auth_host']
287
'auth cluster required': 'none',
288
'auth service required': 'none',
289
'auth client required': 'none',
290
'log to syslog': 'false',
291
'err to syslog': 'false',
292
'clog to syslog': 'false'
294
'client.radosgw.gateway': {
295
'keyring': '/etc/ceph/keyring.rados.gateway',
296
'rgw socket path': '/tmp/radosgw.sock',
297
'log file': '/var/log/ceph/radosgw.log',
298
'rgw print continue': 'false',
299
'rgw keystone url': 'http://{}:35357/'.format(keystone_ip),
300
'rgw keystone admin token': 'ubuntutesting',
301
'rgw keystone accepted roles': 'Member,Admin',
302
'rgw keystone token cache size': '500',
303
'rgw keystone revocation interval': '600'
307
for section, pairs in expected.iteritems():
308
ret = u.validate_config_data(unit, conf, section, pairs)
310
message = "ceph config error: {}".format(ret)
311
amulet.raise_status(amulet.FAIL, msg=message)
313
def test_restart_on_config_change(self):
314
"""Verify the specified services are restarted on config change."""
315
# NOTE(coreycb): Test not implemented but should it be? ceph-radosgw
316
# svcs aren't restarted by charm after config change
317
# Should they be restarted?
318
if self._get_openstack_release() >= self.precise_essex:
319
u.log.error("Test not implemented")