Merge lp:~ack/charms/trusty/keystone/pause-and-resume into lp:~openstack-charmers-archive/charms/trusty/keystone/next

Proposed by Alberto Donato
Status: Merged
Merged at revision: 173
Proposed branch: lp:~ack/charms/trusty/keystone/pause-and-resume
Merge into: lp:~openstack-charmers-archive/charms/trusty/keystone/next
Diff against target: 584 lines (+300/-48)
12 files modified
.coveragerc (+1/-0)
actions.yaml (+11/-0)
actions/actions.py (+56/-0)
actions/git_reinstall.py (+3/-5)
charm-helpers-hooks.yaml (+1/-1)
hooks/keystone_utils.py (+11/-22)
tests/basic_deployment.py (+33/-0)
unit_tests/test_actions.py (+150/-0)
unit_tests/test_actions_git_reinstall.py (+6/-4)
unit_tests/test_keystone_contexts.py (+16/-6)
unit_tests/test_keystone_hooks.py (+9/-9)
unit_tests/test_keystone_utils.py (+3/-1)
To merge this branch: bzr merge lp:~ack/charms/trusty/keystone/pause-and-resume
Reviewer Review Type Date Requested Status
Billy Olsen Approve
Adam Collard (community) Approve
Ryan Beisner (community) Approve
Geoff Teale (community) Approve
OpenStack Charmers Pending
Review via email: mp+267931@code.launchpad.net

Description of the change

This branch adds pause/resume actions that can be used to pause the service for maintenance on a unit.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

There's also a charmhelpers sync to pull fixes for service_pause/resume.

Revision history for this message
Adam Collard (adam-collard) wrote :

You should stop all of the services that are started by the charm - namely apache2 and haproxy - look at BASE_RESOURCE_MAP in keystone_utils.py

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

charm_lint_check #7984 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7398 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5776 keystone-next for ack mp267931
    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/12070271/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5776/

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

charm_lint_check #7986 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7400 keystone-next for ack mp267931
    UNIT FAIL: unit-test failed

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

Full unit test output: http://paste.ubuntu.com/12070303/
Build: http://10.245.162.77:8080/job/charm_unit_test/7400/

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

charm_amulet_test #5778 keystone-next for ack mp267931
    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/12070351/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5778/

Revision history for this message
Geoff Teale (tealeg) wrote :

+1 From me.

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

charm_unit_test #7402 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_lint_check #7989 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_lint_check #8040 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7451 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5784 keystone-next for ack mp267931
    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/12077756/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5784/

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

charm_lint_check #8041 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7452 keystone-next for ack mp267931
    UNIT FAIL: unit-test failed

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

Full unit test output: http://paste.ubuntu.com/12077979/
Build: http://10.245.162.77:8080/job/charm_unit_test/7452/

Revision history for this message
Alberto Donato (ack) wrote :

> You should stop all of the services that are started by the charm - namely
> apache2 and haproxy - look at BASE_RESOURCE_MAP in keystone_utils.py

Good catch, it's fixed now.

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

charm_lint_check #8043 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7454 keystone-next for ack mp267931
    UNIT FAIL: unit-test failed

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

Full unit test output: http://paste.ubuntu.com/12078204/
Build: http://10.245.162.77:8080/job/charm_unit_test/7454/

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

charm_amulet_test #5787 keystone-next for ack mp267931
    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/12078264/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5787/

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

charm_amulet_test #5785 keystone-next for ack mp267931
    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/12078388/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5785/

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

Thank you for your work on this. These will be great test additions.

I'd like to see the added amulet tests and helpers land in basic_deployment.py (or charmhelpers where appropriate) so that we can maintain consistency across the os-charms in the way that we iterate ubuntu/openstack series/release.

This means adding new test_ methods in basic_deployment.py, each of which should be idempotent, and not dependent on the run order of the other tests.

If there are OpenStack-specific, amulet-specific helpers which are useful in other charm tests, please land those in charmhelpers/contrib/openstack/amulet/utils.py.

If there are non-OpenStack-specific, amulet-specific helpers which are useful in other charm tests, please land those in charmhelpers/contrib/amulet/utils.py.

