Package omero :: Package plugins :: Module web
[hide private]
[frames] | no frames]

Source Code for Module omero.plugins.web

  1  #!/usr/bin/env python 
  2  """ 
  3     Plugin for our configuring the OMERO.web installation 
  4   
  5     Copyright 2009 University of Dundee. All rights reserved. 
  6     Use is subject to license terms supplied in LICENSE.txt 
  7   
  8  """ 
  9   
 10  from exceptions import Exception 
 11  from omero.cli import BaseControl, CLI 
 12  import omero.java 
 13  import time 
 14  import sys 
 15  import os 
 16   
 17  HELP="""omero web settings 
 18   
 19  OMERO.web tools: 
 20   
 21       settings           - Configuration for web 
 22   
 23  For advance use: 
 24       custom_settings    - Creates only custom_settings.py 
 25       server             - Set to 'default' for django internal webserver 
 26                            or 'fastcgi' 
 27       config             - output a config template for server (only 'nginx' 
 28                            for the moment) 
 29       syncmedia          - creates needed symlinks for static media files 
 30       enableapp          - TODO: document 
 31       gateway 
 32       test 
 33       seleniumtest 
 34       call 
 35   
 36  """ 
37 -class WebControl(BaseControl):
38
39 - def _configure(self, parser):
40 sub = parser.sub() 41 parser.add(sub, self.help, "Print extended help") 42 parser.add(sub, self.settings, "Primary configuration for web") 43 parser.add(sub, self.custom_settings, "Advanced use: Creates only a a custom_settings.py") 44 45 start = parser.add(sub, self.start, "Primary start for webserver") 46 start.add_argument("host", nargs="*") 47 start.add_argument("port", nargs="*") 48 49 server = parser.add(sub, self.server, "Advanced use: Set to 'default' for django internal webserver or 'fastcfgi'") 50 server.add_argument("server") 51 52 config = parser.add(sub, self.config, "Advanced use: Output a config template for server (only 'nginx' for the moment") 53 config.add_argument("type", choices=("nginx",)) 54 55 parser.add(sub, self.syncmedia, "Advanced use: Creates needed symlinks for static media files") 56 57 enableapp = parser.add(sub, self.enableapp, "Advanced use:") 58 enableapp.add_argument("appname", nargs="*") 59 60 parser.add(sub, self.gateway, "Advanced use:") 61 62 test = parser.add(sub, self.test, "Advanced use:") 63 test.add_argument("arg", nargs="*") 64 65 selenium = parser.add(sub, self.seleniumtest, "Advanced use: runs selenium tests on a django app") 66 selenium.add_argument("djangoapp", help = "Django-app to be tested") 67 68 call = parser.add(sub, self.call, """Advanced use: call appname "[executable] scriptname" args """) 69 call.add_argument("appname") 70 call.add_argument("scriptname") 71 call.add_argument("arg", nargs="*")
72
73 - def help(self, args = None):
74 self.ctx.out(HELP)
75
76 - def _setup_server(self, email_server=None, app_host=None, sender_address=None, smtp_server=None):
77 settings = dict() 78 79 while not app_host or len(app_host) < 1: 80 app_host = self.ctx.input("Please enter the domain you want to run OMERO.web on (http://www.domain.com:8000/):") 81 if app_host == None or app_host == "": 82 self.ctx.err("Domain cannot be empty") 83 continue 84 settings["APPLICATION_HOST"] = app_host 85 break 86 87 while not sender_address or len(sender_address) < 1 : 88 sender_address = self.ctx.input("Please enter the Email address you want to send from (omero_admin@example.com): ") 89 if sender_address == None or sender_address == "": 90 self.ctx.err("Email cannot be empty") 91 continue 92 break 93 94 while not smtp_server or len(smtp_server) < 1 : 95 smtp_server = self.ctx.input("Please enter the SMTP server host you want to send from (smtp.example.com): ") 96 if smtp_server == None or smtp_server == "": 97 self.ctx.err("SMTP server host cannot be empty") 98 continue 99 100 smtp_port = self.ctx.input("Optional: please enter the SMTP server port (default 25): ") 101 smtp_user = self.ctx.input("Optional: Please enter the SMTP server username: ") 102 smtp_password = self.ctx.input("Optional: Password: ", hidden=True) 103 smtp_tls = self.ctx.input("Optional: TSL? (yes/no): ") 104 if smtp_tls == "yes": 105 smtp_tls = True 106 else: 107 smtp_tls = False 108 break 109 110 settings["SERVER_EMAIL"] = sender_address 111 settings["EMAIL_HOST"] = smtp_server 112 113 if smtp_port: 114 settings["EMAIL_PORT"] = smtp_port 115 if smtp_user: 116 settings["EMAIL_HOST_USER"] = smtp_user 117 if smtp_password: 118 settings["EMAIL_HOST_PASSWORD"] = smtp_password 119 if smtp_tls: 120 settings["EMAIL_USE_TLS"] = smtp_tls 121 122 return settings
123
124 - def _update_settings(self, location, settings=None):
125 output = open(location, 'w') 126 127 try: 128 output.write("""#!/usr/bin/env python 129 # 130 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 131 # # Django custom settings for OMERO.web project. # # 132 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 133 # 134 # 135 # Copyright (c) 2009 University of Dundee. 136 # 137 # This program is free software: you can redistribute it and/or modify 138 # it under the terms of the GNU Affero General Public License as 139 # published by the Free Software Foundation, either version 3 of the 140 # License, or (at your option) any later version. 141 # 142 # This program is distributed in the hope that it will be useful, 143 # but WITHOUT ANY WARRANTY; without even the implied warranty of 144 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 145 # GNU Affero General Public License for more details. 146 # 147 # You should have received a copy of the GNU Affero General Public License 148 # along with this program. If not, see <http://www.gnu.org/licenses/>. 149 # 150 # Author: Aleksandra Tarkowska <A(dot)Tarkowska(at)dundee(dot)ac(dot)uk>, 2008. 151 # 152 # Version: 1.0 153 154 # Notification 155 # Application allows to notify user about new shares 156 157 SERVER_LIST = ( 158 ('localhost', 4064, 'omero'), 159 ) 160 161 ADMINS = ( 162 # ('Name', 'email'), 163 ) 164 165 """) 166 if settings.has_key('SERVER_EMAIL'): 167 output.write("""SERVER_EMAIL = '%s' 168 """ % settings["SERVER_EMAIL"]) 169 if settings.has_key('EMAIL_HOST'): 170 output.write("""EMAIL_HOST = '%s' 171 """ % settings["EMAIL_HOST"]) 172 if settings.has_key('EMAIL_PORT'): 173 output.write("""EMAIL_PORT = %s 174 """ % settings["EMAIL_PORT"]) 175 if settings.has_key('EMAIL_HOST_USER'): 176 output.write("""EMAIL_HOST_USER = '%s' 177 """ % settings["EMAIL_HOST_USER"]) 178 if settings.has_key('EMAIL_HOST_PASSWORD'): 179 output.write("""EMAIL_HOST_PASSWORD = '%s' 180 """ % settings["EMAIL_HOST_PASSWORD"]) 181 if settings.has_key('EMAIL_USE_TLS'): 182 if settings["EMAIL_USE_TLS"]: 183 output.write("""EMAIL_USE_TLS = 'True' 184 """) 185 else: 186 output.write("""EMAIL_USE_TLS = 'False' 187 """) 188 189 output.write(""" 190 APPLICATION_HOST='%s' 191 """ % settings["APPLICATION_HOST"]) 192 finally: 193 output.flush() 194 output.close() 195 196 self.ctx.out("Saved to " + location) 197 sys.path_importer_cache.pop(self.ctx.dir / "var" / "lib", None) 198 self.ctx.out("PYTHONPATH updated.")
199
200 - def _get_yes_or_no(self, file_name, answer=None):
201 while answer != "yes" and answer != "no": 202 answer = self.ctx.input("%s already exist. Do you want to ovewrite it? (yes/no)" % file_name) 203 if answer != "yes" and answer != "no": 204 self.ctx.err("Answer yes or no") 205 continue 206 break 207 return answer
208
209 - def custom_settings(self, args):
210 location = self.ctx.dir / "var" / "lib" / "custom_settings.py" 211 212 if location.exists(): 213 if self._get_yes_or_no("%s" % location) == 'no': 214 if hasattr(args, "no_exit") and args.no_exit: 215 return 216 else: 217 sys.exit() 218 else: 219 self.ctx.out("You just installed OMERO, which means you didn't have settings configured in OMERO.web.") 220 221 if not os.path.exists(self.ctx.dir / "var" / "lib"): 222 os.mkdir(self.ctx.dir / "var" / "lib") 223 224 settings = self._setup_server() 225 self._update_settings(location, settings)
226
227 - def settings(self, args):
228 args.no_exit = True 229 self.custom_settings(args) 230 try: 231 sys.getwindowsversion() 232 except: 233 self.syncmedia(args)
234
235 - def server(self, args):
236 if not args.server: 237 self.ctx.out("OMERO.web application is served by 'default'") 238 else: 239 location = self.ctx.dir / "var" / "lib" / "custom_settings.py" 240 settings = file(location, 'rb').read().split('\n') 241 if settings[-1] == '': 242 settings = settings[:-1] 243 cserver = 'default' 244 for l in settings: 245 if l.startswith('APPLICATION_SERVER'): 246 cserver = l.split('=')[-1].strip().replace("'",'').replace('"','') 247 server = args.server 248 if server == cserver: 249 self.ctx.out("OMERO.web was already configured to be served by '%s'" % server) 250 elif server in ('default', 'fastcgi'): 251 if server == 'fastcgi': 252 import flup 253 out = file(location, 'wb') 254 wrote = False 255 for l in settings: 256 if l.startswith('APPLICATION_SERVER'): 257 wrote = True 258 out.write("APPLICATION_SERVER = '%s'\n" % server) 259 else: 260 out.write(l + '\n') 261 if not wrote: 262 out.write("APPLICATION_SERVER = '%s'\n" % server) 263 self.ctx.out("OMERO.web has been configured to be served by '%s'" % server) 264 else: 265 self.ctx.err("Unknown server '%s'" % server)
266
267 - def config(self, args):
268 if not args.type: 269 self.ctx.out("Available configuration helpers:\n - nginx\n") 270 else: 271 from omeroweb.settings import APPLICATION_HOST 272 host = APPLICATION_HOST.split(':') 273 try: 274 port = int(host[-1]) 275 except ValueError: 276 port = 8000 277 server = args.type 278 if server == "nginx": 279 c = file(self.ctx.dir / "etc" / "nginx.conf.template").read() 280 d = { 281 "ROOT":self.ctx.dir, 282 "OMEROWEBROOT":self.ctx.dir / "lib" / "python" / "omeroweb", 283 "HTTPPORT":port, 284 } 285 self.ctx.out(c % d)
286
287 - def syncmedia(self, args):
288 import shutil 289 from glob import glob 290 from omeroweb.settings import INSTALLED_APPS 291 location = self.ctx.dir / "lib" / "python" / "omeroweb" 292 # Targets 293 apps = map(lambda x: x.startswith('omeroweb.') and x[9:] or x, INSTALLED_APPS) 294 apps = filter(lambda x: os.path.exists(location / x), apps) 295 # Destination dir 296 if not os.path.exists(location / 'media'): 297 os.mkdir(location / 'media') 298 299 # Create app media links 300 for app in apps: 301 media_dir = location / app / 'media' 302 if os.path.exists(media_dir): 303 if os.path.exists(location / 'media' / app): 304 os.remove(os.path.abspath(location / 'media' / app)) 305 os.symlink(os.path.abspath(media_dir), location / 'media' / app)
306
307 - def enableapp(self, args):
308 from omeroweb.settings import INSTALLED_APPS 309 location = self.ctx.dir / "lib" / "python" / "omeroweb" 310 if not args.appname: 311 apps = [x.name for x in filter(lambda x: x.isdir() and (x / 'scripts' / 'enable.py').exists(), location.listdir())] 312 iapps = map(lambda x: x.startswith('omeroweb.') and x[9:] or x, INSTALLED_APPS) 313 apps = filter(lambda x: x not in iapps, apps) 314 self.ctx.out('[enableapp] available apps:\n - ' + '\n - '.join(apps) + '\n') 315 else: 316 for app in args.appname: 317 args = ["python", location / app / "scripts" / "enable.py"] 318 rv = self.ctx.call(args, cwd = location) 319 if rv != 0: 320 self.ctx.die(121, "Failed to enable '%s'.\n" % app) 321 else: 322 self.ctx.out("App '%s' was enabled\n" % app) 323 args = ["python", "manage.py", "syncdb", "--noinput"] 324 rv = self.ctx.call(args, cwd = location) 325 self.syncmedia(None)
326
327 - def gateway(self, args):
328 location = self.ctx.dir / "lib" / "python" / "omeroweb" 329 args = ["python", "-i", location / "../omero/gateway/scripts/dbhelpers.py"] 330 os.environ['ICE_CONFIG'] = self.ctx.dir / "etc" / "ice.config" 331 os.environ['PATH'] = os.environ.get('PATH', '.') + ':' + self.ctx.dir / 'bin' 332 os.environ['DJANGO_SETTINGS_MODULE'] = os.environ.get('DJANGO_SETTINGS_MODULE', 'omeroweb.settings') 333 rv = self.ctx.call(args, cwd = location)
334
335 - def test(self, args):
336 location = self.ctx.dir / "lib" / "python" / "omeroweb" 337 cargs = ["coverage","-x", "manage.py", "test"] 338 if args.arg: 339 cargs.append(args.arg) 340 os.environ['ICE_CONFIG'] = self.ctx.dir / "etc" / "ice.config" 341 os.environ['PATH'] = os.environ.get('PATH', '.') + ':' + self.ctx.dir / 'bin' 342 rv = self.ctx.call(cargs, cwd = location)
343
344 - def seleniumtest (self, args):
345 location = self.ctx.dir / "lib" / "python" / "omeroweb" 346 cargs = ["python", "seleniumtests.py"] 347 location = location / args.djangoapp / "tests" 348 print location 349 rv = self.ctx.call(cargs, cwd = location )
350
351 - def call (self, args):
352 try: 353 location = self.ctx.dir / "lib" / "python" / "omeroweb" 354 cargs = [] 355 appname = args.appname 356 scriptname = args.scriptname.split(' ') 357 if len(scriptname) > 1: 358 cargs.append(scriptname[0]) 359 scriptname = ' '.join(scriptname[1:]) 360 else: 361 scriptname = scriptname[0] 362 cargs.extend([location / appname / "scripts" / scriptname] + args.arg) 363 print cargs 364 os.environ['DJANGO_SETTINGS_MODULE'] = 'omeroweb.settings' 365 os.environ['ICE_CONFIG'] = self.ctx.dir / "etc" / "ice.config" 366 os.environ['PATH'] = os.environ.get('PATH', '.') + ':' + self.ctx.dir / 'bin' 367 rv = self.ctx.call(cargs, cwd = location) 368 except: 369 import traceback 370 print traceback.print_exc()
371
372 - def start(self, args):
373 host = args.host is not None and args.host or "0.0.0.0" 374 port = args.port is not None and args.port or "8000" 375 link = ("%s:%s" % (host, port)) 376 location = self.ctx.dir / "lib" / "python" / "omeroweb" 377 self.ctx.out("Starting django development webserver... \n") 378 import omeroweb.settings as settings 379 deploy = getattr(settings, 'APPLICATION_SERVER', 'default') 380 if deploy == 'fastcgi': 381 cmd = "python manage.py runfcgi workdir=./" 382 cmd += " method=prefork socket=%(base)s/var/django_fcgi.sock" 383 cmd += " pidfile=%(base)s/var/django.pid daemonize=false" 384 cmd += " maxchildren=5 minspare=1 maxspare=5 maxrequests=400" 385 django = (cmd % {'base': self.ctx.dir}).split()+list(args.arg) 386 else: 387 django = ["python","manage.py","runserver", link, "--noreload"] 388 rv = self.ctx.call(django, cwd = location)
389 390 try: 391 register("web", WebControl, HELP) 392 except NameError: 393 if __name__ == "__main__": 394 cli = CLI() 395 cli.register("web", WebControl, HELP) 396 cli.invoke(sys.argv[1:]) 397