Merge lp:~corey.bryant/charm-helpers/wsgi into lp:charm-helpers

Proposed by Corey Bryant
Status: Merged
Merged at revision: 670
Proposed branch: lp:~corey.bryant/charm-helpers/wsgi
Merge into: lp:charm-helpers
Diff against target: 294 lines (+232/-0)
5 files modified
charmhelpers/contrib/openstack/context.py (+40/-0)
charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf (+100/-0)
charmhelpers/contrib/openstack/utils.py (+29/-0)
tests/contrib/openstack/test_openstack_utils.py (+34/-0)
tests/contrib/openstack/test_os_contexts.py (+29/-0)
To merge this branch: bzr merge lp:~corey.bryant/charm-helpers/wsgi
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
charmers Pending
Review via email: mp+312947@code.launchpad.net

Commit message

Add WSGI context and template for OpenStack APIs

To post a comment you must log in.
lp:~corey.bryant/charm-helpers/wsgi updated
667. By Liam Young

[gnuoy, r=ajkavanagh] Fixes for amulet memcache service checks.
1) Use 'service' not 'status' for checking status of memcached on pre-systemd systems as its not an upstart script.
2) Trusty memcache uses ip6-localhost as its listen address because it does not understand ::1

668. By Stuart Bishop

[hloeung,r=stub] Add timeout to rsync and capture rsync error messages

669. By Liam Young

[gnuoy, r=ajkavanagh] Add option package var to Memcache context to allow contect to lookup Openstack release without using Openstack-origin which may not be present. enable_memcache also had to be extended to take a package option to support this

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

It looks good but needs unit tests for the new context and methods

review: Needs Fixing
lp:~corey.bryant/charm-helpers/wsgi updated
670. By Corey Bryant

Add WSGI context and template for OpenStack APIs

671. By Corey Bryant

Add unit test for WSGI context.

672. By Corey Bryant

Add unit test for git_determine_*()

Revision history for this message
Corey Bryant (corey.bryant) wrote :

Thanks for the review Liam. I've added unit tests.

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