Often times, during test dev, I'll keep all of my helpers as local helpers in basic_deployment.py. Then once I have them the way that I want them, pluck them out into charmhelpers if they are potentially useful for writing tests in other charms.

Feel free to holler with any questions. Thanks again!

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

charm_lint_check #8192 keystone-next for ack mp267931
    LINT FAIL: lint-test failed

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

Full lint test output: http://paste.ubuntu.com/12107343/
Build: http://10.245.162.77:8080/job/charm_lint_check/8192/

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

charm_unit_test #7594 keystone-next for ack mp267931
    UNIT OK: passed

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

195. By Alberto Donato

Lint.

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

charm_lint_check #8193 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7595 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5838 keystone-next for ack mp267931
    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/12107613/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5838/

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

charm_amulet_test #5839 keystone-next for ack mp267931
    AMULET OK: passed

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

196. By Alberto Donato

Move actions to action.py

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

charm_lint_check #8338 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7735 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5881 keystone-next for ack mp267931
    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/12122634/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5881/

197. By Alberto Donato

Fix mocking, again.

198. By Alberto Donato

Add missing files,

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

charm_lint_check #8339 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7736 keystone-next for ack mp267931
    UNIT FAIL: unit-test failed

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

Full unit test output: http://paste.ubuntu.com/12122747/
Build: http://10.245.162.77:8080/job/charm_unit_test/7736/

199. By Alberto Donato

Fix unittest.

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

charm_amulet_test #5882 keystone-next for ack mp267931
    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/12122835/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5882/

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

charm_lint_check #8340 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7737 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5883 keystone-next for ack mp267931
    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/12123034/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5883/

200. By Alberto Donato

Fix docstrings.

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

charm_lint_check #8341 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7738 keystone-next for ack mp267931
    UNIT OK: passed

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

201. By Alberto Donato

Add missing shebang.

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

charm_amulet_test #5884 keystone-next for ack mp267931
    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/12123486/
Build: http://10.245.162.77:8080/job/charm_amulet_test/5884/

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

charm_lint_check #8342 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7739 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5885 keystone-next for ack mp267931
    AMULET OK: passed

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

Revision history for this message
Alberto Donato (ack) wrote :

@Ryan, thanks for the feedback. I've aligned the changes in this branch with the swift-storage one.

It should be good for another round of review.

Revision history for this message
Adam Collard (adam-collard) wrote :

5 inline comments below :)

202. By Alberto Donato

Merge from -next.

203. By Alberto Donato

Undo charm sync.

204. By Alberto Donato

Address review comments.

205. By Alberto Donato

Use right executable names.

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

charm_lint_check #8367 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7764 keystone-next for ack mp267931
    UNIT OK: passed

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

Revision history for this message
Alberto Donato (ack) wrote :

> 5 inline comments below :)

All comments addressed, thanks

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

charm_lint_check #8368 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7765 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #5910 keystone-next for ack mp267931
    AMULET OK: passed

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

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

RE: Amulet tests

Thank you for your work on this.

Please do another charm-helper sync to pull in sparkiegeek's tests/charmhelpers/ system service status check and py3 drive-by fixes.

Otherwise, looks good to me.

206. By Alberto Donato

charmhelpers sync.

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

charm_lint_check #8483 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7874 keystone-next for ack mp267931
    UNIT OK: passed

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

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

Although the amulet job isn't done, I checked its status as of 019 vivid-kilo, and all passed.

All clear to merge as far as test perspective.

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

charm_amulet_test #5942 keystone-next for ack mp267931
    AMULET OK: passed

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

207. By Alberto Donato

Merge from next, fix conflict.

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

charm_lint_check #8647 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #7984 keystone-next for ack mp267931
    UNIT OK: passed

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

Revision history for this message
Adam Collard (adam-collard) wrote :

Thanks for your patience and work on getting this to match style of swift-storage. Looks good! +1

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

charm_amulet_test #6012 keystone-next for ack mp267931
    AMULET OK: passed

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

Revision history for this message
Billy Olsen (billy-olsen) wrote :

Thanks for the submission! I think this generally looks good and would be quite pleased to approve it for a single unit operation. However, in the case where keystone is scaled out and paired with the hacluster charm I think we want to do some cluster appropriate operations first (e.g. move resources off-node pre-emptively).

