Merge lp:~jr.allen/unifield-web/us-2080 into lp:unifield-web
- us-2080
- Merge into trunk
Proposed by
Jeff Allen
Status: | Merged |
---|---|
Merged at revision: | 4835 |
Proposed branch: | lp:~jr.allen/unifield-web/us-2080 |
Merge into: | lp:unifield-web |
Diff against target: |
313 lines (+134/-34) 7 files modified
doc/openerp-web-oc.cfg (+6/-0) openerp-web.py (+1/-1) openobject/commands.py (+92/-2) openobject/i18n/_gettext.py (+10/-10) setup.nsi (+1/-0) setup.py (+16/-15) win32/OpenERPWebService.py (+8/-6) |
To merge this branch: | bzr merge lp:~jr.allen/unifield-web/us-2080 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
jftempo | Pending | ||
Review via email: mp+317322@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 4840. By Jeff Allen
-
merge
- 4841. By Jeff Allen
-
pyflakes fixes. To avoid a race, move the signal where it should have been all along. Update revprox to handle LetsEncrypt automatically.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/openerp-web-oc.cfg' |
2 | --- doc/openerp-web-oc.cfg 2016-06-08 10:23:06 +0000 |
3 | +++ doc/openerp-web-oc.cfg 2017-02-16 14:13:31 +0000 |
4 | @@ -8,3 +8,9 @@ |
5 | #server.environment = "red" |
6 | #server.environment = "blue" |
7 | |
8 | +# HTTPS server |
9 | +# To enable the HTTPS wrapper server (revprox.exe) set this to the |
10 | +# fully qualified domain name of the server, and arrange for this to |
11 | +# resolve in local DNS to the Unifield server machine's IP address. |
12 | + |
13 | +# server.https_name = "THIS-INSTANCE.prod.unifield.org" |
14 | |
15 | === modified file 'openerp-web.py' |
16 | --- openerp-web.py 2010-09-15 17:46:36 +0000 |
17 | +++ openerp-web.py 2017-02-16 14:13:31 +0000 |
18 | @@ -1,5 +1,5 @@ |
19 | #!/usr/bin/env python |
20 | -# -*- coding: UTF-8 -*- |
21 | +# -*- coding: utf-8 -*- |
22 | """Start script for the openerp-web project. |
23 | |
24 | This script is only needed during development for running from the project |
25 | |
26 | === modified file 'openobject/commands.py' |
27 | --- openobject/commands.py 2016-01-18 08:45:32 +0000 |
28 | +++ openobject/commands.py 2017-02-16 14:13:31 +0000 |
29 | @@ -1,9 +1,10 @@ |
30 | import os |
31 | import sys |
32 | +import time |
33 | +import subprocess |
34 | +import threading |
35 | from optparse import OptionParser |
36 | |
37 | -import babel.localedata |
38 | - |
39 | import cherrypy |
40 | try: |
41 | from cherrypy.lib.reprconf import as_dict |
42 | @@ -81,6 +82,15 @@ |
43 | if options.static: |
44 | openobject.enable_static_paths() |
45 | |
46 | + # Try to start revprox now so that we know what default to set for |
47 | + # port number (revprox ok? port = 18061) |
48 | + if options.port is None: |
49 | + options.port = cherrypy.config.get('server.socket_port', 8061) |
50 | + if revprox(options.port): |
51 | + options.port = 18061 |
52 | + options.address = '127.0.0.1' |
53 | + cherrypy.config['tools.proxy.on'] = True |
54 | + |
55 | if options.address: |
56 | cherrypy.config['server.socket_host'] = options.address |
57 | if options.port: |
58 | @@ -89,6 +99,7 @@ |
59 | except: |
60 | pass |
61 | port = cherrypy.config.get('server.socket_port') |
62 | + |
63 | if not isinstance(port, (int, long)) or port < 1 or port > 65535: |
64 | cherrypy.log('Wrong configuration socket_port: %s' % (port,), "ERROR") |
65 | raise ConfigurationError(_("Wrong configuration socket_port: %s") % |
66 | @@ -122,3 +133,82 @@ |
67 | |
68 | def stop(): |
69 | cherrypy.engine.exit() |
70 | + |
71 | +# Try to start the reverse proxy. If anything goes wrong, return |
72 | +# False. Launch a thread which monitors it's output, copying it to |
73 | +# cherrypy.log, and kills the server if revproxy dies. |
74 | +def revprox(redir_port): |
75 | + ctx = "REVPROX" |
76 | + |
77 | + https_name = cherrypy.config.get('server.https_name') |
78 | + if not https_name: |
79 | + cherrypy.log("server.https_name is not set, not running the reverse proxy", ctx) |
80 | + return False |
81 | + |
82 | + rbin = 'revprox' |
83 | + if sys.platform == 'win32': |
84 | + rbin += '.exe' |
85 | + rbin = os.path.abspath(openobject.paths.root('revprox', rbin)) |
86 | + if not os.path.exists(rbin): |
87 | + cherrypy.log("%s does not exist, not running the reverse proxy." % rbin, ctx) |
88 | + return False |
89 | + |
90 | + cmd = [ rbin, '-server', https_name, '-redir', str(redir_port) ] |
91 | + if cherrypy.config.get('server.use_letsencrypt', False): |
92 | + cmd.append('-usele') |
93 | + proc = subprocess.Popen(cmd, |
94 | + stderr=subprocess.STDOUT, # Merge stdout and stderr |
95 | + stdout=subprocess.PIPE) |
96 | + ok = False |
97 | + while not ok: |
98 | + line = proc.stdout.readline() |
99 | + if line != '': |
100 | + line = line.strip().split(" ", 2) |
101 | + cherrypy.log(line[-1], ctx) |
102 | + if line[-1] == 'Startup OK.': |
103 | + ok = True |
104 | + else: |
105 | + # Process exited |
106 | + break |
107 | + |
108 | + if not ok: |
109 | + cherrypy.log("reverse proxy exited without starting up", ctx) |
110 | + return False |
111 | + |
112 | + # It started correctly. So arrange that it's logs are copied |
113 | + # and that it is killed on shutdown. |
114 | + |
115 | + def logRead(proc): |
116 | + while True: |
117 | + line = proc.stdout.readline() |
118 | + if line != '': |
119 | + line = line.split(" ", 2) |
120 | + cherrypy.log(line[-1].strip(), ctx) |
121 | + else: |
122 | + break |
123 | + rc = proc.wait() |
124 | + cherrypy.log("reverse proxy exited (rc=%d)." % rc, ctx) |
125 | + if rc != 0: |
126 | + # revprox exited with an error, so tell cherrypy to exit too. |
127 | + # We will be restarted by the system (see setup.nsi: "sc failure...") |
128 | + cherrypy.engine.stop() |
129 | + # However, if it gets stuck on "Bus STOPPED", use exit to be sure |
130 | + time.sleep(5) |
131 | + os._exit(1) |
132 | + return |
133 | + |
134 | + thread = threading.Thread(target=logRead, args=[proc]) |
135 | + thread.start() |
136 | + |
137 | + # A callback to register on stop, for killing revprox. |
138 | + def _cb(p): |
139 | + cherrypy.log("stopping", ctx) |
140 | + try: |
141 | + p.terminate() |
142 | + except OSError: |
143 | + # Probably "no such process", which is ok. |
144 | + pass |
145 | + |
146 | + cherrypy.engine.subscribe('stop', lambda p=proc: _cb(p)) |
147 | + return True |
148 | + |
149 | |
150 | === modified file 'openobject/i18n/_gettext.py' |
151 | --- openobject/i18n/_gettext.py 2011-05-10 13:22:29 +0000 |
152 | +++ openobject/i18n/_gettext.py 2017-02-16 14:13:31 +0000 |
153 | @@ -62,9 +62,9 @@ |
154 | with open(popath, 'rb') as pofile: |
155 | with open(mopath, 'wb') as mofile: |
156 | babel.messages.mofile.write_mo( |
157 | - mofile, |
158 | - babel.messages.pofile.read_po( |
159 | - pofile, locale, domain)) |
160 | + mofile, |
161 | + babel.messages.pofile.read_po( |
162 | + pofile, locale, domain)) |
163 | except Exception: |
164 | # If the parsing of the PO file broke, don't leave an empty MO |
165 | # file hanging around |
166 | @@ -75,7 +75,7 @@ |
167 | raise |
168 | |
169 | return babel.support.Translations.load( |
170 | - locale_path, [locale], domain) |
171 | + locale_path, [locale], domain) |
172 | |
173 | def _load_translations(path, locales, domain): |
174 | if not locales: |
175 | @@ -94,11 +94,11 @@ |
176 | except SyntaxError: |
177 | # http://babel.edgewall.org/ticket/213 |
178 | cherrypy.log.error( |
179 | - 'Could not load translation domain "%s" for' |
180 | - ' locale "%s" in addon %s' % ( |
181 | - domain, locale, basename(path)), |
182 | - context="i18n", |
183 | - severity=logging.WARNING) |
184 | + 'Could not load translation domain "%s" for' |
185 | + ' locale "%s" in addon %s' % ( |
186 | + domain, locale, basename(path)), |
187 | + context="i18n", |
188 | + severity=logging.WARNING) |
189 | cherrypy.log.error(context='i18n', severity=logging.DEBUG, |
190 | traceback=True) |
191 | if isinstance(translation, babel.support.Translations): |
192 | @@ -184,7 +184,7 @@ |
193 | _lazy_gettext = lazify(_gettext) |
194 | |
195 | def gettext(key, locale=None, domain=None): |
196 | - if cherrypy.request.loading_addons: |
197 | + if hasattr(cherrypy.request, "loading_addons") and cherrypy.request.loading_addons: |
198 | return _lazy_gettext(key, locale, domain) |
199 | return _gettext(key, locale, domain) |
200 | |
201 | |
202 | === added directory 'revprox' |
203 | === added file 'revprox/revprox.exe' |
204 | Binary files revprox/revprox.exe 1970-01-01 00:00:00 +0000 and revprox/revprox.exe 2017-02-16 14:13:31 +0000 differ |
205 | === modified file 'setup.nsi' |
206 | --- setup.nsi 2016-10-27 09:40:52 +0000 |
207 | +++ setup.nsi 2017-02-16 14:13:31 +0000 |
208 | @@ -170,6 +170,7 @@ |
209 | Section -RestartService |
210 | nsExec::Exec '"$INSTDIR\service\OpenERPWebService.exe" -auto -install' |
211 | sleep 2 |
212 | + nsExec::Exec 'sc failure openerp-web-6.0 reset= 0 actions= restart/0/restart/0/restart/0' |
213 | nsExec::Exec "sc config openerp-web-6.0 depend= openerp-server-6.0" |
214 | nsExec::Exec "net start openerp-web-6.0" |
215 | sleep 2 |
216 | |
217 | === modified file 'setup.py' |
218 | --- setup.py 2013-02-04 09:09:45 +0000 |
219 | +++ setup.py 2017-02-16 14:13:31 +0000 |
220 | @@ -24,12 +24,12 @@ |
221 | 'win32serviceutil', |
222 | ]) |
223 | opts['options']['py2exe'].update( |
224 | - skip_archive=1, |
225 | - compressed=0, |
226 | - bundle_files=3, |
227 | - optimize=0, |
228 | - collected_libs_dir='libs', |
229 | - collected_libs_data_relocate='babel,pytz', |
230 | + skip_archive=1, |
231 | + compressed=0, |
232 | + bundle_files=3, |
233 | + optimize=0, |
234 | + collected_libs_dir='libs', |
235 | + collected_libs_data_relocate='babel,pytz', |
236 | ) |
237 | opts.setdefault('data_files', []).extend(fixup_data_pytz_zoneinfo()) |
238 | opts.update(cmdclass={'py2exe': custom_py2exe},) |
239 | @@ -99,16 +99,17 @@ |
240 | 'Programming Language :: Python', |
241 | 'Environment :: Web Environment', |
242 | 'Topic :: Office/Business :: Financial', |
243 | - ], |
244 | + ], |
245 | scripts=['scripts/openerp-web'], |
246 | data_files=(find_data_files('addons/openerp') |
247 | - + find_data_files('addons/view_calendar') |
248 | - + find_data_files('addons/view_diagram') |
249 | - + find_data_files('addons/view_graph') |
250 | - + find_data_files('addons/widget_ckeditor') |
251 | - + find_data_files('doc', patterns='') |
252 | - + find_data_files('openobject', patterns=r'.+\.(cfg|css|js|mako|gif|png|jpg|ico)') |
253 | - + opts.pop('data_files', []) |
254 | - ), |
255 | + + find_data_files('addons/view_calendar') |
256 | + + find_data_files('addons/view_diagram') |
257 | + + find_data_files('addons/view_graph') |
258 | + + find_data_files('addons/widget_ckeditor') |
259 | + + find_data_files('doc', patterns='') |
260 | + + find_data_files('openobject', patterns=r'.+\.(cfg|css|js|mako|gif|png|jpg|ico)') |
261 | + + find_data_files('revprox', patterns='') |
262 | + + opts.pop('data_files', []) |
263 | + ), |
264 | **opts |
265 | ) |
266 | |
267 | === modified file 'win32/OpenERPWebService.py' |
268 | --- win32/OpenERPWebService.py 2013-02-04 09:06:57 +0000 |
269 | +++ win32/OpenERPWebService.py 2017-02-16 14:13:31 +0000 |
270 | @@ -20,7 +20,6 @@ |
271 | ############################################################################## |
272 | |
273 | # Win32 python extensions modules |
274 | -import win32con |
275 | import win32serviceutil |
276 | import win32service |
277 | import win32event |
278 | @@ -54,11 +53,13 @@ |
279 | def SvcStop(self): |
280 | # Before we do anything, tell the SCM we are starting the stop process. |
281 | self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) |
282 | - # stop the running OpenERP Web: say it's a normal exit |
283 | - win32api.TerminateProcess(int(self.openerp_process._handle), 0) |
284 | - servicemanager.LogInfoMsg("OpenERP Web stopped correctly") |
285 | # And set my event. |
286 | win32event.SetEvent(self.hWaitStop) |
287 | + # stop the running OpenERP Web and any children (i.e. revprox.exe) |
288 | + pid = str(self.openerp_process.pid) |
289 | + subprocess.call(['taskkill', '/F', '/T', '/PID', pid]) |
290 | + self.openerp_process = None |
291 | + servicemanager.LogInfoMsg("OpenERP Web stopped correctly") |
292 | self.ReportServiceStatus(win32service.SERVICE_STOPPED) |
293 | |
294 | def StartOpenERP(self): |
295 | @@ -69,7 +70,7 @@ |
296 | service_dir = os.path.dirname(sys.argv[0]) |
297 | server_dir = os.path.split(service_dir)[0] |
298 | server_path = os.path.join(server_dir, 'openerp-web.exe') |
299 | - result = win32api.SetConsoleCtrlHandler(self.handle, 1) |
300 | + win32api.SetConsoleCtrlHandler(self.handle, 1) |
301 | |
302 | self.openerp_process = subprocess.Popen([server_path], cwd=server_dir, creationflags=win32process.CREATE_NO_WINDOW) |
303 | |
304 | @@ -92,7 +93,8 @@ |
305 | # verification if the server is really running, else quit with an error |
306 | self.openerp_process.wait() |
307 | if not self.stopping: |
308 | - sys.exit("OpenERP Web check: server not running, check the logfile for more info") |
309 | + servicemanager.LogInfoMsg("openerp-web child process died unexpectedly, exiting now") |
310 | + os._exit(1) |
311 | |
312 | if __name__=='__main__': |
313 | # Do with the service whatever option is passed in the command line |