LGTM, thanks

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmhelpers/contrib/openstack/context.py'
2--- charmhelpers/contrib/openstack/context.py 2016-12-14 15:10:32 +0000
3+++ charmhelpers/contrib/openstack/context.py 2016-12-14 18:51:33 +0000
4@@ -14,6 +14,7 @@
5
6 import glob
7 import json
8+import math
9 import os
10 import re
11 import time
12@@ -90,6 +91,8 @@
13 from charmhelpers.contrib.openstack.utils import (
14 config_flags_parser,
15 get_host_ip,
16+ git_determine_usr_bin,
17+ git_determine_python_path,
18 enable_memcache,
19 )
20 from charmhelpers.core.unitdata import kv
21@@ -1208,6 +1211,43 @@
22 return ctxt
23
24
25+class WSGIWorkerConfigContext(WorkerConfigContext):
26+
27+ def __init__(self, name=None, script=None, admin_script=None,
28+ public_script=None, process_weight=1.00,
29+ admin_process_weight=0.75, public_process_weight=0.25):
30+ self.service_name = name
31+ self.user = name
32+ self.group = name
33+ self.script = script
34+ self.admin_script = admin_script
35+ self.public_script = public_script
36+ self.process_weight = process_weight
37+ self.admin_process_weight = admin_process_weight
38+ self.public_process_weight = public_process_weight
39+
40+ def __call__(self):
41+ multiplier = config('worker-multiplier') or 1
42+ total_processes = self.num_cpus * multiplier
43+ ctxt = {
44+ "service_name": self.service_name,
45+ "user": self.user,
46+ "group": self.group,
47+ "script": self.script,
48+ "admin_script": self.admin_script,
49+ "public_script": self.public_script,
50+ "processes": int(math.ceil(self.process_weight * total_processes)),
51+ "admin_processes": int(math.ceil(self.admin_process_weight *
52+ total_processes)),
53+ "public_processes": int(math.ceil(self.public_process_weight *
54+ total_processes)),
55+ "threads": 1,
56+ "usr_bin": git_determine_usr_bin(),
57+ "python_path": git_determine_python_path(),
58+ }
59+ return ctxt
60+
61+
62 class ZeroMQContext(OSContextGenerator):
63 interfaces = ['zeromq-configuration']
64
65
66=== added file 'charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf'
67--- charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf 1970-01-01 00:00:00 +0000
68+++ charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf 2016-12-14 18:51:33 +0000
69@@ -0,0 +1,100 @@
70+# Configuration file maintained by Juju. Local changes may be overwritten.
71+
72+{% if port -%}
73+Listen {{ port }}
74+{% endif -%}
75+
76+{% if admin_port -%}
77+Listen {{ admin_port }}
78+{% endif -%}
79+
80+{% if public_port -%}
81+Listen {{ public_port }}
82+{% endif -%}
83+
84+{% if port -%}
85+<VirtualHost *:{{ port }}>
86+ WSGIDaemonProcess {{ service_name }} processes={{ processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
87+{% if python_path -%}
88+ python-path={{ python_path }} \
89+{% endif -%}
90+ display-name=%{GROUP}
91+ WSGIProcessGroup {{ service_name }}
92+ WSGIScriptAlias / {{ script }}
93+ WSGIApplicationGroup %{GLOBAL}
94+ WSGIPassAuthorization On
95+ <IfVersion >= 2.4>
96+ ErrorLogFormat "%{cu}t %M"
97+ </IfVersion>
98+ ErrorLog /var/log/apache2/{{ service_name }}_error.log
99+ CustomLog /var/log/apache2/{{ service_name }}_access.log combined
100+
101+ <Directory {{ usr_bin }}>
102+ <IfVersion >= 2.4>
103+ Require all granted
104+ </IfVersion>
105+ <IfVersion < 2.4>
106+ Order allow,deny
107+ Allow from all
108+ </IfVersion>
109+ </Directory>
110+</VirtualHost>
111+{% endif -%}
112+
113+{% if admin_port -%}
114+<VirtualHost *:{{ admin_port }}>
115+ WSGIDaemonProcess {{ service_name }}-admin processes={{ admin_processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
116+{% if python_path -%}
117+ python-path={{ python_path }} \
118+{% endif -%}
119+ display-name=%{GROUP}
120+ WSGIProcessGroup {{ service_name }}-admin
121+ WSGIScriptAlias / {{ admin_script }}
122+ WSGIApplicationGroup %{GLOBAL}
123+ WSGIPassAuthorization On
124+ <IfVersion >= 2.4>
125+ ErrorLogFormat "%{cu}t %M"
126+ </IfVersion>
127+ ErrorLog /var/log/apache2/{{ service_name }}_error.log
128+ CustomLog /var/log/apache2/{{ service_name }}_access.log combined
129+
130+ <Directory {{ usr_bin }}>
131+ <IfVersion >= 2.4>
132+ Require all granted
133+ </IfVersion>
134+ <IfVersion < 2.4>
135+ Order allow,deny
136+ Allow from all
137+ </IfVersion>
138+ </Directory>
139+</VirtualHost>
140+{% endif -%}
141+
142+{% if public_port -%}
143+<VirtualHost *:{{ public_port }}>
144+ WSGIDaemonProcess {{ service_name }}-public processes={{ public_processes }} threads={{ threads }} user={{ service_name }} group={{ service_name }} \
145+{% if python_path -%}
146+ python-path={{ python_path }} \
147+{% endif -%}
148+ display-name=%{GROUP}
149+ WSGIProcessGroup {{ service_name }}-public
150+ WSGIScriptAlias / {{ public_script }}
151+ WSGIApplicationGroup %{GLOBAL}
152+ WSGIPassAuthorization On
153+ <IfVersion >= 2.4>
154+ ErrorLogFormat "%{cu}t %M"
155+ </IfVersion>
156+ ErrorLog /var/log/apache2/{{ service_name }}_error.log
157+ CustomLog /var/log/apache2/{{ service_name }}_access.log combined
158+
159+ <Directory {{ usr_bin }}>
160+ <IfVersion >= 2.4>
161+ Require all granted
162+ </IfVersion>
163+ <IfVersion < 2.4>
164+ Order allow,deny
165+ Allow from all
166+ </IfVersion>
167+ </Directory>
168+</VirtualHost>
169+{% endif -%}
170
171=== modified file 'charmhelpers/contrib/openstack/utils.py'
172--- charmhelpers/contrib/openstack/utils.py 2016-12-14 15:46:41 +0000
173+++ charmhelpers/contrib/openstack/utils.py 2016-12-14 18:51:33 +0000
174@@ -1119,6 +1119,35 @@
175 shutil.copyfile(service_source, service_dest)
176
177
178+def git_determine_usr_bin():
179+ """Return the /usr/bin path for Apache2 config.
180+
181+ The /usr/bin path will be located in the virtualenv if the charm
182+ is configured to deploy from source.
183+ """
184+ if git_install_requested():
185+ projects_yaml = config('openstack-origin-git')
186+ projects_yaml = git_default_repos(projects_yaml)
187+ return os.path.join(git_pip_venv_dir(projects_yaml), 'bin')
188+ else:
189+ return '/usr/bin'
190+
191+
192+def git_determine_python_path():
193+ """Return the python-path for Apache2 config.
194+
195+ Returns 'None' unless the charm is configured to deploy from source,
196+ in which case the path of the virtualenv's site-packages is returned.
197+ """
198+ if git_install_requested():
199+ projects_yaml = config('openstack-origin-git')
200+ projects_yaml = git_default_repos(projects_yaml)
201+ return os.path.join(git_pip_venv_dir(projects_yaml),
202+ 'lib/python2.7/site-packages')
203+ else:
204+ return None
205+
206+
207 def os_workload_status(configs, required_interfaces, charm_func=None):
208 """
209 Decorator to set workload status based on complete contexts
210
211=== modified file 'tests/contrib/openstack/test_openstack_utils.py'
212--- tests/contrib/openstack/test_openstack_utils.py 2016-09-16 09:50:01 +0000
213+++ tests/contrib/openstack/test_openstack_utils.py 2016-12-14 18:51:33 +0000
214@@ -933,6 +933,40 @@
215 openstack.git_src_dir(openstack_origin_git, 'keystone')
216 join.assert_called_with('/mnt/openstack-git', 'keystone')
217
218+ @patch.object(openstack, 'config')
219+ def test_git_determine_usr_bin(self, config):
220+ config.return_value = None
221+ result = openstack.git_determine_usr_bin()
222+ self.assertEquals(result, '/usr/bin')
223+
224+ @patch('os.path.join')
225+ @patch.object(openstack, 'git_default_repos')
226+ @patch.object(openstack, 'config')
227+ def test_git_determine_usr_bin_git(self, config, git_default, join):
228+ venv_bin = '/mnt/openstack/.venv/bin'
229+ join.return_value = venv_bin
230+ config.return_value = openstack_origin_git
231+ git_default.return_value = openstack_origin_git
232+ result = openstack.git_determine_usr_bin()
233+ self.assertEquals(result, venv_bin)
234+
235+ @patch.object(openstack, 'config')
236+ def test_git_determine_python_path(self, config):
237+ config.return_value = None
238+ result = openstack.git_determine_python_path()
239+ self.assertEquals(result, None)
240+
241+ @patch('os.path.join')
242+ @patch.object(openstack, 'git_default_repos')
243+ @patch.object(openstack, 'config')
244+ def test_git_determine_python_path_git(self, config, git_default, join):
245+ venv_site = '/mnt/openstack/.venv/lib/python2.7/site-packages'
246+ join.return_value = venv_site
247+ config.return_value = openstack_origin_git
248+ git_default.return_value = openstack_origin_git
249+ result = openstack.git_determine_python_path()
250+ self.assertEquals(result, venv_site)
251+
252 def test_incomplete_relation_data(self):
253 configs = MagicMock()
254 configs.complete_contexts.return_value = ['pgsql-db', 'amqp']
255
256=== modified file 'tests/contrib/openstack/test_os_contexts.py'
257--- tests/contrib/openstack/test_os_contexts.py 2016-12-09 16:48:53 +0000
258+++ tests/contrib/openstack/test_os_contexts.py 2016-12-14 18:51:33 +0000
259@@ -2371,6 +2371,35 @@
260 }
261 self.assertEquals(result, expected)
262
263+ @patch.object(context, 'psutil')
264+ @patch.object(context, 'git_determine_python_path')
265+ @patch.object(context, 'git_determine_usr_bin')
266+ def test_wsgi_worker_config_context(self, usr_bin, python_path, psutil):
267+ self.config.return_value = 2 # worker-multiplier=2
268+ usr_bin_path = '/usr/bin'
269+ usr_bin.return_value = usr_bin_path
270+ python_path.return_value = None
271+ psutil.cpu_count.return_value = 4
272+ service_name = 'service-name'
273+ script = '/usr/bin/script'
274+ ctxt = context.WSGIWorkerConfigContext(name=service_name,
275+ script=script)
276+ expect = {
277+ "service_name": service_name,
278+ "user": service_name,
279+ "group": service_name,
280+ "script": script,
281+ "admin_script": None,
282+ "public_script": None,
283+ "processes": 8,
284+ "admin_processes": 6,
285+ "public_processes": 2,
286+ "threads": 1,
287+ "usr_bin": usr_bin_path,
288+ "python_path": None,
289+ }
290+ self.assertEqual(expect, ctxt())
291+
292 def test_zeromq_context_unrelated(self):
293 self.is_relation_made.return_value = False
294 self.assertEquals(context.ZeroMQContext()(), {})

Subscribers

People subscribed via source and target branches