That's probably common code to be shared amongst other charms, but I think we definitely need to consider the scenario in which a service is paused/resumed in a cluster. If its paused and resources are moved away, does it need to be able to ensure that resources cannot be moved back to the node which may cause confusion.

Will mark the review as Needs Information for now while this is sorted.

review: Needs Information
Revision history for this message
Billy Olsen (billy-olsen) wrote :

After discussion, the hacluster charm can handle the move of the VIP - which is probably an appropriate place to put it. It needs to move the vip off of this node and mark the cluster in maintenance mode so that services aren't moved around. That can be handled by the hacluster charm itself.

However, this would introduce a 2 step process for the user to be able to do things without service disruption. It would require they first run the pause action against the hacluster charm and then run the pause action against the keystone charm. It would be ideal if the charm could enforce this or invoke the hacluster pause action for the node, however that might be over complicating things for the basic building blocks here.

At a minimum I think we need some better docs describing this behavior in the actions.yaml file and possibly the consequences of not performing the node movement.

Thinking something along the lines of (though I'm sure there's better wordsmithing available):

Note: when pausing the keystone services when keystone is clustered using the hacluster charm, the hacluster unit on this node must first be paused as well. Not doing so may lead to an interruption of service.

review: Needs Fixing
208. By Alberto Donato

Fix actions description.

Revision history for this message
Alberto Donato (ack) wrote :

@Billy thanks for the review and suggestion, I've expanded the actions description.

209. By Alberto Donato

Lint.

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

charm_lint_check #8929 keystone-next for ack mp267931
    LINT OK: passed

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

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

charm_unit_test #8252 keystone-next for ack mp267931
    UNIT OK: passed

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

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

charm_amulet_test #6078 keystone-next for ack mp267931
    AMULET OK: passed

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

Revision history for this message
Billy Olsen (billy-olsen) wrote :

On further inspection, its not clear why the charmhelpers were moved out of the hooks directory to the root directory of the charm but the amulet tests continues to have its own charmhelpers installation. I'm not holding this merge proposal up based on this comment, but I also noticed the same in the swift storage charm (and likely glance, though I haven't looked there yet).

