~billy-olsen/charms/trusty/ceph-radosgw/lp1500635

« back to all changes in this revision

Viewing changes to tests/basic_deployment.py

  • Committer: james.page at ubuntu
  • Date: 2014-10-06 22:16:05 UTC
  • mfrom: (26.1.5 ceph-radosgw)
  • Revision ID: james.page@ubuntu.com-20141006221605-z9wo0l6kj02s4onu
[coreycb,r=james-page] Add amulet tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
import amulet
 
4
from charmhelpers.contrib.openstack.amulet.deployment import (
 
5
    OpenStackAmuletDeployment
 
6
)
 
7
from charmhelpers.contrib.openstack.amulet.utils import (  # noqa
 
8
    OpenStackAmuletUtils,
 
9
    DEBUG,
 
10
    ERROR
 
11
)
 
12
 
 
13
# Use DEBUG to turn on debug logging
 
14
u = OpenStackAmuletUtils(ERROR)
 
15
 
 
16
 
 
17
class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
 
18
    """Amulet tests on a basic ceph-radosgw deployment."""
 
19
 
 
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,
 
23
                                                         source, stable)
 
24
        self._add_services()
 
25
        self._add_relations()
 
26
        self._configure_services()
 
27
        self._deploy()
 
28
        self._initialize_tests()
 
29
 
 
30
    def _add_services(self):
 
31
        """Add services
 
32
 
 
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).
 
36
           """
 
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'},
 
41
                          {'name': 'cinder'}]
 
42
        super(CephRadosGwBasicDeployment, self)._add_services(this_service,
 
43
                                                              other_services)
 
44
 
 
45
    def _add_relations(self):
 
46
        """Add all of the relations for the services."""
 
47
        relations = {
 
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'
 
64
        }
 
65
        super(CephRadosGwBasicDeployment, self)._add_relations(relations)
 
66
 
 
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'}
 
73
        ceph_config = {
 
74
            'monitor-count': '3',
 
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'
 
81
        }
 
82
 
 
83
        configs = {'keystone': keystone_config,
 
84
                   'mysql': mysql_config,
 
85
                   'cinder': cinder_config,
 
86
                   'ceph': ceph_config}
 
87
        super(CephRadosGwBasicDeployment, self)._configure_services(configs)
 
88
 
 
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']
 
102
 
 
103
        # Authenticate admin with keystone
 
104
        self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
 
105
                                                      user='admin',
 
106
                                                      password='openstack',
 
107
                                                      tenant='admin')
 
108
 
 
109
        # Authenticate admin with glance endpoint
 
110
        self.glance = u.authenticate_glance_admin(self.keystone)
 
111
 
 
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',
 
119
                                                  enabled=True)
 
120
            self.keystone.roles.create(name=self.demo_role)
 
121
            self.keystone.users.create(name=self.demo_user,
 
122
                                       password='password',
 
123
                                       tenant_id=tenant.id,
 
124
                                       email='demo@demo.com')
 
125
 
 
126
        # Authenticate demo user with keystone
 
127
        self.keystone_demo = u.authenticate_keystone_user(self.keystone,
 
128
                                                          self.demo_user,
 
129
                                                          'password',
 
130
                                                          self.demo_tenant)
 
131
 
 
132
        # Authenticate demo user with nova-api
 
133
        self.nova_demo = u.authenticate_nova_user(self.keystone,
 
134
                                                  self.demo_user,
 
135
                                                  'password',
 
136
                                                  self.demo_tenant)
 
137
 
 
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
 
141
 
 
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`']
 
146
        commands = {
 
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']
 
157
        }
 
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
 
164
 
 
165
        ret = u.validate_services(commands)
 
166
        if ret:
 
167
            amulet.raise_status(amulet.FAIL, msg=ret)
 
168
 
 
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']
 
173
        expected = {
 
174
            'private-address': u.valid_ip
 
175
        }
 
176
 
 
177
        ret = u.validate_relation_data(unit, relation, expected)
 
178
        if ret:
 
179
            message = u.relation_error('ceph-radosgw to ceph', ret)
 
180
            amulet.raise_status(amulet.FAIL, msg=message)
 
181
 
 
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']
 
186
        expected = {
 
187
            'private-address': u.valid_ip,
 
188
            'radosgw_key': u.not_null,
 
189
            'auth': 'none',
 
190
            'ceph-public-address': u.valid_ip,
 
191
            'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
 
192
        }
 
193
 
 
194
        ret = u.validate_relation_data(unit, relation, expected)
 
195
        if ret:
 
196
            message = u.relation_error('ceph0 to ceph-radosgw', ret)
 
197
            amulet.raise_status(amulet.FAIL, msg=message)
 
198
 
 
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']
 
203
        expected = {
 
204
            'private-address': u.valid_ip,
 
205
            'radosgw_key': u.not_null,
 
206
            'auth': 'none',
 
207
            'ceph-public-address': u.valid_ip,
 
208
            'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
 
209
        }
 
210
 
 
211
        ret = u.validate_relation_data(unit, relation, expected)
 
212
        if ret:
 
213
            message = u.relation_error('ceph1 to ceph-radosgw', ret)
 
214
            amulet.raise_status(amulet.FAIL, msg=message)
 
215
 
 
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']
 
220
        expected = {
 
221
            'private-address': u.valid_ip,
 
222
            'radosgw_key': u.not_null,
 
223
            'auth': 'none',
 
224
            'ceph-public-address': u.valid_ip,
 
225
            'fsid': u'6547bd3e-1397-11e2-82e5-53567c8d32dc'
 
226
        }
 
227
 
 
228
        ret = u.validate_relation_data(unit, relation, expected)
 
229
        if ret:
 
230
            message = u.relation_error('ceph2 to ceph-radosgw', ret)
 
231
            amulet.raise_status(amulet.FAIL, msg=message)
 
232
 
 
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']
 
237
        expected = {
 
238
            'service': 'swift',
 
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
 
245
        }
 
246
 
 
247
        ret = u.validate_relation_data(unit, relation, expected)
 
248
        if ret:
 
249
            message = u.relation_error('ceph-radosgw to keystone', ret)
 
250
            amulet.raise_status(amulet.FAIL, msg=message)
 
251
 
 
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']
 
256
        expected = {
 
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
 
270
        }
 
271
 
 
272
        ret = u.validate_relation_data(unit, relation, expected)
 
273
        if ret:
 
274
            message = u.relation_error('keystone to ceph-radosgw', ret)
 
275
            amulet.raise_status(amulet.FAIL, msg=message)
 
276
 
 
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']
 
285
        expected = {
 
286
            'global': {
 
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'
 
293
            },
 
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'
 
304
            },
 
305
        }
 
306
 
 
307
        for section, pairs in expected.iteritems():
 
308
            ret = u.validate_config_data(unit, conf, section, pairs)
 
309
            if ret:
 
310
                message = "ceph config error: {}".format(ret)
 
311
                amulet.raise_status(amulet.FAIL, msg=message)
 
312
 
 
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")
 
320
            return