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