Thanks for the contribution Alberto!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.coveragerc'
2--- .coveragerc 2014-03-31 10:18:06 +0000
3+++ .coveragerc 2015-08-28 06:58:18 +0000
4@@ -4,3 +4,4 @@
5 if __name__ == .__main__.:
6 include=
7 hooks/keystone_*
8+ actions/actions.py
9
10=== modified file 'actions.yaml'
11--- actions.yaml 2015-03-20 01:15:23 +0000
12+++ actions.yaml 2015-08-28 06:58:18 +0000
13@@ -1,2 +1,13 @@
14 git-reinstall:
15 description: Reinstall keystone from the openstack-origin-git repositories.
16+pause:
17+ description: |
18+ Pause keystone services.
19+ If the keystone deployment is clustered using the hacluster charm, the
20+ corresponding hacluster unit on the node must first be paused as well.
21+ Not doing so may lead to an interruption of service.
22+resume:
23+ description: |
24+ Resume keystone services.
25+ If the keystone deployment is clustered using the hacluster charm, the
26+ corresponding hacluster unit on the node must be resumed as well.
27
28=== added file 'actions/__init__.py'
29=== added file 'actions/actions.py'
30--- actions/actions.py 1970-01-01 00:00:00 +0000
31+++ actions/actions.py 2015-08-28 06:58:18 +0000
32@@ -0,0 +1,56 @@
33+#!/usr/bin/python
34+
35+import sys
36+import os
37+
38+from charmhelpers.core.host import service_pause, service_resume
39+from charmhelpers.core.hookenv import action_fail, status_set
40+
41+from hooks.keystone_utils import services
42+
43+
44+def pause(args):
45+ """Pause all the Keystone services.
46+
47+ @raises Exception if any services fail to stop
48+ """
49+ for service in services():
50+ stopped = service_pause(service)
51+ if not stopped:
52+ raise Exception("{} didn't stop cleanly.".format(service))
53+ status_set(
54+ "maintenance", "Paused. Use 'resume' action to resume normal service.")
55+
56+
57+def resume(args):
58+ """Resume all the Keystone services.
59+
60+ @raises Exception if any services fail to start
61+ """
62+ for service in services():
63+ started = service_resume(service)
64+ if not started:
65+ raise Exception("{} didn't start cleanly.".format(service))
66+ status_set("active", "")
67+
68+
69+# A dictionary of all the defined actions to callables (which take
70+# parsed arguments).
71+ACTIONS = {"pause": pause, "resume": resume}
72+
73+
74+def main(args):
75+ action_name = os.path.basename(args[0])
76+ try:
77+ action = ACTIONS[action_name]
78+ except KeyError:
79+ return "Action %s undefined" % action_name
80+ else:
81+ try:
82+ action(args)
83+ except Exception as e:
84+ action_fail(str(e))
85+
86+
87+if __name__ == "__main__":
88+ sys.exit(main(sys.argv))
89
90=== added symlink 'actions/charmhelpers'
91=== target is u'../charmhelpers'
92=== modified file 'actions/git_reinstall.py'
93--- actions/git_reinstall.py 2015-04-15 16:33:30 +0000
94+++ actions/git_reinstall.py 2015-08-28 06:58:18 +0000
95@@ -1,9 +1,7 @@
96 #!/usr/bin/python
97-import sys
98+
99 import traceback
100
101-sys.path.append('hooks/')
102-
103 from charmhelpers.contrib.openstack.utils import (
104 git_install_requested,
105 )
106@@ -14,11 +12,11 @@
107 config,
108 )
109
110-from keystone_utils import (
111+from hooks.keystone_utils import (
112 git_install,
113 )
114
115-from keystone_hooks import (
116+from hooks.keystone_hooks import (
117 config_changed,
118 )
119
120
121=== added symlink 'actions/hooks'
122=== target is u'../hooks'
123=== added symlink 'actions/pause'
124=== target is u'actions.py'
125=== added symlink 'actions/resume'
126=== target is u'actions.py'
127=== modified file 'charm-helpers-hooks.yaml'
128--- charm-helpers-hooks.yaml 2015-07-31 13:10:52 +0000
129+++ charm-helpers-hooks.yaml 2015-08-28 06:58:18 +0000
130@@ -1,5 +1,5 @@
131 branch: lp:charm-helpers
132-destination: hooks/charmhelpers
133+destination: charmhelpers
134 include:
135 - core
136 - cli
137
138=== renamed directory 'hooks/charmhelpers' => 'charmhelpers'
139=== added file 'hooks/__init__.py'
140=== added symlink 'hooks/charmhelpers'
141=== target is u'../charmhelpers'
142=== modified file 'hooks/keystone_utils.py'
143--- hooks/keystone_utils.py 2015-06-10 13:59:24 +0000
144+++ hooks/keystone_utils.py 2015-08-28 06:58:18 +0000
145@@ -14,6 +14,7 @@
146 import urlparse
147 import uuid
148
149+from itertools import chain
150 from base64 import b64encode
151 from collections import OrderedDict
152 from copy import deepcopy
153@@ -150,11 +151,6 @@
154 'keystone',
155 ]
156
157-API_PORTS = {
158- 'keystone-admin': config('admin-port'),
159- 'keystone-public': config('service-port')
160-}
161-
162 KEYSTONE_CONF = "/etc/keystone/keystone.conf"
163 KEYSTONE_LOGGER_CONF = "/etc/keystone/logging.conf"
164 KEYSTONE_CONF_DIR = os.path.dirname(KEYSTONE_CONF)
165@@ -178,7 +174,6 @@
166 CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
167 SSL_SYNC_SEMAPHORE = threading.Semaphore()
168 SSL_DIRS = [SSL_DIR, APACHE_SSL_DIR, CA_CERT_PATH]
169-
170 BASE_RESOURCE_MAP = OrderedDict([
171 (KEYSTONE_CONF, {
172 'services': BASE_SERVICES,
173@@ -321,11 +316,8 @@
174
175
176 def services():
177- """Returns a list of services associate with this charm"""
178- _services = []
179- for v in restart_map().values():
180- _services = _services + v
181- return list(set(_services))
182+ """Returns a list of (unique) services associated with this charm"""
183+ return list(set(chain(*restart_map().values())))
184
185
186 def determine_ports():
187@@ -335,23 +327,20 @@
188
189
190 def api_port(service):
191- return API_PORTS[service]
192+ return {
193+ 'keystone-admin': config('admin-port'),
194+ 'keystone-public': config('service-port')
195+ }[service]
196
197
198 def determine_packages():
199 # currently all packages match service names
200- packages = [] + BASE_PACKAGES
201- for k, v in resource_map().iteritems():
202- packages.extend(v['services'])
203-
204+ packages = set(services()).union(BASE_PACKAGES)
205 if git_install_requested():
206- packages.extend(BASE_GIT_PACKAGES)
207- # don't include packages that will be installed from git
208- packages = list(set(packages))
209- for p in GIT_PACKAGE_BLACKLIST:
210- packages.remove(p)
211+ packages |= set(BASE_GIT_PACKAGES)
212+ packages -= set(GIT_PACKAGE_BLACKLIST)
213
214- return list(set(packages))
215+ return sorted(packages)
216
217
218 def save_script_rc():
219
220=== modified file 'tests/basic_deployment.py'
221--- tests/basic_deployment.py 2015-07-13 16:07:29 +0000
222+++ tests/basic_deployment.py 2015-08-28 06:58:18 +0000
223@@ -38,6 +38,21 @@
224 self._deploy()
225 self._initialize_tests()
226
227+ def _assert_services(self, should_run):
228+ u.get_unit_process_ids(
229+ {self.keystone_sentry: ("keystone-all", "apache2", "haproxy")},
230+ expect_success=should_run)
231+
232+ def get_service_overrides(self, unit):
233+ """
234+ Return a dict mapping service names to a boolean indicating whether
235+ an override file exists for that service.
236+ """
237+ init_contents = unit.directory_contents("/etc/init/")
238+ return {
239+ service: "{}.override".format(service) in init_contents["files"]
240+ for service in ("keystone", "apache2", "haproxy")}
241+
242 def _add_services(self):
243 """Add services
244
245@@ -462,3 +477,21 @@
246 sleep_time = 0
247
248 self.d.configure(juju_service, set_default)
249+
250+ def test_901_pause_resume(self):
251+ """Test pause and resume actions."""
252+ unit_name = "keystone/0"
253+ unit = self.d.sentry.unit[unit_name]
254+ self._assert_services(should_run=True)
255+ action_id = u.run_action(unit, "pause")
256+ assert u.wait_on_action(action_id), "Pause action failed."
257+
258+ self._assert_services(should_run=False)
259+ assert all(self.get_service_overrides(unit).itervalues()), \
260+ "Not all override files were created."
261+
262+ action_id = u.run_action(unit, "resume")
263+ assert u.wait_on_action(action_id), "Resume action failed"
264+ assert not any(self.get_service_overrides(unit).itervalues()), \
265+ "Not all override files were removed."
266+ self._assert_services(should_run=True)
267
268=== added file 'unit_tests/test_actions.py'
269--- unit_tests/test_actions.py 1970-01-01 00:00:00 +0000
270+++ unit_tests/test_actions.py 2015-08-28 06:58:18 +0000
271@@ -0,0 +1,150 @@
272+import mock
273+
274+from test_utils import CharmTestCase
275+
276+import actions.actions
277+
278+
279+class PauseTestCase(CharmTestCase):
280+
281+ def setUp(self):
282+ super(PauseTestCase, self).setUp(
283+ actions.actions, ["service_pause", "status_set"])
284+
285+ def test_pauses_services(self):
286+ """Pause action pauses all Keystone services."""
287+ pause_calls = []
288+
289+ def fake_service_pause(svc):
290+ pause_calls.append(svc)
291+ return True
292+
293+ self.service_pause.side_effect = fake_service_pause
294+
295+ actions.actions.pause([])
296+ self.assertEqual(pause_calls, ['haproxy', 'keystone', 'apache2'])
297+
298+ def test_bails_out_early_on_error(self):
299+ """Pause action fails early if there are errors stopping a service."""
300+ pause_calls = []
301+
302+ def maybe_kill(svc):
303+ if svc == "keystone":
304+ return False
305+ else:
306+ pause_calls.append(svc)
307+ return True
308+
309+ self.service_pause.side_effect = maybe_kill
310+ self.assertRaisesRegexp(
311+ Exception, "keystone didn't stop cleanly.",
312+ actions.actions.pause, [])
313+ self.assertEqual(pause_calls, ['haproxy'])
314+
315+ def test_status_mode(self):
316+ """Pause action sets the status to maintenance."""
317+ status_calls = []
318+ self.status_set.side_effect = lambda state, msg: status_calls.append(
319+ state)
320+
321+ actions.actions.pause([])
322+ self.assertEqual(status_calls, ["maintenance"])
323+
324+ def test_status_message(self):
325+ """Pause action sets a status message reflecting that it's paused."""
326+ status_calls = []
327+ self.status_set.side_effect = lambda state, msg: status_calls.append(
328+ msg)
329+
330+ actions.actions.pause([])
331+ self.assertEqual(
332+ status_calls, ["Paused. "
333+ "Use 'resume' action to resume normal service."])
334+
335+
336+class ResumeTestCase(CharmTestCase):
337+
338+ def setUp(self):
339+ super(ResumeTestCase, self).setUp(
340+ actions.actions, ["service_resume", "status_set"])
341+
342+ def test_resumes_services(self):
343+ """Resume action resumes all Keystone services."""
344+ resume_calls = []
345+
346+ def fake_service_resume(svc):
347+ resume_calls.append(svc)
348+ return True
349+
350+ self.service_resume.side_effect = fake_service_resume
351+ actions.actions.resume([])
352+ self.assertEqual(resume_calls, ['haproxy', 'keystone', 'apache2'])
353+
354+ def test_bails_out_early_on_error(self):
355+ """Resume action fails early if there are errors starting a service."""
356+ resume_calls = []
357+
358+ def maybe_kill(svc):
359+ if svc == "keystone":
360+ return False
361+ else:
362+ resume_calls.append(svc)
363+ return True
364+
365+ self.service_resume.side_effect = maybe_kill
366+ self.assertRaisesRegexp(
367+ Exception, "keystone didn't start cleanly.",
368+ actions.actions.resume, [])
369+ self.assertEqual(resume_calls, ['haproxy'])
370+
371+ def test_status_mode(self):
372+ """Resume action sets the status to maintenance."""
373+ status_calls = []
374+ self.status_set.side_effect = lambda state, msg: status_calls.append(
375+ state)
376+
377+ actions.actions.resume([])
378+ self.assertEqual(status_calls, ["active"])
379+
380+ def test_status_message(self):
381+ """Resume action sets an empty status message."""
382+ status_calls = []
383+ self.status_set.side_effect = lambda state, msg: status_calls.append(
384+ msg)
385+
386+ actions.actions.resume([])
387+ self.assertEqual(status_calls, [""])
388+
389+
390+class MainTestCase(CharmTestCase):
391+
392+ def setUp(self):
393+ super(MainTestCase, self).setUp(actions.actions, ["action_fail"])
394+
395+ def test_invokes_action(self):
396+ dummy_calls = []
397+
398+ def dummy_action(args):
399+ dummy_calls.append(True)
400+
401+ with mock.patch.dict(actions.actions.ACTIONS, {"foo": dummy_action}):
402+ actions.actions.main(["foo"])
403+ self.assertEqual(dummy_calls, [True])
404+
405+ def test_unknown_action(self):
406+ """Unknown actions aren't a traceback."""
407+ exit_string = actions.actions.main(["foo"])
408+ self.assertEqual("Action foo undefined", exit_string)
409+
410+ def test_failing_action(self):
411+ """Actions which traceback trigger action_fail() calls."""
412+ dummy_calls = []
413+
414+ self.action_fail.side_effect = dummy_calls.append
415+
416+ def dummy_action(args):
417+ raise ValueError("uh oh")
418+
419+ with mock.patch.dict(actions.actions.ACTIONS, {"foo": dummy_action}):
420+ actions.actions.main(["foo"])
421+ self.assertEqual(dummy_calls, ["uh oh"])
422
423=== modified file 'unit_tests/test_actions_git_reinstall.py'
424--- unit_tests/test_actions_git_reinstall.py 2015-04-15 16:33:30 +0000
425+++ unit_tests/test_actions_git_reinstall.py 2015-08-28 06:58:18 +0000
426@@ -4,8 +4,8 @@
427 config.return_value = 'keystone'
428 import keystone_utils as utils # noqa
429
430-with patch('keystone_utils.register_configs') as register_configs:
431- import git_reinstall
432+ with patch('keystone_utils.register_configs') as register_configs:
433+ import git_reinstall
434
435 from test_utils import (
436 CharmTestCase
437@@ -36,8 +36,10 @@
438 @patch.object(git_reinstall, 'action_fail')
439 @patch.object(git_reinstall, 'git_install')
440 @patch.object(git_reinstall, 'config_changed')
441- def test_git_reinstall(self, config_changed, git_install, action_fail,
442- action_set):
443+ @patch('charmhelpers.contrib.openstack.utils.config')
444+ def test_git_reinstall(self, config, config_changed, git_install,
445+ action_fail, action_set):
446+ config.return_value = openstack_origin_git
447 self.test_config.set('openstack-origin-git', openstack_origin_git)
448
449 git_reinstall.git_reinstall()
450
451=== modified file 'unit_tests/test_keystone_contexts.py'
452--- unit_tests/test_keystone_contexts.py 2015-03-18 13:48:33 +0000
453+++ unit_tests/test_keystone_contexts.py 2015-08-28 06:58:18 +0000
454@@ -1,3 +1,5 @@
455+import os
456+
457 import keystone_context as context
458 from mock import patch, MagicMock
459
460@@ -45,6 +47,7 @@
461 self.assertTrue(mock_ensure_permissions.called)
462 self.assertFalse(mock_get_ca.called)
463
464+ @patch('keystone_utils.determine_ports')
465 @patch('keystone_utils.is_ssl_cert_master')
466 @patch('keystone_utils.is_ssl_enabled')
467 @patch('charmhelpers.contrib.openstack.context.config')
468@@ -60,7 +63,8 @@
469 mock_is_clustered,
470 mock_config,
471 mock_is_ssl_enabled,
472- mock_is_ssl_cert_master):
473+ mock_is_ssl_cert_master,
474+ mock_determine_ports):
475 mock_is_ssl_enabled.return_value = True
476 mock_is_ssl_cert_master.return_value = True
477 mock_https.return_value = True
478@@ -69,6 +73,7 @@
479 mock_determine_apache_port.return_value = '34'
480 mock_is_clustered.return_value = False
481 mock_config.return_value = None
482+ mock_determine_ports.return_value = ['12']
483
484 ctxt = context.ApacheSSLContext()
485 ctxt.enable_modules = MagicMock()
486@@ -83,6 +88,7 @@
487 self.assertTrue(mock_https.called)
488 mock_unit_get.assert_called_with('private-address')
489
490+ @patch('keystone_utils.api_port')
491 @patch('charmhelpers.contrib.openstack.context.get_netmask_for_address')
492 @patch('charmhelpers.contrib.openstack.context.get_address_in_network')
493 @patch('charmhelpers.contrib.openstack.context.config')
494@@ -95,7 +101,10 @@
495 def test_haproxy_context_service_enabled(
496 self, mock_open, mock_log, mock_relation_get, mock_related_units,
497 mock_unit_get, mock_relation_ids, mock_config,
498- mock_get_address_in_network, mock_get_netmask_for_address):
499+ mock_get_address_in_network, mock_get_netmask_for_address,
500+ mock_api_port):
501+ os.environ['JUJU_UNIT_NAME'] = 'keystone'
502+
503 mock_relation_ids.return_value = ['identity-service:0', ]
504 mock_unit_get.return_value = '1.2.3.4'
505 mock_relation_get.return_value = '10.0.0.0'
506@@ -104,19 +113,20 @@
507 mock_get_address_in_network.return_value = None
508 mock_get_netmask_for_address.return_value = '255.255.255.0'
509 self.determine_apache_port.return_value = '34'
510+ mock_api_port.return_value = '12'
511
512 ctxt = context.HAProxyContext()
513
514 self.maxDiff = None
515 self.assertEquals(
516 ctxt(),
517- {'listen_ports': {'admin_port': 'keystone',
518- 'public_port': 'keystone'},
519+ {'listen_ports': {'admin_port': '12',
520+ 'public_port': '12'},
521 'local_host': '127.0.0.1',
522 'haproxy_host': '0.0.0.0',
523 'stat_port': ':8888',
524- 'service_ports': {'admin-port': ['keystone', '34'],
525- 'public-port': ['keystone', '34']},
526+ 'service_ports': {'admin-port': ['12', '34'],
527+ 'public-port': ['12', '34']},
528 'default_backend': '1.2.3.4',
529 'frontends': {'1.2.3.4': {
530 'network': '1.2.3.4/255.255.255.0',
531
532=== modified file 'unit_tests/test_keystone_hooks.py'
533--- unit_tests/test_keystone_hooks.py 2015-07-21 13:44:57 +0000
534+++ unit_tests/test_keystone_hooks.py 2015-08-28 06:58:18 +0000
535@@ -92,9 +92,9 @@
536 self.configure_installation_source.assert_called_with(repo)
537 self.assertTrue(self.apt_update.called)
538 self.apt_install.assert_called_with(
539- ['haproxy', 'unison', 'python-keystoneclient',
540- 'uuid', 'python-mysqldb', 'openssl', 'apache2',
541- 'pwgen', 'python-six', 'keystone', 'python-psycopg2'], fatal=True)
542+ ['apache2', 'haproxy', 'keystone', 'openssl', 'pwgen',
543+ 'python-keystoneclient', 'python-mysqldb', 'python-psycopg2',
544+ 'python-six', 'unison', 'uuid'], fatal=True)
545 self.git_install.assert_called_with(None)
546
547 @patch.object(utils, 'git_install_requested')
548@@ -120,12 +120,12 @@
549 self.configure_installation_source.assert_called_with(repo)
550 self.assertTrue(self.apt_update.called)
551 self.apt_install.assert_called_with(
552- ['haproxy', 'unison', 'python-setuptools', 'python-keystoneclient',
553- 'uuid', 'python-mysqldb', 'libmysqlclient-dev', 'libssl-dev',
554- 'openssl', 'libffi-dev', 'apache2', 'python-pip', 'pwgen',
555- 'python-six', 'libxslt1-dev', 'python-psycopg2', 'libyaml-dev',
556- 'zlib1g-dev', 'python-dev', 'libxml2-dev'],
557- fatal=True)
558+ ['apache2', 'haproxy', 'libffi-dev', 'libmysqlclient-dev',
559+ 'libssl-dev', 'libxml2-dev', 'libxslt1-dev', 'libyaml-dev',
560+ 'openssl', 'pwgen', 'python-dev', 'python-keystoneclient',
561+ 'python-mysqldb', 'python-pip', 'python-psycopg2',
562+ 'python-setuptools', 'python-six', 'unison', 'uuid',
563+ 'zlib1g-dev'], fatal=True)
564 self.git_install.assert_called_with(projects_yaml)
565
566 mod_ch_openstack_utils = 'charmhelpers.contrib.openstack.utils'
567
568=== modified file 'unit_tests/test_keystone_utils.py'
569--- unit_tests/test_keystone_utils.py 2015-06-10 20:44:02 +0000
570+++ unit_tests/test_keystone_utils.py 2015-08-28 06:58:18 +0000
571@@ -281,11 +281,13 @@
572 self.relation_set.assert_called_with(relation_id=relation_id,
573 **filtered)
574
575+ @patch('charmhelpers.contrib.openstack.ip.config')
576 @patch.object(utils, 'ensure_valid_service')
577 @patch.object(utils, 'add_endpoint')
578 @patch.object(manager, 'KeystoneManager')
579 def test_add_service_to_keystone_nosubset(
580- self, KeystoneManager, add_endpoint, ensure_valid_service):
581+ self, KeystoneManager, add_endpoint, ensure_valid_service,
582+ ip_config):
583 relation_id = 'identity-service:0'
584 remote_unit = 'unit/0'
585

Subscribers

People subscribed via source and target branches