Merge lp:~1chb1n/charms/trusty/nova-cloud-controller/next-amulet-1510 into lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next

Proposed by Ryan Beisner
Status: Merged
Merged at revision: 201
Proposed branch: lp:~1chb1n/charms/trusty/nova-cloud-controller/next-amulet-1510
Merge into: lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next
Diff against target: 820 lines (+326/-175)
5 files modified
tests/020-basic-trusty-liberty (+12/-0)
tests/021-basic-wily-liberty (+10/-0)
tests/README (+10/-0)
tests/basic_deployment.py (+254/-175)
tests/charmhelpers/contrib/openstack/amulet/deployment.py (+40/-0)
To merge this branch: bzr merge lp:~1chb1n/charms/trusty/nova-cloud-controller/next-amulet-1510
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+273740@code.launchpad.net

Description of the change

Update amulet tests for Vivid-Kilo, Trusty-Liberty, prep for Wily-Liberty.

Add new logic to wait for extended status message to confirm deploy is ready, before testing.

Dependent on this charm-helpers change landing:
https://code.launchpad.net/~1chb1n/charm-helpers/auto-status-wait/+merge/274600

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11792 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11792/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #10967 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/10967/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7308 nova-cloud-controller-next for 1chb1n mp273740
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/12775880/
Build: http://10.245.162.77:8080/job/charm_amulet_test/7308/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11843 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11843/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11015 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11015/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7311 nova-cloud-controller-next for 1chb1n mp273740
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/12778607/
Build: http://10.245.162.77:8080/job/charm_amulet_test/7311/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11898 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11898/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11065 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11065/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11899 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11899/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11066 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11066/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7338 nova-cloud-controller-next for 1chb1n mp273740
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/12784221/
Build: http://10.245.162.77:8080/job/charm_amulet_test/7338/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7339 nova-cloud-controller-next for 1chb1n mp273740
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/12784371/
Build: http://10.245.162.77:8080/job/charm_amulet_test/7339/

Revision history for this message
Ryan Beisner (1chb1n) wrote :

^ FYI, Amulet passes for everything but the deploy-from-source tests, which are also failing in next proper.

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11957 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11957/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11115 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11115/

209. By Ryan Beisner

resync tests/charmhelpers

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #11988 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/11988/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11142 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11142/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7343 nova-cloud-controller-next for 1chb1n mp273740
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/7343/

210. By Ryan Beisner

stop using deprecated delete helpers

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #12018 nova-cloud-controller-next for 1chb1n mp273740
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/12018/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #11169 nova-cloud-controller-next for 1chb1n mp273740
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/11169/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7371 nova-cloud-controller-next for 1chb1n mp273740
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/7371/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #7379 nova-cloud-controller-next for 1chb1n mp273740
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/7379/

Revision history for this message
Liam Young (gnuoy) wrote :

Approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/010-basic-precise-essex' (properties changed: +x to -x)
2=== modified file 'tests/019-basic-vivid-kilo' (properties changed: -x to +x)
3=== added file 'tests/020-basic-trusty-liberty'
4--- tests/020-basic-trusty-liberty 1970-01-01 00:00:00 +0000
5+++ tests/020-basic-trusty-liberty 2015-10-16 05:41:21 +0000
6@@ -0,0 +1,12 @@
7+#!/usr/bin/python
8+
9+"""Amulet tests on a basic nova cloud controller deployment on
10+ trusty-liberty."""
11+
12+from basic_deployment import NovaCCBasicDeployment
13+
14+if __name__ == '__main__':
15+ deployment = NovaCCBasicDeployment(series='trusty',
16+ openstack='cloud:trusty-liberty',
17+ source='cloud:trusty-updates/liberty')
18+ deployment.run_tests()
19
20=== added file 'tests/021-basic-wily-liberty'
21--- tests/021-basic-wily-liberty 1970-01-01 00:00:00 +0000
22+++ tests/021-basic-wily-liberty 2015-10-16 05:41:21 +0000
23@@ -0,0 +1,10 @@
24+#!/usr/bin/python
25+
26+"""Amulet tests on a basic nova cloud controller deployment on
27+ wily-liberty."""
28+
29+from basic_deployment import NovaCCBasicDeployment
30+
31+if __name__ == '__main__':
32+ deployment = NovaCCBasicDeployment(series='wily')
33+ deployment.run_tests()
34
35=== modified file 'tests/README'
36--- tests/README 2014-09-29 21:03:48 +0000
37+++ tests/README 2015-10-16 05:41:21 +0000
38@@ -1,6 +1,16 @@
39 This directory provides Amulet tests that focus on verification of Nova Cloud
40 Controller deployments.
41
42+test_* methods are called in lexical sort order, although each individual test
43+should be idempotent, and expected to pass regardless of run order.
44+
45+Test name convention to ensure desired test order:
46+ 1xx service and endpoint checks
47+ 2xx relation checks
48+ 3xx config checks
49+ 4xx functional checks
50+ 9xx restarts and other final checks
51+
52 In order to run tests, you'll need charm-tools installed (in addition to
53 juju, of course):
54 sudo add-apt-repository ppa:juju/stable
55
56=== modified file 'tests/basic_deployment.py'
57--- tests/basic_deployment.py 2015-10-05 06:50:03 +0000
58+++ tests/basic_deployment.py 2015-10-16 05:41:21 +0000
59@@ -1,5 +1,3 @@
60-#!/usr/bin/python
61-
62 import amulet
63 import os
64 import yaml
65@@ -10,8 +8,8 @@
66
67 from charmhelpers.contrib.openstack.amulet.utils import (
68 OpenStackAmuletUtils,
69- DEBUG, # flake8: noqa
70- ERROR
71+ DEBUG,
72+ # ERROR
73 )
74
75 # Use DEBUG to turn on debug logging
76@@ -24,12 +22,18 @@
77 def __init__(self, series=None, openstack=None, source=None, git=False,
78 stable=False):
79 """Deploy the entire test environment."""
80- super(NovaCCBasicDeployment, self).__init__(series, openstack, source, stable)
81+ super(NovaCCBasicDeployment, self).__init__(series, openstack,
82+ source, stable)
83 self.git = git
84 self._add_services()
85 self._add_relations()
86 self._configure_services()
87 self._deploy()
88+
89+ u.log.info('Waiting on extended status checks...')
90+ exclude_services = ['mysql']
91+ self._auto_wait_for_status(exclude_services=exclude_services)
92+
93 self._initialize_tests()
94
95 def _add_services(self):
96@@ -40,27 +44,31 @@
97 compatible with the local charm (e.g. stable or next).
98 """
99 this_service = {'name': 'nova-cloud-controller'}
100- other_services = [{'name': 'mysql'}, {'name': 'rabbitmq-server'},
101+ other_services = [{'name': 'mysql'},
102+ {'name': 'rabbitmq-server'},
103 {'name': 'nova-compute', 'units': 2},
104- {'name': 'keystone'}, {'name': 'glance'}]
105+ {'name': 'keystone'},
106+ {'name': 'glance'}]
107 super(NovaCCBasicDeployment, self)._add_services(this_service,
108 other_services)
109
110 def _add_relations(self):
111 """Add all of the relations for the services."""
112 relations = {
113- 'nova-cloud-controller:shared-db': 'mysql:shared-db',
114- 'nova-cloud-controller:identity-service': 'keystone:identity-service',
115- 'nova-cloud-controller:amqp': 'rabbitmq-server:amqp',
116- 'nova-cloud-controller:cloud-compute': 'nova-compute:cloud-compute',
117- 'nova-cloud-controller:image-service': 'glance:image-service',
118- 'nova-compute:image-service': 'glance:image-service',
119- 'nova-compute:shared-db': 'mysql:shared-db',
120- 'nova-compute:amqp': 'rabbitmq-server:amqp',
121- 'keystone:shared-db': 'mysql:shared-db',
122- 'glance:identity-service': 'keystone:identity-service',
123- 'glance:shared-db': 'mysql:shared-db',
124- 'glance:amqp': 'rabbitmq-server:amqp'
125+ 'nova-cloud-controller:shared-db': 'mysql:shared-db',
126+ 'nova-cloud-controller:identity-service': 'keystone:'
127+ 'identity-service',
128+ 'nova-cloud-controller:amqp': 'rabbitmq-server:amqp',
129+ 'nova-cloud-controller:cloud-compute': 'nova-compute:'
130+ 'cloud-compute',
131+ 'nova-cloud-controller:image-service': 'glance:image-service',
132+ 'nova-compute:image-service': 'glance:image-service',
133+ 'nova-compute:shared-db': 'mysql:shared-db',
134+ 'nova-compute:amqp': 'rabbitmq-server:amqp',
135+ 'keystone:shared-db': 'mysql:shared-db',
136+ 'glance:identity-service': 'keystone:identity-service',
137+ 'glance:shared-db': 'mysql:shared-db',
138+ 'glance:amqp': 'rabbitmq-server:amqp'
139 }
140 super(NovaCCBasicDeployment, self)._add_relations(relations)
141
142@@ -98,16 +106,24 @@
143 'http_proxy': amulet_http_proxy,
144 'https_proxy': amulet_http_proxy,
145 }
146- nova_cc_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
147- nova_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
148+
149+ nova_cc_config['openstack-origin-git'] = \
150+ yaml.dump(openstack_origin_git)
151+
152+ nova_config['openstack-origin-git'] = \
153+ yaml.dump(openstack_origin_git)
154
155 # Add some rate-limiting options to the charm. These will noop before
156 # icehouse.
157- nova_cc_config['api-rate-limit-rules'] = "( POST, '*', .*, 9999, MINUTE );"
158+ nova_cc_config['api-rate-limit-rules'] = \
159+ "( POST, '*', .*, 9999, MINUTE );"
160+
161 keystone_config = {'admin-password': 'openstack',
162 'admin-token': 'ubuntutesting'}
163+
164 configs = {'nova-cloud-controller': nova_cc_config,
165 'keystone': keystone_config, 'nova-compute': nova_config}
166+
167 super(NovaCCBasicDeployment, self)._configure_services(configs)
168
169 def _initialize_tests(self):
170@@ -120,6 +136,11 @@
171 self.nova_compute_sentry = self.d.sentry.unit['nova-compute/0']
172 self.glance_sentry = self.d.sentry.unit['glance/0']
173
174+ u.log.debug('openstack release val: {}'.format(
175+ self._get_openstack_release()))
176+ u.log.debug('openstack release str: {}'.format(
177+ self._get_openstack_release_string()))
178+
179 # Authenticate admin with keystone
180 self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
181 user='admin',
182@@ -155,32 +176,33 @@
183 password='password',
184 tenant=self.demo_tenant)
185
186- def test_services(self):
187+ def test_100_services(self):
188 """Verify the expected services are running on the corresponding
189 service units."""
190- commands = {
191- self.mysql_sentry: ['status mysql'],
192- self.rabbitmq_sentry: ['sudo service rabbitmq-server status'],
193- self.nova_cc_sentry: ['status nova-api-ec2',
194- 'status nova-api-os-compute',
195- 'status nova-objectstore',
196- 'status nova-cert',
197- 'status nova-scheduler'],
198- self.nova_compute_sentry: ['status nova-compute',
199- 'status nova-network',
200- 'status nova-api'],
201- self.keystone_sentry: ['status keystone'],
202- self.glance_sentry: ['status glance-registry', 'status glance-api']
203+ u.log.debug('Checking system services on units...')
204+ services = {
205+ self.mysql_sentry: ['mysql'],
206+ self.rabbitmq_sentry: ['rabbitmq-server'],
207+ self.nova_cc_sentry: ['nova-api-ec2',
208+ 'nova-api-os-compute',
209+ 'nova-conductor',
210+ 'nova-objectstore',
211+ 'nova-cert',
212+ 'nova-scheduler'],
213+ self.nova_compute_sentry: ['nova-compute',
214+ 'nova-network',
215+ 'nova-api'],
216+ self.keystone_sentry: ['keystone'],
217+ self.glance_sentry: ['glance-registry', 'glance-api']
218 }
219- if self._get_openstack_release() >= self.precise_grizzly:
220- commands[self.nova_cc_sentry] = ['status nova-conductor']
221
222- ret = u.validate_services(commands)
223+ ret = u.validate_services_by_name(services)
224 if ret:
225 amulet.raise_status(amulet.FAIL, msg=ret)
226
227- def test_service_catalog(self):
228+ def test_102_service_catalog(self):
229 """Verify that the service catalog endpoint data is valid."""
230+ u.log.debug('Checking keystone service catalog...')
231 endpoint_vol = {'adminURL': u.valid_url,
232 'region': 'RegionOne',
233 'publicURL': u.valid_url,
234@@ -189,30 +211,38 @@
235 'region': 'RegionOne',
236 'publicURL': u.valid_url,
237 'internalURL': u.valid_url}
238+
239 if self._get_openstack_release() >= self.precise_folsom:
240 endpoint_vol['id'] = u.not_null
241 endpoint_id['id'] = u.not_null
242+
243 if self._get_openstack_release() >= self.trusty_kilo:
244 expected = {'compute': [endpoint_vol], 'identity': [endpoint_id]}
245 else:
246 expected = {'s3': [endpoint_vol], 'compute': [endpoint_vol],
247 'ec2': [endpoint_vol], 'identity': [endpoint_id]}
248+
249 actual = self.keystone_demo.service_catalog.get_endpoints()
250
251 ret = u.validate_svc_catalog_endpoint_data(expected, actual)
252 if ret:
253 amulet.raise_status(amulet.FAIL, msg=ret)
254
255- def test_openstack_compute_api_endpoint(self):
256+ def test_104_openstack_compute_api_endpoint(self):
257 """Verify the openstack compute api (osapi) endpoint data."""
258+ u.log.debug('Checking compute endpoint data...')
259+
260 endpoints = self.keystone.endpoints.list()
261 admin_port = internal_port = public_port = '8774'
262- expected = {'id': u.not_null,
263- 'region': 'RegionOne',
264- 'adminurl': u.valid_url,
265- 'internalurl': u.valid_url,
266- 'publicurl': u.valid_url,
267- 'service_id': u.not_null}
268+
269+ expected = {
270+ 'id': u.not_null,
271+ 'region': 'RegionOne',
272+ 'adminurl': u.valid_url,
273+ 'internalurl': u.valid_url,
274+ 'publicurl': u.valid_url,
275+ 'service_id': u.not_null
276+ }
277
278 ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
279 public_port, expected)
280@@ -220,19 +250,23 @@
281 message = 'osapi endpoint: {}'.format(ret)
282 amulet.raise_status(amulet.FAIL, msg=message)
283
284- def test_ec2_api_endpoint(self):
285+ def test_106_ec2_api_endpoint(self):
286 """Verify the EC2 api endpoint data."""
287 if self._get_openstack_release() >= self.trusty_kilo:
288 return
289
290+ u.log.debug('Checking ec2 endpoint data...')
291 endpoints = self.keystone.endpoints.list()
292 admin_port = internal_port = public_port = '8773'
293- expected = {'id': u.not_null,
294- 'region': 'RegionOne',
295- 'adminurl': u.valid_url,
296- 'internalurl': u.valid_url,
297- 'publicurl': u.valid_url,
298- 'service_id': u.not_null}
299+
300+ expected = {
301+ 'id': u.not_null,
302+ 'region': 'RegionOne',
303+ 'adminurl': u.valid_url,
304+ 'internalurl': u.valid_url,
305+ 'publicurl': u.valid_url,
306+ 'service_id': u.not_null
307+ }
308
309 ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
310 public_port, expected)
311@@ -240,19 +274,22 @@
312 message = 'EC2 endpoint: {}'.format(ret)
313 amulet.raise_status(amulet.FAIL, msg=message)
314
315- def test_s3_api_endpoint(self):
316+ def test_108_s3_api_endpoint(self):
317 """Verify the S3 api endpoint data."""
318 if self._get_openstack_release() >= self.trusty_kilo:
319 return
320
321+ u.log.debug('Checking s3 endpoint data...')
322 endpoints = self.keystone.endpoints.list()
323 admin_port = internal_port = public_port = '3333'
324- expected = {'id': u.not_null,
325- 'region': 'RegionOne',
326- 'adminurl': u.valid_url,
327- 'internalurl': u.valid_url,
328- 'publicurl': u.valid_url,
329- 'service_id': u.not_null}
330+ expected = {
331+ 'id': u.not_null,
332+ 'region': 'RegionOne',
333+ 'adminurl': u.valid_url,
334+ 'internalurl': u.valid_url,
335+ 'publicurl': u.valid_url,
336+ 'service_id': u.not_null
337+ }
338
339 ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
340 public_port, expected)
341@@ -260,10 +297,12 @@
342 message = 'S3 endpoint: {}'.format(ret)
343 amulet.raise_status(amulet.FAIL, msg=message)
344
345- def test_nova_cc_shared_db_relation(self):
346+ def test_200_nova_cc_shared_db_relation(self):
347 """Verify the nova-cc to mysql shared-db relation data"""
348+ u.log.debug('Checking n-c-c:mysql db relation data...')
349 unit = self.nova_cc_sentry
350 relation = ['shared-db', 'mysql:shared-db']
351+
352 expected = {
353 'private-address': u.valid_ip,
354 'nova_database': 'nova',
355@@ -276,8 +315,9 @@
356 message = u.relation_error('nova-cc shared-db', ret)
357 amulet.raise_status(amulet.FAIL, msg=message)
358
359- def test_mysql_shared_db_relation(self):
360+ def test_202_mysql_shared_db_relation(self):
361 """Verify the mysql to nova-cc shared-db relation data"""
362+ u.log.debug('Checking mysql:n-c-c db relation data...')
363 unit = self.mysql_sentry
364 relation = ['shared-db', 'nova-cloud-controller:shared-db']
365 expected = {
366@@ -291,8 +331,9 @@
367 message = u.relation_error('mysql shared-db', ret)
368 amulet.raise_status(amulet.FAIL, msg=message)
369
370- def test_nova_cc_identity_service_relation(self):
371+ def test_204_nova_cc_identity_service_relation(self):
372 """Verify the nova-cc to keystone identity-service relation data"""
373+ u.log.debug('Checking n-c-c:keystone identity relation data...')
374 unit = self.nova_cc_sentry
375 relation = ['identity-service', 'keystone:identity-service']
376 expected = {
377@@ -320,8 +361,9 @@
378 message = u.relation_error('nova-cc identity-service', ret)
379 amulet.raise_status(amulet.FAIL, msg=message)
380
381- def test_keystone_identity_service_relation(self):
382+ def test_206_keystone_identity_service_relation(self):
383 """Verify the keystone to nova-cc identity-service relation data"""
384+ u.log.debug('Checking keystone:n-c-c identity relation data...')
385 unit = self.keystone_sentry
386 relation = ['identity-service',
387 'nova-cloud-controller:identity-service']
388@@ -347,8 +389,9 @@
389 message = u.relation_error('keystone identity-service', ret)
390 amulet.raise_status(amulet.FAIL, msg=message)
391
392- def test_nova_cc_amqp_relation(self):
393+ def test_208_nova_cc_amqp_relation(self):
394 """Verify the nova-cc to rabbitmq-server amqp relation data"""
395+ u.log.debug('Checking n-c-c:rmq amqp relation data...')
396 unit = self.nova_cc_sentry
397 relation = ['amqp', 'rabbitmq-server:amqp']
398 expected = {
399@@ -362,8 +405,9 @@
400 message = u.relation_error('nova-cc amqp', ret)
401 amulet.raise_status(amulet.FAIL, msg=message)
402
403- def test_rabbitmq_amqp_relation(self):
404+ def test_210_rabbitmq_amqp_relation(self):
405 """Verify the rabbitmq-server to nova-cc amqp relation data"""
406+ u.log.debug('Checking rmq:n-c-c amqp relation data...')
407 unit = self.rabbitmq_sentry
408 relation = ['amqp', 'nova-cloud-controller:amqp']
409 expected = {
410@@ -377,8 +421,11 @@
411 message = u.relation_error('rabbitmq amqp', ret)
412 amulet.raise_status(amulet.FAIL, msg=message)
413
414- def test_nova_cc_cloud_compute_relation(self):
415+ def test_212_nova_cc_cloud_compute_relation(self):
416 """Verify the nova-cc to nova-compute cloud-compute relation data"""
417+ u.log.debug('Checking n-c-c:nova-compute '
418+ 'cloud-compute relation data...')
419+
420 unit = self.nova_cc_sentry
421 relation = ['cloud-compute', 'nova-compute:cloud-compute']
422 expected = {
423@@ -396,8 +443,11 @@
424 message = u.relation_error('nova-cc cloud-compute', ret)
425 amulet.raise_status(amulet.FAIL, msg=message)
426
427- def test_nova_cloud_compute_relation(self):
428+ def test_214_nova_cloud_compute_relation(self):
429 """Verify the nova-compute to nova-cc cloud-compute relation data"""
430+ u.log.debug('Checking nova-compute:n-c-c '
431+ 'cloud-compute relation data...')
432+
433 unit = self.nova_compute_sentry
434 relation = ['cloud-compute', 'nova-cloud-controller:cloud-compute']
435 expected = {
436@@ -409,8 +459,9 @@
437 message = u.relation_error('nova-compute cloud-compute', ret)
438 amulet.raise_status(amulet.FAIL, msg=message)
439
440- def test_nova_cc_image_service_relation(self):
441+ def test_216_nova_cc_image_service_relation(self):
442 """Verify the nova-cc to glance image-service relation data"""
443+ u.log.debug('Checking n-c-c:glance image-service relation data...')
444 unit = self.nova_cc_sentry
445 relation = ['image-service', 'glance:image-service']
446 expected = {
447@@ -422,8 +473,9 @@
448 message = u.relation_error('nova-cc image-service', ret)
449 amulet.raise_status(amulet.FAIL, msg=message)
450
451- def test_glance_image_service_relation(self):
452+ def test_218_glance_image_service_relation(self):
453 """Verify the glance to nova-cc image-service relation data"""
454+ u.log.debug('Checking glance:n-c-c image-service relation data...')
455 unit = self.glance_sentry
456 relation = ['image-service', 'nova-cloud-controller:image-service']
457 expected = {
458@@ -436,72 +488,44 @@
459 message = u.relation_error('glance image-service', ret)
460 amulet.raise_status(amulet.FAIL, msg=message)
461
462- def test_z_restart_on_config_change(self):
463- """Verify that the specified services are restarted when the config
464- is changed.
465-
466- Note(coreycb): The method name with the _z_ is a little odd
467- but it forces the test to run last. It just makes things
468- easier because restarting services requires re-authorization.
469- """
470- # NOTE(coreycb): Skipping failing test on essex until resolved.
471- # config-flags don't take effect on essex.
472- if self._get_openstack_release() == self.precise_essex:
473- u.log.error("Skipping failing test until resolved")
474- return
475-
476- flags_set = 'quota_cores=20,quota_instances=40,quota_ram=102400'
477- flags_reset = 'quota_cores=10,quota_instances=20,quota_ram=51200'
478-
479- services = ['nova-api-ec2', 'nova-api-os-compute', 'nova-objectstore',
480- 'nova-cert', 'nova-scheduler', 'nova-conductor']
481- self.d.configure('nova-cloud-controller', {'config-flags': flags_set})
482- pgrep_full = True
483-
484- time = 20
485- conf = '/etc/nova/nova.conf'
486- for s in services:
487- if not u.service_restarted(self.nova_cc_sentry, s, conf,
488- pgrep_full=True, sleep_time=time):
489- self.d.configure('nova-cloud-controller',
490- {'config-flags': flags_reset})
491- msg = "service {} didn't restart after config change".format(s)
492- amulet.raise_status(amulet.FAIL, msg=msg)
493- time = 0
494-
495- self.d.configure('nova-cloud-controller', {'config-flags': flags_reset})
496-
497- def test_nova_default_config(self):
498+ def test_300_nova_default_config(self):
499 """Verify the data in the nova config file's default section."""
500 # NOTE(coreycb): Currently no way to test on essex because config file
501 # has no section headers.
502 if self._get_openstack_release() == self.precise_essex:
503 return
504
505+ u.log.debug('Checking nova config file data...')
506 unit = self.nova_cc_sentry
507 conf = '/etc/nova/nova.conf'
508- rabbitmq_relation = self.rabbitmq_sentry.relation('amqp',
509- 'nova-cloud-controller:amqp')
510- glance_relation = self.glance_sentry.relation('image-service',
511- 'nova-cloud-controller:image-service')
512- keystone_ep = self.keystone_demo.service_catalog.url_for(\
513- service_type='identity',
514- endpoint_type='publicURL')
515- keystone_ec2 = "{}/ec2tokens".format(keystone_ep)
516-
517- keystone_relation = self.keystone_sentry.relation('identity-service',
518- 'nova-cloud-controller:identity-service')
519- keystone_uri = "http://{}:{}/".format(keystone_relation['service_host'],
520- keystone_relation['service_port'])
521- identity_uri = "{}://{}:{}/".format(keystone_relation['auth_protocol'],
522- keystone_relation['service_host'],
523- keystone_relation['auth_port'])
524-
525- mysql_relation = self.mysql_sentry.relation('shared-db',
526- 'nova-cloud-controller:shared-db')
527+
528+ rmq_ncc_rel = self.rabbitmq_sentry.relation(
529+ 'amqp', 'nova-cloud-controller:amqp')
530+
531+ gl_ncc_rel = self.glance_sentry.relation(
532+ 'image-service', 'nova-cloud-controller:image-service')
533+
534+ ks_ep = self.keystone_demo.service_catalog.url_for(
535+ service_type='identity', endpoint_type='publicURL')
536+
537+ ks_ec2 = "{}/ec2tokens".format(ks_ep)
538+
539+ ks_ncc_rel = self.keystone_sentry.relation(
540+ 'identity-service', 'nova-cloud-controller:identity-service')
541+
542+ ks_uri = "http://{}:{}/".format(ks_ncc_rel['service_host'],
543+ ks_ncc_rel['service_port'])
544+
545+ id_uri = "{}://{}:{}/".format(ks_ncc_rel['auth_protocol'],
546+ ks_ncc_rel['service_host'],
547+ ks_ncc_rel['auth_port'])
548+
549+ db_ncc_rel = self.mysql_sentry.relation(
550+ 'shared-db', 'nova-cloud-controller:shared-db')
551+
552 db_uri = "mysql://{}:{}@{}/{}".format('nova',
553- mysql_relation['nova_password'],
554- mysql_relation['db_host'],
555+ db_ncc_rel['nova_password'],
556+ db_ncc_rel['db_host'],
557 'nova')
558
559 expected = {
560@@ -523,7 +547,7 @@
561 'enabled_apis': 'ec2,osapi_compute,metadata',
562 'auth_strategy': 'keystone',
563 'compute_driver': 'libvirt.LibvirtDriver',
564- 'keystone_ec2_url': keystone_ec2,
565+ 'keystone_ec2_url': ks_ec2,
566 'network_manager': 'nova.network.manager.FlatDHCPManager',
567 's3_listen_port': '3323',
568 'osapi_compute_listen_port': '8764',
569@@ -542,13 +566,13 @@
570 }
571 keystone_authtoken = {
572 'keystone_authtoken': {
573- 'auth_uri': keystone_uri,
574- 'auth_host': keystone_relation['service_host'],
575- 'auth_port': keystone_relation['auth_port'],
576- 'auth_protocol': keystone_relation['auth_protocol'],
577- 'admin_tenant_name': keystone_relation['service_tenant'],
578- 'admin_user': keystone_relation['service_username'],
579- 'admin_password': keystone_relation['service_password'],
580+ 'auth_uri': ks_uri,
581+ 'auth_host': ks_ncc_rel['service_host'],
582+ 'auth_port': ks_ncc_rel['auth_port'],
583+ 'auth_protocol': ks_ncc_rel['auth_protocol'],
584+ 'admin_tenant_name': ks_ncc_rel['service_tenant'],
585+ 'admin_user': ks_ncc_rel['service_username'],
586+ 'admin_password': ks_ncc_rel['service_password'],
587 }
588 }
589 expected.update(database)
590@@ -558,9 +582,9 @@
591 expected[d]['compute_driver'] = 'libvirt.LibvirtDriver'
592 expected[d]['rabbit_userid'] = 'nova'
593 expected[d]['rabbit_virtual_host'] = 'openstack'
594- expected[d]['rabbit_password'] = rabbitmq_relation['password']
595- expected[d]['rabbit_host'] = rabbitmq_relation['hostname']
596- expected[d]['glance_api_servers'] = glance_relation['glance-api-server']
597+ expected[d]['rabbit_password'] = rmq_ncc_rel['password']
598+ expected[d]['rabbit_host'] = rmq_ncc_rel['hostname']
599+ expected[d]['glance_api_servers'] = gl_ncc_rel['glance-api-server']
600
601 else:
602 database = {
603@@ -571,16 +595,16 @@
604 }
605 glance = {
606 'glance': {
607- 'api_servers': glance_relation['glance-api-server'],
608+ 'api_servers': gl_ncc_rel['glance-api-server'],
609 }
610 }
611 keystone_authtoken = {
612 'keystone_authtoken': {
613- 'identity_uri': identity_uri,
614- 'auth_uri': keystone_uri,
615- 'admin_tenant_name': keystone_relation['service_tenant'],
616- 'admin_user': keystone_relation['service_username'],
617- 'admin_password': keystone_relation['service_password'],
618+ 'identity_uri': id_uri,
619+ 'auth_uri': ks_uri,
620+ 'admin_tenant_name': ks_ncc_rel['service_tenant'],
621+ 'admin_user': ks_ncc_rel['service_username'],
622+ 'admin_password': ks_ncc_rel['service_password'],
623 'signing_dir': '/var/cache/nova',
624 }
625 }
626@@ -598,8 +622,8 @@
627 'oslo_messaging_rabbit': {
628 'rabbit_userid': 'nova',
629 'rabbit_virtual_host': 'openstack',
630- 'rabbit_password': rabbitmq_relation['password'],
631- 'rabbit_host': rabbitmq_relation['hostname'],
632+ 'rabbit_password': rmq_ncc_rel['password'],
633+ 'rabbit_host': rmq_ncc_rel['hostname'],
634 }
635 }
636 oslo_concurrency = {
637@@ -621,15 +645,41 @@
638 message = "nova config error: {}".format(ret)
639 amulet.raise_status(amulet.FAIL, msg=message)
640
641- def test_image_instance_create(self):
642+ def test_302_api_rate_limiting_is_enabled_for_icehouse_or_more(self):
643+ """
644+ The API rate limiting is enabled for icehouse or more. Otherwise the
645+ api-paste.ini file is left untouched.
646+ """
647+ u.log.debug('Checking api-paste config file data...')
648+
649+ unit = self.nova_cc_sentry
650+ conf = '/etc/nova/api-paste.ini'
651+ section = "filter:ratelimit"
652+ factory = ("nova.api.openstack.compute.limits:RateLimitingMiddleware"
653+ ".factory")
654+
655+ if self._get_openstack_release() >= self.precise_icehouse:
656+ expected = {"paste.filter_factory": factory,
657+ "limits": "( POST, '*', .*, 9999, MINUTE );"}
658+ else:
659+ expected = {"paste.filter_factory": factory}
660+
661+ ret = u.validate_config_data(unit, conf, section, expected)
662+ if ret:
663+ message = "api paste config error: {}".format(ret)
664+ amulet.raise_status(amulet.FAIL, msg=message)
665+
666+ def test_400_image_instance_create(self):
667 """Create an image/instance, verify they exist, and delete them."""
668 # NOTE(coreycb): Skipping failing test on essex until resolved. essex
669- # nova API calls are getting "Malformed request url (HTTP
670- # 400)".
671+ # nova API calls are getting "Malformed request url
672+ # (HTTP 400)".
673 if self._get_openstack_release() == self.precise_essex:
674- u.log.error("Skipping failing test until resolved")
675+ u.log.error("Skipping test (due to Essex)")
676 return
677
678+ u.log.debug('Checking nova instance creation...')
679+
680 image = u.create_cirros_image(self.glance, "cirros-image")
681 if not image:
682 amulet.raise_status(amulet.FAIL, msg="Image create failed")
683@@ -651,27 +701,56 @@
684 message = "nova cirros instance does not exist"
685 amulet.raise_status(amulet.FAIL, msg=message)
686
687- u.delete_image(self.glance, image)
688- u.delete_instance(self.nova_demo, instance)
689-
690- def test_api_rate_limiting_is_enabled_for_icehouse_or_more(self):
691- """
692- The API rate limiting is enabled for icehouse or more. Otherwise the
693- api-paste.ini file is left untouched.
694- """
695- unit = self.nova_cc_sentry
696- conf = '/etc/nova/api-paste.ini'
697- section = "filter:ratelimit"
698- factory = ("nova.api.openstack.compute.limits:RateLimitingMiddleware"
699- ".factory")
700-
701- if self._get_openstack_release() >= self.precise_icehouse:
702- expected = {"paste.filter_factory": factory,
703- "limits": "( POST, '*', .*, 9999, MINUTE );"}
704- else:
705- expected = {"paste.filter_factory": factory}
706-
707- ret = u.validate_config_data(unit, conf, section, expected)
708- if ret:
709- message = "api paste config error: {}".format(ret)
710- amulet.raise_status(amulet.FAIL, msg=message)
711+ u.delete_resource(self.glance.images, image.id,
712+ msg="glance image")
713+
714+ u.delete_resource(self.nova_demo.servers, instance.id,
715+ msg="nova instance")
716+
717+ def test_900_restart_on_config_change(self):
718+ """Verify that the specified services are restarted when the config
719+ is changed."""
720+ if self._get_openstack_release() == self.precise_essex:
721+ u.log.error("Skipping test (due to Essex)")
722+ return
723+
724+ u.log.info('Checking that conf files and system services respond '
725+ 'to a charm config change...')
726+
727+ sentry = self.nova_cc_sentry
728+ juju_service = 'nova-cloud-controller'
729+
730+ # Process names, corresponding conf files
731+ conf_file = '/etc/nova/nova.conf'
732+ services = {
733+ 'nova-api-ec2': conf_file,
734+ 'nova-api-os-compute': conf_file,
735+ 'nova-objectstore': conf_file,
736+ 'nova-cert': conf_file,
737+ 'nova-scheduler': conf_file,
738+ 'nova-conductor': conf_file
739+ }
740+
741+ # Expected default and alternate values
742+ flags_default = 'quota_cores=20,quota_instances=40,quota_ram=102400'
743+ flags_alt = 'quota_cores=10,quota_instances=20,quota_ram=51200'
744+ set_default = {'config-flags': flags_default}
745+ set_alternate = {'config-flags': flags_alt}
746+
747+ # Make config change, check for service restarts
748+ u.log.debug('Making config change on {}...'.format(juju_service))
749+ mtime = u.get_sentry_time(sentry)
750+ self.d.configure(juju_service, set_alternate)
751+
752+ sleep_time = 60
753+ for s, conf_file in services.iteritems():
754+ u.log.debug("Checking that service restarted: {}".format(s))
755+ if not u.validate_service_config_changed(sentry, mtime, s,
756+ conf_file,
757+ sleep_time=sleep_time):
758+ self.d.configure(juju_service, set_default)
759+ msg = "service {} didn't restart after config change".format(s)
760+ amulet.raise_status(amulet.FAIL, msg=msg)
761+ sleep_time = 0
762+
763+ self.d.configure(juju_service, set_default)
764
765=== modified file 'tests/charmhelpers/contrib/openstack/amulet/deployment.py'
766--- tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-09-25 14:35:19 +0000
767+++ tests/charmhelpers/contrib/openstack/amulet/deployment.py 2015-10-16 05:41:21 +0000
768@@ -14,6 +14,7 @@
769 # You should have received a copy of the GNU Lesser General Public License
770 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
771
772+import re
773 import six
774 from collections import OrderedDict
775 from charmhelpers.contrib.amulet.deployment import (
776@@ -114,6 +115,45 @@
777 for service, config in six.iteritems(configs):
778 self.d.configure(service, config)
779
780+ def _auto_wait_for_status(self, message=None, exclude_services=None,
781+ timeout=1800):
782+ """Wait for all units to have a specific extended status, except
783+ for any defined as excluded. Unless specified via message, any
784+ status containing any case of 'ready' will be considered a match.
785+
786+ Examples of message usage:
787+
788+ Wait for all unit status to CONTAIN any case of 'ready' or 'ok':
789+ message = re.compile('.*ready.*|.*ok.*', re.IGNORECASE)
790+
791+ Wait for all units to reach this status (exact match):
792+ message = 'Unit is ready'
793+
794+ Wait for all units to reach any one of these (exact match):
795+ message = re.compile('Unit is ready|OK|Ready')
796+
797+ Wait for at least one unit to reach this status (exact match):
798+ message = {'ready'}
799+
800+ See Amulet's sentry.wait_for_messages() for message usage detail.
801+ https://github.com/juju/amulet/blob/master/amulet/sentry.py
802+
803+ :param message: Expected status match
804+ :param exclude_services: List of juju service names to ignore
805+ :param timeout: Maximum time in seconds to wait for status match
806+ :returns: None. Raises if timeout is hit.
807+ """
808+
809+ if not message:
810+ message = re.compile('.*ready.*', re.IGNORECASE)
811+
812+ if not exclude_services:
813+ exclude_services = []
814+
815+ services = list(set(self.d.services.keys()) - set(exclude_services))
816+ service_messages = {service: message for service in services}
817+ self.d.sentry.wait_for_messages(service_messages, timeout=timeout)
818+
819 def _get_openstack_release(self):
820 """Get openstack release.
821

Subscribers

People subscribed via source and target branches