Merge lp:~bloodearnest/charms/trusty/apache2/fix-mpm-type into lp:charms/trusty/apache2

Proposed by Simon Davy
Status: Merged
Merged at revision: 65
Proposed branch: lp:~bloodearnest/charms/trusty/apache2/fix-mpm-type
Merge into: lp:charms/trusty/apache2
Diff against target: 162 lines (+98/-10)
5 files modified
Makefile (+2/-1)
hooks/hooks.py (+41/-6)
hooks/tests/test_config_changed.py (+3/-2)
tests/10-bundles-test.py (+1/-1)
tests/20-mpm-test.py (+51/-0)
To merge this branch: bzr merge lp:~bloodearnest/charms/trusty/apache2/fix-mpm-type
Reviewer Review Type Date Requested Status
Tom Haddon Approve
Review via email: mp+252916@code.launchpad.net

Commit message

Fixes configuration of mpm_type is broken on trusty.

Description of the change

Fixes configuration of mpm_type is broken on trusty, which is broken completely.

Apache 2.4 on trusty defaults to mpm_event, and all mpm modules are compiled in, and require explicit a2en/dismodding. The charm was written for precise, and just purged/installed apache2-mpm-{type} package to a) install the module and b) switch the worker type.

In trusty, these packages are just transitional packages that install nothing and do not switch modules.

This change refactors the mpm management to work on trusty, and adds amulet test coverage for *all three* worker types (previously, mpm_event was *not* supported).

To post a comment you must log in.
68. By Simon Davy

make trusty only

Revision history for this message
Tom Haddon (mthaddon) wrote :

