Merge lp:~jr.allen/unifield-web/us-2080 into lp:unifield-web

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
Reviewer Review Type Date Requested Status
jftempo Pending
Review via email: mp+317322@code.launchpad.net
To post a comment you must log in.
lp:~jr.allen/unifield-web/us-2080 updated
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'
204Binary 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

Subscribers

People subscribed via source and target branches

to all changes: