Merge lp:~1chb1n/charms/trusty/swift-storage/amulet-update-1508 into lp:~openstack-charmers-archive/charms/trusty/swift-storage/next

Proposed by Ryan Beisner on 2015-08-21
Status: Merged
Merged at revision: 77
Proposed branch: lp:~1chb1n/charms/trusty/swift-storage/amulet-update-1508
Merge into: lp:~openstack-charmers-archive/charms/trusty/swift-storage/next
Diff against target: 494 lines (+166/-120)
8 files modified
Makefile (+6/-9)
metadata.yaml (+2/-1)
tests/00-setup (+7/-3)
tests/020-basic-trusty-liberty (+11/-0)
tests/021-basic-wily-liberty (+9/-0)
tests/README (+10/-0)
tests/basic_deployment.py (+102/-107)
tests/tests.yaml (+19/-0)
To merge this branch: bzr merge lp:~1chb1n/charms/trusty/swift-storage/amulet-update-1508
Reviewer Review Type Date Requested Status
Corey Bryant 2015-08-21 Approve on 2015-08-25
Adam Collard (community) Approve on 2015-08-24
Review via email: mp+268788@code.launchpad.net

This proposal supersedes a proposal from 2015-08-21.

Description of the Change

Update amulet tests, enable T-K, V-K, prep for T-L and W-L.

To post a comment you must log in.

charm_lint_check #8487 swift-storage-next for 1chb1n mp268788
    LINT OK: passed

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

charm_unit_test #7878 swift-storage-next for 1chb1n mp268788
    UNIT OK: passed

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

charm_amulet_test #5947 swift-storage-next for 1chb1n mp268788
    AMULET OK: passed

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

81. By Ryan Beisner on 2015-08-22

update makefile, correct import order

charm_lint_check #8544 swift-storage-next for 1chb1n mp268788
    LINT OK: passed

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

charm_unit_test #7932 swift-storage-next for 1chb1n mp268788
    UNIT OK: passed

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

charm_amulet_test #5956 swift-storage-next for 1chb1n mp268788
    AMULET OK: passed

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

Adam Collard (adam-collard) wrote :

Broadly looks good, thanks for the work to freshen this up! I have a few comments inline.

review: Needs Information
Ryan Beisner (1chb1n) wrote :

Thank you for the review, replies in line. 1 modification will be pushed momentarily re: dependency.

82. By Ryan Beisner on 2015-08-24

adjust tests.yaml for superfluous python-amulet

charm_lint_check #8649 swift-storage-next for 1chb1n mp268788
    LINT OK: passed

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

charm_unit_test #7986 swift-storage-next for 1chb1n mp268788
    UNIT OK: passed

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

Adam Collard (adam-collard) wrote :

Looks good, thanks for explaining.

review: Approve

