Package gluon :: Module winservice
[hide private]
[frames] | no frames]

Source Code for Module gluon.winservice

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  """ 
  4  This file is part of the web2py Web Framework 
  5  Developed by Massimo Di Pierro <mdipierro@cs.depaul.edu> and 
  6  Limodou <limodou@gmail.com>. 
  7  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html) 
  8   
  9  This makes uses of the pywin32 package 
 10  (http://sourceforge.net/projects/pywin32/). 
 11  You do not need to install this package to use web2py. 
 12   
 13   
 14  """ 
 15   
 16  import time 
 17  import os 
 18  import sys 
 19  import traceback 
 20  try: 
 21      import win32serviceutil 
 22      import win32service 
 23      import win32event 
 24  except: 
 25      if os.name == 'nt': 
 26          print "Warning, winservice is unable to install the Mark Hammond Win32 extensions" 
 27  import servicemanager 
 28  import _winreg 
 29  from fileutils import up 
 30   
 31   
 32  __all__ = ['web2py_windows_service_handler'] 
 33   
 34   
35 -class Service(win32serviceutil.ServiceFramework):
36 37 _svc_name_ = '_unNamed' 38 _svc_display_name_ = '_Service Template' 39
40 - def __init__(self, *args):
41 win32serviceutil.ServiceFramework.__init__(self, *args) 42 self.stop_event = win32event.CreateEvent(None, 0, 0, None)
43
44 - def log(self, msg):
45 servicemanager.LogInfoMsg(str(msg))
46
47 - def SvcDoRun(self):
48 self.ReportServiceStatus(win32service.SERVICE_START_PENDING) 49 try: 50 self.ReportServiceStatus(win32service.SERVICE_RUNNING) 51 self.start() 52 win32event.WaitForSingleObject(self.stop_event, 53 win32event.INFINITE) 54 except: 55 self.log(traceback.format_exc(sys.exc_info)) 56 self.SvcStop() 57 self.ReportServiceStatus(win32service.SERVICE_STOPPED)
58
59 - def SvcStop(self):
60 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 61 try: 62 self.stop() 63 except: 64 self.log(traceback.format_exc(sys.exc_info)) 65 win32event.SetEvent(self.stop_event) 66 self.ReportServiceStatus(win32service.SERVICE_STOPPED)
67 68 # to be overridden 69
70 - def start(self):
71 pass
72 73 # to be overridden 74
75 - def stop(self):
76 pass
77 78
79 -class Web2pyService(Service):
80 81 _svc_name_ = 'web2py' 82 _svc_display_name_ = 'web2py Service' 83 _exe_args_ = 'options' 84 server = None 85
86 - def chdir(self):
87 try: 88 h = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 89 r'SYSTEM\CurrentControlSet\Services\%s' 90 % self._svc_name_) 91 try: 92 cls = _winreg.QueryValue(h, 'PythonClass') 93 finally: 94 _winreg.CloseKey(h) 95 dir = os.path.dirname(cls) 96 os.chdir(dir) 97 from gluon.settings import global_settings 98 global_settings.gluon_parent = dir 99 return True 100 except: 101 self.log("Can't change to web2py working path; server is stopped") 102 return False
103
104 - def start(self):
105 self.log('web2py server starting') 106 if not self.chdir(): 107 return 108 if len(sys.argv) == 2: 109 opt_mod = sys.argv[1] 110 else: 111 opt_mod = self._exe_args_ 112 options = __import__(opt_mod, [], [], '') 113 if True: # legacy support for old options files, which have only (deprecated) numthreads 114 if hasattr(options, 'numthreads') and not hasattr(options, 'minthreads'): 115 options.minthreads = options.numthreads 116 if not hasattr(options, 'minthreads'): 117 options.minthreads = None 118 if not hasattr(options, 'maxthreads'): 119 options.maxthreads = None 120 import main 121 self.server = main.HttpServer( 122 ip=options.ip, 123 port=options.port, 124 password=options.password, 125 pid_filename=options.pid_filename, 126 log_filename=options.log_filename, 127 profiler_filename=options.profiler_filename, 128 ssl_certificate=options.ssl_certificate, 129 ssl_private_key=options.ssl_private_key, 130 min_threads=options.minthreads, 131 max_threads=options.maxthreads, 132 server_name=options.server_name, 133 request_queue_size=options.request_queue_size, 134 timeout=options.timeout, 135 shutdown_timeout=options.shutdown_timeout, 136 path=options.folder 137 ) 138 try: 139 from rewrite import load 140 load() 141 self.server.start() 142 except: 143 144 # self.server.stop() 145 146 self.server = None 147 raise
148
149 - def stop(self):
150 self.log('web2py server stopping') 151 if not self.chdir(): 152 return 153 if self.server: 154 self.server.stop() 155 time.sleep(1)
156 157
158 -class Web2pyCronService(Web2pyService):
159 160 _svc_name_ = 'web2py_cron' 161 _svc_display_name_ = 'web2py Cron Service' 162 _exe_args_ = 'options' 163
164 - def start(self):
165 import newcron 166 import global_settings 167 self.log('web2py server starting') 168 if not self.chdir(): 169 return 170 if len(sys.argv) == 2: 171 opt_mod = sys.argv[1] 172 else: 173 opt_mod = self._exe_args_ 174 options = __import__(opt_mod, [], [], '') 175 global_settings.global_settings.web2py_crontype = 'external' 176 if options.scheduler: # -K 177 apps = [app.strip() for app in options.scheduler.split( 178 ',') if check_existent_app(options, app.strip())] 179 else: 180 apps = None 181 self.extcron = newcron.extcron(options.folder, apps=apps) 182 try: 183 self.extcron.start() 184 except: 185 # self.server.stop() 186 self.extcron = None 187 raise
188
189 - def stop(self):
190 self.log('web2py cron stopping') 191 if not self.chdir(): 192 return 193 if self.extcron: 194 self.extcron.join()
195
196 -def register_service_handler(argv=None, opt_file='options', cls=Web2pyService):
197 path = os.path.dirname(__file__) 198 web2py_path = up(path) 199 if web2py_path.endswith('.zip'): # in case bianry distro 'library.zip' 200 web2py_path = os.path.dirname(web2py_path) 201 os.chdir(web2py_path) 202 classstring = os.path.normpath( 203 os.path.join(web2py_path, 'gluon.winservice.'+cls.__name__)) 204 if opt_file: 205 cls._exe_args_ = opt_file 206 win32serviceutil.HandleCommandLine( 207 cls, serviceClassString=classstring, argv=['', 'install']) 208 win32serviceutil.HandleCommandLine( 209 cls, serviceClassString=classstring, argv=argv)
210 211 if __name__ == '__main__': 212 register_service_handler(cls=Web2pyService) 213 register_service_handler(cls=Web2pyCronService) 214