00001
00002 '''
00003 This module is the log file parser server start script.
00004
00005 Reading University
00006 MSc in Network Centered Computing
00007 a.weise - a.weise@reading.ac.uk - December 2005
00008 '''
00009
00010 import server_classes
00011 import sys, os, time, getopt
00012 import socket
00013 import fcntl
00014 import struct
00015 from utils_server import LoadConfig, check_ip, usage_exit
00016
00017 class WorkingServer:
00018 '''
00019 This is the main class for the server.
00020 '''
00021
00022 def __init__(self, config_data, config_dir, verb):
00023 '''
00024 Constructor
00025 '''
00026 self._verbose = verb
00027 config = config_data
00028 self._workingpath = os.getcwd()
00029
00030 self._server_certificate = config.get("files.server_certificate")
00031 self._server_certificate_path = config.get("path.path_server_certificate")
00032 self._server_certificate_path = self._server_certificate_path.rstrip("/")
00033 if(self._server_certificate_path == '' or self._server_certificate_path == None):
00034 self._server_certificate_path = self._workingpath
00035 else:
00036 self._server_certificate = self._server_certificate.strip()
00037 if (-1 != self._server_certificate_path.find("/", 0, 1)):
00038
00039 pass
00040 else:
00041 self._server_certificate_path = self._workingpath+"/"+self._server_certificate_path
00042
00043 self._server_ca = config.get("files.server_ca")
00044 self._server_ca_path = config.get("path.path_server_ca")
00045 self._server_ca_path = self._server_ca_path.rstrip("/")
00046 if(self._server_ca_path == '' or self._server_ca_path == None):
00047 self._server_ca_path = self._workingpath
00048 else:
00049 self._server_ca = self._server_ca.strip()
00050 if (-1 != self._server_ca_path.find("/", 0, 1)):
00051
00052 pass
00053 else:
00054 self._server_ca_path = self._workingpath+"/"+self._server_ca_path
00055
00056 self._srb_log = config.get("files.srb_log")
00057 self._srb_log_path = config.get("path.path_srb_log")
00058 self._srb_log_path = self._srb_log_path.rstrip("/")
00059 if(self._srb_log_path == '' or self._srb_log_path == None):
00060 self._srb_log_path = self._workingpath
00061 else:
00062 self._srb_log = self._srb_log.strip()
00063 if (-1 != self._srb_log_path.find("/", 0, 1)):
00064
00065 pass
00066 else:
00067 self._srb_log_path = self._workingpath+"/"+self._srb_log_path
00068
00069 self._gz_path = config.get("path.path_gz")
00070 self._gz_path = self._gz_path.rstrip("/")
00071 if(self._gz_path == '' or self._gz_path == None):
00072 self._gz_path = self._workingpath
00073 else:
00074 if (-1 != self._gz_path.find("/", 0, 1)):
00075
00076 pass
00077 else:
00078 self._gz_path = self._workingpath+"/"+self._gz_path
00079
00080 self._keyword_name = config.get("files.keyword")
00081 self._keyword_path = config.get("path.path_keyword")
00082 self._keyword_path = self._keyword_path.rstrip("/")
00083 if(self._keyword_path == '' or self._keyword_path == None):
00084 self._keyword_path = self._workingpath
00085 else:
00086 self._keyword_name = self._keyword_name.strip()
00087 if (-1 != self._keyword_path.find("/", 0, 1)):
00088
00089 pass
00090 else:
00091 self._keyword_path = self._workingpath+"/"+self._keyword_path
00092
00093 self._xml_file = "client_log.xml"
00094 self._xml_file_path = os.getcwd()+"/xml_client"
00095
00096 try:
00097 self._interval = int(config.get("misc.minute"))
00098 except ValueError:
00099 print "Please check the configuration in the config file (section: misc, item: minute). It should have the following pattern:\nminute = <int>"
00100 os._exit(-1)
00101 try:
00102 self._port = int(config.get("misc.port"))
00103 except ValueError:
00104 print "Please check the configuration in the config file (section: misc, item: port). It should have the following pattern:\nport = <int>"
00105 os._exit(-1)
00106 if (self._port < 1024 or self._port > 50001):
00107 print "A server port is out of range. \nPlease check the configuration file and make sure the server port lies between 1025 (inclusive) and 50000 (inclusive)!\n\n"
00108 os._exit(-1)
00109
00110
00111 if(0 == os.path.exists(self._server_certificate_path+"/"+self._server_certificate)):
00112 print "Could not locate server certifiate under %s !\nMaybe change configuration file and try again!\n\n" % self._server_certificate_path
00113 os._exit(-1)
00114
00115 if(0 == os.path.exists(self._server_ca_path+"/"+self._server_ca)):
00116 print "Could not locate server ca certificate under %s !\nMaybe change configuration file and try again!\n\n" % self._server_ca_path
00117 os._exit(-1)
00118
00119 if(0 == os.access((self._srb_log_path+"/"+self._srb_log), 4)):
00120 print "Could not access SRB server log file under %s !\nMaybe change configuration file and try again!\n\n" % self._srb_log_path
00121 os._exit(-1)
00122
00123 if(0 == os.path.exists(self._xml_file_path)):
00124 print "Creating path \"%s\"\n\n" % self._xml_file_path
00125 os.mkdir(self._xml_file_path)
00126
00127 self._share = server_classes.Mutex()
00128
00129 self._keyword = server_classes.get_keywords(self._keyword_path+"/"+self._keyword_name)
00130
00131 error = config.get("misc.ignore_error")
00132
00133 self._ip = config.get("misc.interface")
00134
00135 error = error.strip()
00136 error = error.strip(",")
00137 self._ignore_error = error.split(",")
00138 for i in range(len(self._ignore_error)):
00139 if self._ignore_error[i] != '':
00140 try:
00141 self._ignore_error[i] = int(self._ignore_error[i].strip())
00142 except ValueError:
00143 print "Please check the \"ignore_error\" list in the config file (section: misc). It should have the following pattern (comma separeted list of integer):\nignore_error = <int>,<int> "
00144 os._exit(-1)
00145 else:
00146 del self._ignore_error[i]
00147
00148 self._configfile = config_dir
00149
00150 self._rpc = server_classes.RPC(self._verbose, self._share, self._configfile, self._interval, self._keyword_path, self._keyword_name, self._xml_file_path)
00151
00152 def establish_connection(self):
00153 '''
00154 establish a working connection using MySSLServer
00155 '''
00156 cert = self._server_certificate_path+"/"+self._server_certificate
00157 ca = self._server_ca_path+"/"+self._server_ca
00158 self._serverobject = server_classes.My_SSL_Server(cert, ca, self._verbose)
00159 ip = self.get_ip_address(self._ip)
00160 if (0 == check_ip(ip)):
00161 self._serv = self._serverobject.start_server(ip, self._port)
00162 else:
00163 print "Could not start the server. (IP: \"%s\")" % ip
00164 os._exit(-1)
00165
00166
00167 workerthread = server_classes.MyParserThread(self._share, self._interval, self._gz_path, self._srb_log_path, self._srb_log, self._keyword, self._ignore_error, self._xml_file_path, self._xml_file, self._configfile, (self._keyword_path+"/"+self._keyword_name), self._verbose)
00168 workerthread.setName("parser")
00169 workerthread.start()
00170 print "Started!\n\n"
00171
00172 def get_ip_address(self, network_interface):
00173 '''
00174 Uses the Linux SIOCGIFADDR ioctl to find the IP address associated with a network interface, given the name of that interface, e.g. "eth0".
00175
00176 source: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/439094
00177
00178 modified by a.weise (December 2005)
00179 '''
00180 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
00181 try:
00182 ip = socket.inet_ntoa(fcntl.ioctl(
00183 s.fileno(),
00184 0x8915,
00185 struct.pack('256s', network_interface[:15])
00186 )[20:24])
00187 return ip
00188 except IOError, e:
00189 return e
00190
00191 def register_functions(self):
00192 '''
00193 register all the rpc - functions
00194 '''
00195 self._serv.register_function(self._rpc.rpc_stop_server, 'stop_server')
00196 self._serv.register_function(self._rpc.rpc_status, 'rpc_status')
00197 self._serv.register_function(self._rpc.rpc_disable_rpc_calls, 'disable_rpc_calls')
00198 self._serv.register_function(self._rpc.rpc_enable_rpc_calls, 'enable_rpc_calls')
00199 self._serv.register_function(self._rpc.rpc_get_my_xml_file, 'get_my_xml_file')
00200 self._serv.register_function(self._rpc.rpc_get_file_list, 'get_file_list')
00201 self._serv.register_function(self._rpc.rpc_update_configuration, 'rpc_update_configuration')
00202 self._serv.register_function(self._rpc.rpc_update_keyword_file, 'rpc_update_keyword_file')
00203 self._serv.register_function(self._rpc.rpc_check_availabitity, 'rpc_check_availabitity')
00204 self._serv.register_function(self._rpc.rpc_interval_status, 'rpc_interval_status')
00205
00206 def run_server(self):
00207 '''
00208 handle all client requests
00209 '''
00210 try:
00211
00212 if self._verbose == 1:
00213 print "\nSimple SSL XML RPC Server is running ....\n"
00214 while (1):
00215 if self._verbose == 1:
00216 print "%s -> waiting for request ...." % time.ctime()
00217 self._serv.handle_request(self._serv)
00218 except KeyboardInterrupt:
00219
00220 if self._verbose == 1:
00221 sys.stdout.write("\n\nShutdown !!!\n\n")
00222
00223 command = "./stop_server"
00224 os.system(command)
00225
00226
00227
00228
00229
00230 def daemonize(verbose, stdout = '/dev/null', stderr = None, stdin = '/dev/null', pidfile = None, startmsg = 'Server daemon started with pid %s'):
00231
00232 '''
00233 This function creates a daemon by forking the current process. The parameters stdin, stdout, and stderr are file names which substitute the standard err-, in-, out- output. This parameters are optional and point normally to /dev/null. Note that stderr is opened unbuffered, so if it shares a file with stdout then interleaved output may not appear in the order that you expect.
00234
00235 source: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
00236 modified by a.weise November 2005
00237 '''
00238
00239
00240 try:
00241 pid = os.fork()
00242 if (pid > 0):
00243 sys.exit(0)
00244 except OSError, e:
00245 sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
00246 sys.exit(1)
00247
00248 os.umask(0)
00249 os.setsid()
00250
00251
00252 try:
00253 pid = os.fork()
00254 if (pid > 0):
00255 sys.exit(0)
00256 except OSError, e:
00257
00258 sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
00259 sys.exit(1)
00260
00261
00262 if (not stderr):
00263 stderr = stdout
00264
00265 if verbose == 1:
00266 si = file(stdin, 'r')
00267 so = file(stdout, 'w+')
00268 se = file(stderr, 'w+', 0)
00269 pid = str(os.getpid())
00270 sys.stderr.write("\n%s\n" % startmsg % pid)
00271 sys.stderr.flush()
00272 if pidfile:
00273 file(pidfile,'w+').write("%s\n" % pid)
00274
00275
00276 os.dup2(si.fileno(), sys.stdin.fileno())
00277 os.dup2(so.fileno(), sys.stdout.fileno())
00278 os.dup2(se.fileno(), sys.stderr.fileno())
00279
00280
00281
00282 def start():
00283
00284 '''
00285 START THE APPLICATION
00286 '''
00287 configfile = ""
00288 verbose = 0
00289 daemon = 0
00290
00291 try:
00292 opts, args = getopt.getopt(sys.argv[1:], 'c:vhd', ['config=', 'verbose', 'help', 'daemon'])
00293 for opt, value in opts:
00294 if opt in ('-h','--help'):
00295 msg = "\n\t\t----------- Help ----------\n\n\n"\
00296 "-c or --config\t-> defines config file, if no config file given, default values are used\n"\
00297 "-v or --verbose\t-> activates printing of messages [debug option]\n"\
00298 "-d or --daemon\t-> daemonize the server\n"\
00299 "-h or --help\t-> print this help\n\n"
00300 usage_exit(sys.argv[0], msg)
00301 if opt in ('-c','--config'):
00302 value = value.replace("=", "")
00303 configfile = os.getcwd()+"/"+value
00304 if opt in ('-v','--verbose'):
00305 verbose = 1
00306 if opt in ('-d', '--daemon'):
00307 daemon = 1
00308 except getopt.error, e:
00309 usage_exit(sys.argv[0], e)
00310
00311
00312 if (configfile != ""):
00313
00314 if(1 == os.path.exists(configfile)):
00315 config = LoadConfig(configfile)
00316 else:
00317
00318 print "Sorry, the given file does NOT exist !\nPlease try again!\n\n"
00319 os._exit(-1)
00320 else:
00321 msg = "\nNo configuration file spezified !\n"
00322 usage_exit(sys.argv[0], msg)
00323
00324 print "\n\n--------------------- SRB LOG FILE PARSER [ SERVER ] ------------------ \n\n"
00325 print "Starting ..."
00326
00327 worker = WorkingServer(config, configfile, verbose)
00328
00329 if daemon == 1:
00330 if verbose == 1:
00331
00332 daemonize(verbose, stdout = 'daemonize.log')
00333 else:
00334
00335 daemonize(verbose)
00336 else:
00337 pass
00338
00339 worker.establish_connection()
00340 worker.register_functions()
00341 worker.run_server()
00342
00343
00344 if __name__ == '__main__':
00345
00346 start()
00347
00348
00349
00350
00351
00352