charm_amulet_test #6014 swift-storage-next for 1chb1n mp268788
    AMULET OK: passed

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

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2015-08-11 08:17:24 +0000
3+++ Makefile 2015-08-24 13:33:42 +0000
4@@ -2,20 +2,17 @@
5 PYTHON := /usr/bin/env python
6
7 lint:
8- @flake8 lib
9- @flake8 hooks
10- @flake8 unit_tests tests
11+ @flake8 --exclude hooks/charmhelpers,tests/charmhelpers \
12+ actions lib hooks unit_tests tests
13 @charm proof
14
15-unit_test:
16+test:
17+ @# Bundletester expects unit tests here.
18 @echo Starting unit tests...
19 @$(PYTHON) /usr/bin/nosetests -v --nologcapture --with-coverage unit_tests
20
21-test:
22+functional_test:
23 @echo Starting Amulet tests...
24- # coreycb note: The -v should only be temporary until Amulet sends
25- # raise_status() messages to stderr:
26- # https://bugs.launchpad.net/amulet/+bug/1320357
27 @juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
28
29 bin/charm_helpers_sync.py:
30@@ -31,4 +28,4 @@
31 bzr push lp:charms/swift-storage
32 bzr push lp:charms/trusty/swift-storage
33
34-.PHONY: lint unit_test test sync publish
35+.PHONY: lint test functional_test sync publish
36
37=== modified file 'metadata.yaml'
38--- metadata.yaml 2014-10-30 05:52:15 +0000
39+++ metadata.yaml 2015-08-24 13:33:42 +0000
40@@ -3,7 +3,8 @@
41 summary: "Swift storage node"
42 description: |
43 Contains swift-object, swift-container and swift-account servers.
44-categories:
45+tags:
46+ - openstack
47 - file-servers
48 provides:
49 nrpe-external-master:
50
51=== modified file 'tests/00-setup'
52--- tests/00-setup 2015-08-11 13:58:24 +0000
53+++ tests/00-setup 2015-08-24 13:33:42 +0000
54@@ -4,9 +4,13 @@
55
56 sudo add-apt-repository --yes ppa:juju/stable
57 sudo apt-get update --yes
58-sudo apt-get install --yes python-amulet \
59- python-swiftclient \
60+sudo apt-get install --yes amulet \
61+ python-cinderclient \
62+ python-distro-info \
63 python-glanceclient \
64 python-heatclient \
65 python-keystoneclient \
66- python-novaclient
67+ python-neutronclient \
68+ python-novaclient \
69+ python-pika \
70+ python-swiftclient
71
72=== modified file 'tests/010-basic-precise-essex' (properties changed: +x to -x)
73=== modified file 'tests/017-basic-trusty-kilo' (properties changed: -x to +x)
74=== modified file 'tests/019-basic-vivid-kilo' (properties changed: -x to +x)
75=== added file 'tests/020-basic-trusty-liberty'
76--- tests/020-basic-trusty-liberty 1970-01-01 00:00:00 +0000
77+++ tests/020-basic-trusty-liberty 2015-08-24 13:33:42 +0000
78@@ -0,0 +1,11 @@
79+#!/usr/bin/python
80+
81+"""Amulet tests on a basic swift-storage deployment on trusty-liberty."""
82+
83+from basic_deployment import SwiftStorageBasicDeployment
84+
85+if __name__ == '__main__':
86+ deployment = SwiftStorageBasicDeployment(series='trusty',
87+ openstack='cloud:trusty-liberty',
88+ source='cloud:trusty-updates/liberty')
89+ deployment.run_tests()
90
91=== added file 'tests/021-basic-wily-liberty'
92--- tests/021-basic-wily-liberty 1970-01-01 00:00:00 +0000
93+++ tests/021-basic-wily-liberty 2015-08-24 13:33:42 +0000
94@@ -0,0 +1,9 @@
95+#!/usr/bin/python
96+
97+"""Amulet tests on a basic swift-storage deployment on wily-liberty."""
98+
99+from basic_deployment import SwiftStorageBasicDeployment
100+
101+if __name__ == '__main__':
102+ deployment = SwiftStorageBasicDeployment(series='wily')
103+ deployment.run_tests()
104
105=== modified file 'tests/README'
106--- tests/README 2014-09-29 21:14:05 +0000
107+++ tests/README 2015-08-24 13:33:42 +0000
108@@ -1,6 +1,16 @@
109 This directory provides Amulet tests that focus on verification of swift-storage
110 deployments.
111
112+test_* methods are called in lexical sort order, although each individual test
113+should be idempotent, and expected to pass regardless of run order.
114+
115+Test name convention to ensure desired test order:
116+ 1xx service and endpoint checks
117+ 2xx relation checks
118+ 3xx config checks
119+ 4xx functional checks
120+ 9xx restarts and other final checks
121+
122 In order to run tests, you'll need charm-tools installed (in addition to
123 juju, of course):
124 sudo add-apt-repository ppa:juju/stable
125
126=== modified file 'tests/basic_deployment.py'
127--- tests/basic_deployment.py 2015-08-17 13:44:42 +0000
128+++ tests/basic_deployment.py 2015-08-24 13:33:42 +0000
129@@ -1,3 +1,5 @@
130+import time
131+
132 import amulet
133 import swiftclient
134
135@@ -78,6 +80,14 @@
136 self.swift_proxy_sentry = self.d.sentry.unit['swift-proxy/0']
137 self.swift_storage_sentry = self.d.sentry.unit['swift-storage/0']
138
139+ u.log.debug('openstack release val: {}'.format(
140+ self._get_openstack_release()))
141+ u.log.debug('openstack release str: {}'.format(
142+ self._get_openstack_release_string()))
143+
144+ # Let things settle a bit before moving forward
145+ time.sleep(30)
146+
147 # Authenticate admin with keystone
148 self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
149 user='admin',
150@@ -119,9 +129,10 @@
151 password='password',
152 tenant=self.demo_tenant)
153
154- def test_services(self):
155+ def test_100_services(self):
156 """Verify the expected services are running on the corresponding
157 service units."""
158+ u.log.debug('Checking system services...')
159 swift_storage_services = ['swift-account',
160 'swift-account-auditor',
161 'swift-account-reaper',
162@@ -139,8 +150,8 @@
163 service_names = {
164 self.mysql_sentry: ['mysql'],
165 self.keystone_sentry: ['keystone'],
166- self.glance_sentry: [
167- 'glance-registry', 'glance-api'],
168+ self.glance_sentry: ['glance-registry',
169+ 'glance-api'],
170 self.swift_proxy_sentry: ['swift-proxy'],
171 self.swift_storage_sentry: swift_storage_services
172 }
173@@ -149,8 +160,9 @@
174 if ret:
175 amulet.raise_status(amulet.FAIL, msg=ret)
176
177- def test_users(self):
178+ def test_102_users(self):
179 """Verify all existing roles."""
180+ u.log.debug('Checking keystone users...')
181 user1 = {'name': 'demoUser',
182 'enabled': True,
183 'tenantId': u.not_null,
184@@ -178,19 +190,15 @@
185 if ret:
186 amulet.raise_status(amulet.FAIL, msg=ret)
187
188- def test_service_catalog(self):
189+ def test_104_keystone_service_catalog(self):
190 """Verify that the service catalog endpoint data is valid."""
191- endpoint_vol = {'adminURL': u.valid_url,
192- 'region': 'RegionOne',
193- 'publicURL': u.valid_url,
194- 'internalURL': u.valid_url}
195+ u.log.debug('Checking keystone service catalog...')
196 endpoint_id = {'adminURL': u.valid_url,
197 'region': 'RegionOne',
198 'publicURL': u.valid_url,
199- 'internalURL': u.valid_url}
200- if self._get_openstack_release() >= self.precise_folsom:
201- endpoint_vol['id'] = u.not_null
202- endpoint_id['id'] = u.not_null
203+ 'internalURL': u.valid_url,
204+ 'id': u.not_null}
205+
206 expected = {'image': [endpoint_id], 'object-store': [endpoint_id],
207 'identity': [endpoint_id]}
208 actual = self.keystone_demo.service_catalog.get_endpoints()
209@@ -199,8 +207,9 @@
210 if ret:
211 amulet.raise_status(amulet.FAIL, msg=ret)
212
213- def test_openstack_object_store_endpoint(self):
214+ def test_106_swift_object_store_endpoint(self):
215 """Verify the swift object-store endpoint data."""
216+ u.log.debug('Checking keystone endpoint for swift object store...')
217 endpoints = self.keystone.endpoints.list()
218 admin_port = internal_port = public_port = '8080'
219 expected = {'id': u.not_null,
220@@ -216,9 +225,10 @@
221 message = 'object-store endpoint: {}'.format(ret)
222 amulet.raise_status(amulet.FAIL, msg=message)
223
224- def test_swift_storage_swift_storage_relation(self):
225+ def test_200_swift_storage_swift_storage_relation(self):
226 """Verify the swift-storage to swift-proxy swift-storage relation
227 data."""
228+ u.log.debug('Checking swift:swift-proxy swift-storage relation...')
229 unit = self.swift_storage_sentry
230 relation = ['swift-storage', 'swift-proxy:swift-storage']
231 expected = {
232@@ -235,9 +245,10 @@
233 message = u.relation_error('swift-storage swift-storage', ret)
234 amulet.raise_status(amulet.FAIL, msg=message)
235
236- def test_swift_proxy_swift_storage_relation(self):
237+ def test_202_swift_proxy_swift_storage_relation(self):
238 """Verify the swift-proxy to swift-storage swift-storage relation
239 data."""
240+ u.log.debug('Checking swift-proxy:swift swift-storage relation...')
241 unit = self.swift_proxy_sentry
242 relation = ['swift-storage', 'swift-storage:swift-storage']
243 expected = {
244@@ -252,56 +263,10 @@
245 message = u.relation_error('swift-proxy swift-storage', ret)
246 amulet.raise_status(amulet.FAIL, msg=message)
247
248- def test_z_restart_on_config_change(self):
249- """Verify that the specified services are restarted when the config
250- is changed.
251-
252- Note(coreycb): The method name with the _z_ is a little odd
253- but it forces the test to run last. It just makes things
254- easier because restarting services requires re-authorization.
255- """
256- # NOTE(coreycb): Skipping failing test on until resolved. This test
257- # fails because the config file's last mod time is
258- # slightly after the process' last mod time.
259- if self._get_openstack_release() >= self.precise_essex:
260- u.log.error("Skipping failing test until resolved")
261- return
262-
263- services = {'swift-account-server': 'account-server.conf',
264- 'swift-account-auditor': 'account-server.conf',
265- 'swift-account-reaper': 'account-server.conf',
266- 'swift-account-replicator': 'account-server.conf',
267- 'swift-container-server': 'container-server.conf',
268- 'swift-container-auditor': 'container-server.conf',
269- 'swift-container-replicator': 'container-server.conf',
270- 'swift-container-updater': 'container-server.conf',
271- 'swift-object-server': 'object-server.conf',
272- 'swift-object-auditor': 'object-server.conf',
273- 'swift-object-replicator': 'object-server.conf',
274- 'swift-object-updater': 'object-server.conf'}
275- if self._get_openstack_release() >= self.precise_icehouse:
276- services['swift-container-sync'] = 'container-server.conf'
277-
278- self.d.configure('swift-storage',
279- {'object-server-threads-per-disk': '2'})
280-
281- time = 20
282- for s, conf in services.iteritems():
283- config = '/etc/swift/{}'.format(conf)
284- if not u.service_restarted(self.swift_storage_sentry, s, config,
285- pgrep_full=True, sleep_time=time):
286- self.d.configure('swift-storage',
287- {'object-server-threads-per-disk': '4'})
288- msg = "service {} didn't restart after config change".format(s)
289- amulet.raise_status(amulet.FAIL, msg=msg)
290- time = 0
291-
292- self.d.configure('swift-storage',
293- {'object-server-threads-per-disk': '4'})
294-
295- def test_swift_config(self):
296+ def test_300_swift_config(self):
297 """Verify the data in the swift-hash section of the swift config
298 file."""
299+ u.log.debug('Checking swift config...')
300 unit = self.swift_storage_sentry
301 conf = '/etc/swift/swift.conf'
302 swift_proxy_relation = self.swift_proxy_sentry.relation(
303@@ -315,8 +280,9 @@
304 message = "swift config error: {}".format(ret)
305 amulet.raise_status(amulet.FAIL, msg=message)
306
307- def test_account_server_config(self):
308+ def test_302_account_server_config(self):
309 """Verify the data in the account server config file."""
310+ u.log.debug('Checking swift account-server config...')
311 unit = self.swift_storage_sentry
312 conf = '/etc/swift/account-server.conf'
313 expected = {
314@@ -343,8 +309,9 @@
315 message = "account server config error: {}".format(ret)
316 amulet.raise_status(amulet.FAIL, msg=message)
317
318- def test_container_server_config(self):
319+ def test_304_container_server_config(self):
320 """Verify the data in the container server config file."""
321+ u.log.debug('Checking swift container-server config...')
322 unit = self.swift_storage_sentry
323 conf = '/etc/swift/container-server.conf'
324 expected = {
325@@ -372,8 +339,9 @@
326 message = "container server config error: {}".format(ret)
327 amulet.raise_status(amulet.FAIL, msg=message)
328
329- def test_object_server_config(self):
330+ def test_306_object_server_config(self):
331 """Verify the data in the object server config file."""
332+ u.log.debug('Checking swift object-server config...')
333 unit = self.swift_storage_sentry
334 conf = '/etc/swift/object-server.conf'
335 expected = {
336@@ -404,35 +372,17 @@
337 message = "object server config error: {}".format(ret)
338 amulet.raise_status(amulet.FAIL, msg=message)
339
340- def test_image_create(self):
341+ def test_400_swift_backed_image_create(self):
342 """Create an instance in glance, which is backed by swift, and validate
343- that some of the metadata for the image match in glance and swift.
344- """
345- # NOTE(coreycb): Skipping failing test on folsom until resolved. On
346- # folsom only, uploading an image to glance gets 400 Bad
347- # Request - Error uploading image: (error): [Errno 111]
348- # ECONNREFUSED (HTTP 400)
349- if self._get_openstack_release() == self.precise_folsom:
350- u.log.error("Skipping failing test until resolved")
351- return
352-
353- # Create glance image
354- image = u.create_cirros_image(self.glance, "cirros-image")
355- if not image:
356- amulet.raise_status(amulet.FAIL, msg="Image create failed")
357-
358- # Validate that cirros image exists in glance and get its checksum/size
359- images = list(self.glance.images.list())
360- if len(images) != 1:
361- msg = "Expected 1 glance image, found {}".format(len(images))
362- amulet.raise_status(amulet.FAIL, msg=msg)
363-
364- if images[0].name != 'cirros-image':
365- message = "cirros image does not exist"
366- amulet.raise_status(amulet.FAIL, msg=message)
367-
368- glance_image_md5 = image.checksum
369- glance_image_size = image.size
370+ that some of the metadata for the image match in glance and swift."""
371+ u.log.debug('Checking swift objects and containers with a '
372+ 'swift-backed glance image...')
373+
374+ # Create swift-backed glance image
375+ img_new = u.create_cirros_image(self.glance, "cirros-image-1")
376+ img_id = img_new.id
377+ img_md5 = img_new.checksum
378+ img_size = img_new.size
379
380 # Validate that swift object's checksum/size match that from glance
381 headers, containers = self.swift.get_account()
382@@ -451,18 +401,67 @@
383 swift_object_size = objects[0].get('bytes')
384 swift_object_md5 = objects[0].get('hash')
385
386- if glance_image_size != swift_object_size:
387+ if img_size != swift_object_size:
388 msg = "Glance image size {} != swift object size {}".format(
389- glance_image_size, swift_object_size)
390+ img_size, swift_object_size)
391 amulet.raise_status(amulet.FAIL, msg=msg)
392
393- if glance_image_md5 != swift_object_md5:
394+ if img_md5 != swift_object_md5:
395 msg = "Glance image hash {} != swift object hash {}".format(
396- glance_image_md5, swift_object_md5)
397+ img_md5, swift_object_md5)
398 amulet.raise_status(amulet.FAIL, msg=msg)
399
400 # Cleanup
401- u.delete_image(self.glance, image)
402+ u.delete_resource(self.glance.images, img_id, msg="glance image")
403+ u.log.info('OK')
404+
405+ def test_900_restart_on_config_change(self):
406+ """Verify that the specified services are restarted when the config
407+ is changed."""
408+ u.log.info('Checking that conf files and system services respond '
409+ 'to a charm config change...')
410+ sentry = self.swift_storage_sentry
411+ juju_service = 'swift-storage'
412+
413+ # Expected default and alternate values
414+ set_default = {'object-server-threads-per-disk': '4'}
415+ set_alternate = {'object-server-threads-per-disk': '2'}
416+
417+ # Config file affected by juju set config change, and
418+ # services which are expected to restart upon config change
419+ services = {'swift-account-server': 'account-server.conf',
420+ 'swift-account-auditor': 'account-server.conf',
421+ 'swift-account-reaper': 'account-server.conf',
422+ 'swift-account-replicator': 'account-server.conf',
423+ 'swift-container-server': 'container-server.conf',
424+ 'swift-container-auditor': 'container-server.conf',
425+ 'swift-container-replicator': 'container-server.conf',
426+ 'swift-container-updater': 'container-server.conf',
427+ 'swift-object-server': 'object-server.conf',
428+ 'swift-object-auditor': 'object-server.conf',
429+ 'swift-object-replicator': 'object-server.conf',
430+ 'swift-object-updater': 'object-server.conf',
431+ 'swift-container-sync': 'container-server.conf'}
432+
433+ # Make config change, check for service restarts
434+ u.log.debug('Making config change on {}...'.format(juju_service))
435+ mtime = u.get_sentry_time(sentry)
436+ self.d.configure(juju_service, set_alternate)
437+
438+ sleep_time = 40
439+ for s, conf_file in services.iteritems():
440+ u.log.debug("Checking that service restarted: {}".format(s))
441+ conf_file_abs = '/etc/swift/{}'.format(conf_file)
442+ if not u.validate_service_config_changed(sentry, mtime, s,
443+ conf_file_abs,
444+ sleep_time=sleep_time,
445+ pgrep_full=True):
446+ self.d.configure(juju_service, set_default)
447+ msg = "service {} didn't restart after config change".format(s)
448+ amulet.raise_status(amulet.FAIL, msg=msg)
449+ sleep_time = 0
450+
451+ self.d.configure(juju_service, set_default)
452
453 def _assert_services(self, should_run):
454 swift_storage_services = ['swift-account-auditor',
455@@ -506,12 +505,8 @@
456
457 self._assert_services(should_run=True)
458
459- def test_z_actions(self):
460- """Pause and then resume swift-storage.
461-
462- Note(sparkiegeek): The method name with the _z_ is a little odd
463- but it forces the test to run last. It just makes things
464- easier because restarting services requires re-authorization.
465- """
466+ def test_910_pause_resume_actions(self):
467+ """Pause and then resume swift-storage."""
468+ u.log.debug('Checking pause/resume actions...')
469 self._test_pause()
470 self._test_resume()
471
472=== added file 'tests/tests.yaml'
473--- tests/tests.yaml 1970-01-01 00:00:00 +0000
474+++ tests/tests.yaml 2015-08-24 13:33:42 +0000
475@@ -0,0 +1,19 @@
476+bootstrap: true
477+reset: true
478+virtualenv: true
479+makefile:
480+ - lint
481+ - test
482+sources:
483+ - ppa:juju/stable
484+packages:
485+ - amulet
486+ - python-cinderclient
487+ - python-distro-info
488+ - python-glanceclient
489+ - python-heatclient
490+ - python-keystoneclient
491+ - python-neutronclient
492+ - python-novaclient
493+ - python-pika
494+ - python-swiftclient

Subscribers

People subscribed via source and target branches