Looks good. I've confirmed the issue with the current charm, and that upgrading to this version fixes it so that setting the mpm_type config variable works as expected.

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-03-09 16:32:43 +0000
3+++ Makefile 2015-03-13 16:05:28 +0000
4@@ -28,7 +28,8 @@
5
6 lint:
7 @echo Checking for Python syntax...
8- @flake8 $(HOOKS_DIR) --ignore=E123 --exclude=$(HOOKS_DIR)/charmhelpers && echo OK
9+ @flake8 $(HOOKS_DIR) --ignore=E123 --exclude=$(HOOKS_DIR)/charmhelpers && echo hooks OK
10+ @flake8 tests --ignore=E123 && echo tests OK
11
12 sourcedeps: $(PWD)/config-manager.txt
13 @echo Updating source dependencies...
14
15=== modified file 'hooks/hooks.py'
16--- hooks/hooks.py 2015-03-10 19:10:28 +0000
17+++ hooks/hooks.py 2015-03-13 16:05:28 +0000
18@@ -542,6 +542,45 @@
19 return True
20
21
22+MPM_TYPES = ['mpm_worker', 'mpm_prefork', 'mpm_event']
23+
24+
25+def enable_mpm(config):
26+ """Enables a particular mpm module.
27+
28+ Different from simply enabling a module, as one and only one mpm module
29+ *must* be enabled.
30+ """
31+ # only do anything if value has changed, to avoid a needless restart
32+ if not config.changed('mpm_type'):
33+ return
34+
35+ mpm_type = config.get('mpm_type', '')
36+ name = 'mpm_' + mpm_type
37+ if name not in MPM_TYPES:
38+ log('bad mpm_type: %s. Falling back to mpm_worker' % mpm_type)
39+ name = 'mpm_worker'
40+
41+ # disable all other mpm modules
42+ for mpm in MPM_TYPES:
43+ if mpm != name:
44+ return_value = subprocess.call(['/usr/sbin/a2dismod', mpm])
45+ if return_value != 0:
46+ return False
47+
48+ return_value = subprocess.call(['/usr/sbin/a2enmod', name])
49+ if return_value != 0:
50+ return False
51+
52+ if service_apache2("check"):
53+ log("Switching mpm module to {}".format(name))
54+ service_apache2("restart") # must be a restart to switch mpm
55+ return True
56+ else:
57+ log("Failed to switch mpm module to {}".format(name))
58+ return False
59+
60+
61 def config_changed():
62 relationship_data = {}
63 config_data = config_get()
64@@ -567,12 +606,8 @@
65 for module in module_list:
66 disable_module(module)
67
68- if config_data['mpm_type'] == 'worker':
69- apt_get_install('apache2-mpm-worker')
70- apt_get_purge('apache2-mpm-prefork')
71- elif config_data['mpm_type'] == 'prefork':
72- apt_get_install('apache2-mpm-prefork')
73- apt_get_purge('apache2-mpm-worker')
74+ enable_mpm(config_data)
75+ # XXX we only configure the worker mpm?
76 create_mpm_workerfile()
77 create_security()
78
79
80=== modified file 'hooks/tests/test_config_changed.py'
81--- hooks/tests/test_config_changed.py 2015-03-10 19:10:28 +0000
82+++ hooks/tests/test_config_changed.py 2015-03-13 16:05:28 +0000
83@@ -36,9 +36,10 @@
84 @patch('hooks.get_reverseproxy_data')
85 @patch('hooks.service_apache2')
86 @patch('hooks.relation_set')
87+ @patch('hooks.enable_mpm')
88 def test_config_changed_ensure_empty_site_dir(
89- self, mock_relation_set, mock_service_apache2,
90- mock_reverseproxy, mock_config_get,
91+ self, mock_enable_mpm, mock_relation_set,
92+ mock_service_apache2, mock_reverseproxy, mock_config_get,
93 mock_relations_of_type, mock_relation_ids, mock_log,
94 mock_create_mpm_workerfile, mock_create_security, mock_run,
95 mock_update_nrpe_checks, mock_ship_logrotate_conf,
96
97=== modified file 'tests/10-bundles-test.py'
98--- tests/10-bundles-test.py 2014-10-29 00:10:14 +0000
99+++ tests/10-bundles-test.py 2015-03-13 16:05:28 +0000
100@@ -30,4 +30,4 @@
101
102
103 if __name__ == '__main__':
104- unittest.main()
105\ No newline at end of file
106+ unittest.main()
107
108=== added file 'tests/20-mpm-test.py'
109--- tests/20-mpm-test.py 1970-01-01 00:00:00 +0000
110+++ tests/20-mpm-test.py 2015-03-13 16:05:28 +0000
111@@ -0,0 +1,51 @@
112+#!/usr/bin/env python3
113+import os
114+import time
115+import unittest
116+import amulet
117+
118+
119+class BundleTest(unittest.TestCase):
120+ """ Create a class for testing the charm in the unit test framework. """
121+ @classmethod
122+ def setUpClass(cls):
123+ """ Set up an amulet deployment using the bundle. """
124+ d = amulet.Deployment(series='trusty')
125+ d.add('apache2', os.path.join(os.path.dirname(__file__), os.pardir))
126+ d.setup(180)
127+ cls.d = d
128+ cls.unit = d.sentry.unit['apache2/0']
129+ output, code = cls.unit.run('curl localhost')
130+
131+ def assert_mpm(self, mpm):
132+ cmd = (". /etc/apache2/envvars && apache2 -V 2>/dev/null "
133+ "| grep MPM | awk -F: '{print $2}' | xargs")
134+ self.d.configure('apache2', {'mpm_type': mpm})
135+ self.d.sentry.wait()
136+ # the above doesn't seem to work
137+ time.sleep(10)
138+ # enable default web site so we can check for a valid config
139+ output, code = self.unit.run(
140+ 'a2ensite 000-default.conf && service apache2 reload')
141+ time.sleep(10)
142+ # enable default web site so we can check for a valid config
143+ output, code = self.unit.run(cmd)
144+ self.assertEqual(code, 0)
145+ self.assertIn(mpm, output)
146+ output, code = self.unit.run('curl localhost')
147+ if code != 0:
148+ raise Exception(output)
149+ self.assertEqual(code, 0)
150+
151+ def test_mpm_worker(self):
152+ self.assert_mpm('worker')
153+
154+ def test_mpm_prefork(self):
155+ self.assert_mpm('prefork')
156+
157+ def test_mpm_event(self):
158+ self.assert_mpm('event')
159+
160+
161+if __name__ == '__main__':
162+ unittest.main()

Subscribers

People subscribed via source and target branches

to all changes: