F:/thesis_austausch/dissertation/code_docu_doxygen/Client/start_client.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 '''
00003 This module is the log file parser client start file.
00004 
00005 Reading University
00006 MSc in Network Centered Computing
00007 a.weise - a.weise@reading.ac.uk - December 2005
00008 '''
00009 
00010 import client_classes, os, sys, time
00011 import  getopt, smtplib, socket
00012 from utils_client import LoadConfig, check_ip, usage_exit, get_password
00013 
00014 class MyClient:
00015     '''
00016     main class for the client application 
00017     '''
00018     def __init__(self, config_data, verb, smtp_pa):
00019         '''
00020         Constructor
00021         '''
00022         self._verbose = verb
00023         config = config_data
00024         self._workingpath = os.getcwd()
00025         
00026         #----------------- put together path and file ------------------------------------
00027         self._database_name = config.get("database.name")
00028         self._database_path = config.get("database.path")
00029         self._database_path = self._database_path.rstrip("/")        
00030         if(config.get("database.path") == '' or config.get("database.path") == None):
00031             # field is empty
00032             self._database_path = self._workingpath
00033                 
00034         else:
00035             self._database_name = self._database_name.strip()
00036             if (-1 != self._database_path.find("/", 0, 1)):
00037                 # first character "/"
00038                 print "/ an erster stelle"
00039                 #pass
00040             else:
00041                 self._database_path = self._workingpath+"/"+self._database_path            
00042 
00043         self._error_description_name = config.get("files.error_description")
00044         self._error_description_path = config.get("path.path_error_description")
00045         self._error_description_path = self._error_description_path.rstrip("/")
00046         if(config.get("path.path_error_description") == '' or config.get("path.path_error_description") == None):
00047             self._error_description_path = self._workingpath
00048         else:
00049             self._error_description_name = self._error_description_name.strip()
00050             if (-1 != self._error_description_path.find("/", 0, 1)):
00051                 # first character "/"
00052                 pass
00053             else:
00054                 self._error_description_path = self._workingpath+"/"+self._error_description_path
00055         
00056         self._client_certificate = config.get("files.client_certificate")
00057         self._client_certificate_path = config.get("path.path_client_certificate") 
00058         self._client_certificate_path = self._client_certificate_path.rstrip("/")        
00059         if(config.get("path.path_client_certificate") == '' or config.get("path.path_client_certificate") == None):
00060             self._client_certificate_path = self._workingpath
00061         else:
00062             self._client_certificate = self._client_certificate.strip()
00063             if (-1 != self._client_certificate_path.find("/", 0, 1)):
00064                 # first character "/"
00065                 pass
00066             else:
00067                 self._client_certificate_path = self._workingpath+"/"+self._client_certificate_path
00068                 
00069         self._client_ca = config.get("files.client_ca")
00070         self._client_ca_path = config.get("path.path_client_ca") 
00071         self._client_ca_path = self._client_ca_path.rstrip("/")        
00072         if(config.get("path.path_client_ca") == '' or config.get("path.path_client_ca") == None):
00073             self._client_ca_path = self._workingpath
00074         else:
00075             self._client_ca = self._client_ca.strip()
00076             if (-1 != self._client_ca_path.find("/", 0, 1)):
00077                 # first character "/"
00078                 pass
00079             else:
00080                 self._client_ca_path = self._workingpath+"/"+self._client_ca_path
00081         
00082         # check if the configuration if correct
00083         if(0 == os.path.exists(self._client_certificate_path+"/"+self._client_certificate)):
00084             print "Could not locate client certifiate under %s !\nMaybe change configuration file and try again!\n\n" % self._client_certificate_path
00085             os._exit(-1)
00086         
00087         if(0 == os.path.exists(self._client_ca_path+"/"+self._client_ca)):
00088             print "Could not locate client ca certificate under %s !\nMaybe change configuration file and try again!\n\n" % self._client_ca_path
00089             os._exit(-1)
00090             
00091         if(0 == os.path.exists(self._error_description_path+"/"+self._error_description_name)):
00092             print "Could not locate error description file under %s !\nMaybe change configuration file and try again!\n\n" % self._error_description_path
00093             os._exit(-1)
00094         
00095         self._project = config.get("project.name")
00096         self._interval = int(config.get("misc.minute"))
00097         
00098         #----------------- create server list ------------------------
00099         servers = config.get("server.serverlist")
00100         # split where commas
00101         servers_split = servers.split(",")
00102         # create dictionary
00103         self._serverlist = {}    # dictionary for serverlist:port
00104         for i in range(len(servers_split)):
00105             # remove whitespace
00106             servers_split[i] = servers_split[i].strip()
00107             temp_list = servers_split[i].split(":")
00108             # remove whitespace
00109             if len(temp_list) != 2:
00110                 print "The IP configuration \"%s\" seems not correct. \nPlease check the configuration file!\n\n" % temp_list[0]
00111                 os._exit(-1)
00112             temp_list[0] = temp_list[0].strip()
00113             temp_list[1] = temp_list[1].strip()
00114             # check if IP is valid
00115             if( -1 == check_ip(temp_list[0])):
00116                 print "The IP \"%s\" seems not correct. \nPlease check the configuration file!\n\n" % temp_list[0]
00117                 os._exit(-1)
00118             try:
00119                 temp_list[1] = int(temp_list[1])
00120             except ValueError:
00121                 print "The port \"%s\" is not valid.\nPlease check the configuration file!\n\n" % temp_list[1]
00122                 os._exit(-1)
00123             if (temp_list[1] < 1024 or temp_list[1] > 50001):
00124                 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"
00125                 os._exit(-1)
00126             self._serverlist[temp_list[0]] = temp_list[1]
00127             
00128         self._share = client_classes.Mutex()
00129         
00130         # mail issues
00131         self._smtp_server = config.get("mail.smtp_server")
00132         self._smtp_pass = smtp_pa
00133         self._smtp_from = config.get("mail.from")
00134         self._smtp_user = config.get("mail.user")
00135         
00136         if (None != self._smtp_pass):
00137             # test if smtp server and login is possible
00138             try:
00139                 if self._verbose == 1:
00140                     print "Test SMTP connection to server \"%s\"...." % self._smtp_server
00141                 server = smtplib.SMTP(self._smtp_server)
00142                 print "server object: ", server
00143                 if self._verbose == 1:  # --- debug ---
00144                     server.set_debuglevel(1) # ---- debug ----
00145                 server.login(self._smtp_user, self._smtp_pass)
00146                 server.quit()
00147                 if self._verbose == 1:
00148                     print "SMTP connection successfully tested"
00149             except smtplib.SMTPAuthenticationError, e:
00150                 print "Problem with SMTP server authentication -> \"%s\" !" % e
00151                 print "\n"
00152                 os._exit(-1)
00153             except socket.error, e:
00154                 print "Problem with SMTP server -> \"%s\" !" % e
00155                 print "\n"
00156                 os._exit(-1)
00157 
00158         self._mail_address = []    # mail address list
00159         z = 1
00160         while(1):
00161             temp = "mail_to.address_%d" % z
00162             testus = config.get(temp)
00163             if testus == None:
00164                 break
00165             self._mail_address.append(testus)
00166             z += 1
00167                 
00168         keywordfiles = []
00169         
00170         z = 1
00171         while(1):
00172             temp = "mail_to.path_ignore_error_%d" % z
00173             path = config.get(temp)
00174             if(path == '' or path == None):
00175                 path = self._workingpath
00176             else:
00177                 path = path.rstrip("/")
00178                 if (-1 != path.find("/", 0, 1)):
00179                     # first character "/"
00180                     pass
00181                 else:
00182                     path = self._workingpath+"/"+path
00183            
00184             temp = "mail_to.file_ignore_error_%d" % z
00185             filus = config.get(temp)
00186             if filus == None:
00187                 break
00188             filus = filus.strip()
00189             
00190             keywordfilus = path+"/"+filus
00191             
00192             if(0 == os.access(keywordfilus, 4)):    # 4 -> R_OK -> read only
00193                 print "Could not access keyword file under %s !\nMaybe change configuration file and try again!\n\n" % keywordfilus
00194                 os._exit(-1)            
00195             
00196             keywordfiles.append(keywordfilus)
00197             z += 1
00198         
00199         self._mail_ignore_error = range(len(keywordfiles))
00200         for i in range(len(keywordfiles)):
00201             self._mail_ignore_error[i] = self._get_keywords(keywordfiles[i])
00202 
00203     def _get_keywords(self, filus):
00204         '''
00205         This function extracts keyword from a give file!
00206         '''
00207         keys = []
00208         
00209         try:
00210             file_fd = file(filus, 'r')
00211         except IOError, e:
00212             print "Problem with keyword file -> ",  e
00213             return -1
00214         
00215         content = file_fd.readlines()# save file contetn as list (1 line == 1 entry)
00216 
00217         file_fd.close()
00218     
00219         content = self._remove_item(content, "#")
00220         content = self._remove_item(content, "\n")
00221     
00222         for i in range(len(content)):
00223             content[i] = content[i].strip()
00224             content[i] = content[i].rstrip(",")
00225             content[i] = content[i].split(",")
00226             for a in range(len(content[i])):
00227                 keys.append(content[i][a])
00228         
00229         for i in range(len(keys)):
00230             keys[i] = keys[i].strip() # remove whitespace
00231             keys[i] = keys[i].split(":")
00232             
00233         return keys
00234             
00235     def _remove_item(self, listus, item):
00236         '''
00237         This function removes an item for a list as a rekursive function.
00238         '''
00239         while(1):
00240             
00241             for i in range(len(listus)):
00242                 if -1 != listus[i].find(item, 0, 1):
00243                     del listus[i]
00244                     self._remove_item(listus, item)
00245                     break
00246             else:
00247                 break
00248             
00249         return listus       
00250         
00251     def initialise_database(self):
00252         '''
00253         This function is initalising the database, creates it, when it's not there! It creates finally the database access cursor for further work with the database.
00254         '''
00255         self._db = client_classes.MyDatabase(self._error_description_name, self._error_description_path, self._database_name, self._database_path, self._serverlist.items(), self._project, self._verbose)
00256         
00257     def get_serverlist(self):
00258         '''
00259         This function returns the server list.
00260         '''
00261         return self._serverlist
00262     
00263     def fetch_error_messages(self):
00264         '''
00265         This function starts the worker thread, who initalises the regular fetching of the error messages.
00266         '''
00267         self._workerthread = client_classes.WorkerThread(self._share, self._db, self._interval, self._serverlist.items(), self._client_certificate, self._client_certificate_path, self._client_ca, self._client_ca_path, self._verbose, self._mail_address, self._mail_ignore_error, self._smtp_server, self._smtp_pass, self._smtp_from, self._smtp_user)
00268         self._workerthread.setName("workerthreadDaemon")
00269         self._workerthread.start()
00270        
00271         if self._verbose == 1:
00272             print "%s -> Manager thread started !" % ( time.ctime() ) #--- debug ----
00273         
00274 
00275 ##########################################################        
00276         
00277 def daemonize(verbose, stdout = '/dev/null', stderr = None, stdin = '/dev/null', pidfile = None, startmsg = 'Client daemon started with pid %s'):
00278 
00279     '''
00280     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.
00281         
00282     source: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
00283     modified by a.weise November 2005
00284     '''
00285 
00286     # first fork => fork creates first child-process
00287     try: 
00288         pid = os.fork() 
00289         if (pid > 0):
00290             sys.exit(0) # close first parent-process
00291 
00292     except OSError, e: 
00293         sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
00294         sys.exit(1)
00295       
00296     os.umask(0) 
00297     os.setsid()
00298     
00299     # second fork
00300     try: 
00301         pid = os.fork() 
00302         if (pid > 0):
00303             sys.exit(0) # close second parent-process
00304 
00305     except OSError, e: 
00306 
00307         sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
00308         sys.exit(1)
00309 
00310     # open standard in and out and print standard message
00311     if (not stderr):# if not stderr given => take stdout-path
00312         stderr = stdout
00313 
00314 
00315     if verbose == 1:
00316         si = file(stdin, 'r')
00317         so = file(stdout, 'w+') # w -> overwrite old log content
00318         se = file(stderr, 'w+', 0)
00319         pid = str(os.getpid())
00320         sys.stderr.write("\n%s\n" % startmsg % pid)
00321         sys.stderr.flush()
00322         if pidfile:
00323             file(pidfile,'w+').write("%s\n" % pid)
00324 
00325         # redirect standard in and out to files
00326         os.dup2(si.fileno(), sys.stdin.fileno())
00327         os.dup2(so.fileno(), sys.stdout.fileno())
00328         os.dup2(se.fileno(), sys.stderr.fileno())
00329         
00330       
00331         
00332 ##################################################################
00333 
00334 def start():
00335     
00336     '''
00337     Start the application.
00338     '''
00339     configfile = ""
00340     verbose = 0
00341     smtp_pass = None
00342     daemon = 0
00343     
00344     try:
00345         opts, args = getopt.getopt(sys.argv[1:], 'c:vhpd', ['config=', 'verbose', 'help', 'smtp_password', '--daemon'])
00346         for opt, value in opts:
00347             if opt in ('-h','--help'):
00348                 msg = "\n-----------   Help   ----------\n\n\n"\
00349                       "-c or --config\t\t->  defines config file, if no config file given, default values are used\n"\
00350                       "-p or --smtp_password\t->  activates mail notification sending\n"\
00351                       "-v or --verbose\t\t->  activates printing of messages [debug option]\n"\
00352                       "-d or --daemon\t\t->  daemonize the client\n"\
00353                       "-h or --help\t\t->  print this help\n\n"
00354                 usage_exit(sys.argv[0], msg)
00355             if opt in ('-c','--config'):
00356                 value = value.replace("=", "")
00357                 configfile = os.getcwd()+"/"+value
00358             if opt in ('-v','--verbose'):
00359                 verbose = 1
00360             if opt in ('-p', '--smtp_password'):
00361                 smtp_pass = get_password("Please enter SMTP password: ")
00362             if opt in ('-d', '--daemon'):
00363                 daemon = 1
00364     except getopt.error, e:
00365         usage_exit(sys.argv[0], e)
00366            
00367     # load config file or default values
00368     if (configfile != ""):
00369         # check if file exists
00370         if(1 == os.path.exists(configfile)):
00371             config = LoadConfig(configfile)
00372         else:
00373             # if file NOT exists terminate program
00374             print "Sorry, a given file does NOT exist !\nPlease try again!\n\n"
00375             os._exit(-1)
00376     else:
00377         msg = "\nNo config file spezified !\n"
00378         usage_exit(sys.argv[0], msg)
00379 
00380     print "\n\n--------------------- SRB LOG FILE PARSER [ CLIENT ] ------------------ \n\n"
00381     print "Starting ..."    
00382 
00383 
00384     worker = MyClient(config, verbose, smtp_pass)
00385     worker.initialise_database()
00386     
00387     if daemon == 1:
00388         if verbose == 1:
00389             daemonize(verbose, stdout = 'daemonize.log')
00390         else:
00391             daemonize(verbose)
00392     else:
00393         pass 
00394        
00395     print "%s -> Start manager thread ..." % (time.ctime())
00396     worker.fetch_error_messages()
00397 
00398 if __name__ == '__main__':
00399         
00400     start()

Generated on Sun Mar 5 15:54:49 2006 for Client by  doxygen 1.4.6-NO