[Nym3-commit] r447 - trunk/nymbaron/Server

laurent at conuropsis.org laurent at conuropsis.org
Sun Feb 5 17:11:35 CET 2006


Author: laurent
Date: 2006-02-05 17:11:33 +0100 (Sun, 05 Feb 2006)
New Revision: 447

Modified:
   trunk/nymbaron/Server/Config.py
   trunk/nymbaron/Server/Main.py
Log:
Add support for logging to file.


Modified: trunk/nymbaron/Server/Config.py
===================================================================
--- trunk/nymbaron/Server/Config.py	2006-01-18 10:47:16 UTC (rev 446)
+++ trunk/nymbaron/Server/Config.py	2006-02-05 16:11:33 UTC (rev 447)
@@ -25,8 +25,10 @@
 
 import os
 import ConfigParser
+import logging
 
 SYSFILE = "/etc/nymbaron/nymbarond.conf"
+LEVELMAP = {'debug': logging.DEBUG, 'info': logging.INFO}
 
 def userfile():
     if os.environ.has_key('HOME'):
@@ -35,6 +37,14 @@
 	import pwd
 	return pwd.getpwuid(os.getuid())[5] + '/.nymbaronrc'
 
+def string2loglevel(s):
+    s = s.lower()
+    if s == 'debug':
+	return logging.DEBUG
+    if s == 'info':
+	return logging.INFO
+    return logging.DEBUG
+
 class Config:
 
     def __init__(self, filename = None):
@@ -51,6 +61,12 @@
 	self.path = '/tmp'
 	"""The path to the directory containing the server data"""
 
+	self.logfile = '/var/tmp/nymbaron.log'
+	"""The file where logging informations are written"""
+
+	self.loglevel = logging.DEBUG
+	"""The logging verbosity"""
+
 	self.default_settings = { 'quota' : 10 * 2**20, 'usage' : 0,
 			    'idKey' : None, 'encKey' : None, 'policy' : None,
 			    'SendMsgAfter' : 24, 'SendSummaryAfter' : 12, 
@@ -84,3 +100,9 @@
 		for k in self.default_settings.keys():
 		    if config.has_option('accounts', k):
 			self.default_settings[k] = config.get('accounts', k)
+
+	    if config.has_section('logging'):
+		if config.has_option('logging', 'logfile'):
+		    self.logfile = config.get('logging', 'logfile')
+		if config.has_option('logging', 'loglevel'):
+		    self.logfile = string2loglevel(config.get('logging', 'loglevel'))

Modified: trunk/nymbaron/Server/Main.py
===================================================================
--- trunk/nymbaron/Server/Main.py	2006-01-18 10:47:16 UTC (rev 446)
+++ trunk/nymbaron/Server/Main.py	2006-02-05 16:11:33 UTC (rev 447)
@@ -36,6 +36,10 @@
 import nymbaron.Common as Common
 import nymbaron.Mail as Mail
 import mixminion.Crypto as _cr
+import os
+import base64
+import re
+import logging
 
 lifeCycle = User.lifeCycle
 """The life cycle of a mail received by the server for a nym""" 
@@ -48,6 +52,10 @@
     \tclean-surbs\tRemove used or outdated surbs from account surb files
     \tencode-synopses\tEncrypt synopses that are still in clear"""
 
+# Forward declarations
+logger = None
+config = None
+
 def readMessage(filename):
     if filename:
 	try:
@@ -55,30 +63,17 @@
 	    msg = f.read()
 	    f.close()
 	except IOError:
-	    print("Can't read requested file")
+	    logger.error("Can't read incoming message in specified file %s" % filename)
 	    sys.exit(1)
     else:
 	try:
 	    msg = sys.stdin.read()
 	except KeyboardInterrupt:
-	    print "Interrupted by the user"
+	    logger.error("Interrupted by the user while reading incoming message from stdin")
 	    sys.exit(2)
     return msg
 
-# Try to load the configuration file.
-try:
-    import os
-    os.stat(Config.SYSFILE)
-    config = Config.Config(Config.SYSFILE)
-except OSError:
-    try:
-	import os
-	os.stat(Config.userfile())
-	config = Config.Config(Config.userfile())
-    except OSError:
-	config = Config.Config()
-
-def mapAccount(config, fun, funargs = None):
+def mapAccount(fun, funargs = None):
     """Applies the function fun to each account of the server. The signature of
     fun is: fun(account[, tuple of arguments specific to fun]), returns nothing
     """
@@ -99,12 +94,12 @@
     try:
 	nymuser = User.User(localpart, config)
     except User.NoSuchUser:
-	print "No such user " + localpart
+	logger.error("No such user %s while processing incoming email" % localpart)
 	sys.exit(73)
     # TODO : we should honor the "Quota" sending policy.
     if nymuser.usage() + len(msg) > nymuser.quota():
-	print "Quota exceeded."
-	print repr(nymuser.usage()) + " > " + repr(nymuser.quota())
+	logger.error("Quota exceeded for user %s : %s > %s" % (localpart, repr(nymuser.usage()),
+							       repr(nymuser.quota())))
 	sys.exit(75)
     # Valid user, not over quota. Filtering policy can wait.
     nymuser.store(msg)
@@ -118,6 +113,7 @@
     
     class MyException(Exception): pass
     
+    logger.debug("Processing control message:\n%s" % base64.encodestring(msg))
     sr = Message.StrReader(msg)
     try:
 	h = sr.readHeader()
@@ -162,14 +158,14 @@
 			if (nymUser == None):
 			    #TODO send an Error message to the client when surbs become available?
 			    #for the time being just ignore
-			    print "All nyms proposed in the list were already attributed"
+			    logger.info("All nyms proposed in the list were already attributed")
 			    raise MyException()
-			del(comList[idx])
+			del comList[idx]
 			break
-		if(nymUser == None):
+		if (nymUser == None):
 		    #TODO send an Error message to the client when surbs become available?
 		    #for the time being just ignore
-		    print "No Create Command"
+		    logger.info("No Create Command")
 		    raise MyException()
 			
 		#phase 2 we look for the command surb
@@ -177,9 +173,9 @@
 		    if(com.ct()==2): # TODO : evil numeric litteral
 			nymUser.addSurbs(com.surbs)
 			if nymUser['nSurbs'] < 3:
-			    print "Not Enough Surbs"
+			    logger.info("Not Enough Surbs")
 			    raise MyException()
-			del (comList[idx])
+			del comList[idx]
 			break
 		if(len(comList) != 1):
 		    nymUser.abort()
@@ -208,13 +204,13 @@
 	    except MyException:
 		   #if you come here something went wrong during the account
 		   #initialization
-		   print "Bad formed account creation message"
+		   logger.debug("Bad formed account creation message")
 		   sys.exit(2) #TODO smart error code
 	else: # NYM is not empty
 	    try:
 		nymUser = User.User(h.nym, config)
 	    except User.NoSuchUser:
-		print "No such user %s" % h.nym
+		logger.debug("No such user %s" % h.nym)
 		sys.exit(73) #TODO is it the smart error code
 	    if(not nymUser.checkMessageSign(msg[Message.sigLength:],h.sig)):
 		return
@@ -247,7 +243,7 @@
 			ec = Mail.relay(h.nym, com.rt, com.ri,
 					config.serverName, com.body)
 			if (ec != 0):
-			    print "mixminion exited abnormally with error code %d" % ec
+			    logger.error("mixminion exited abnormally with error code %d" % ec)
 			    sys.exit(2)
 			    
 		    elif (com.ct() == Message.CToSCODE['Get']):
@@ -261,14 +257,14 @@
 				sendList.append(m)
 			ec = nymUser.advanced_send(
 				Message.buildMessage(msgList))
-			print "EC is " + str(ec)
+			logger.debug("EC is " + str(ec))
 			if (ec == 0):
 			    nymUser.markMid(sendList,lifeCycle['sent-in-full'])
 			    if(nymUser['HoldUntilAck'] == 'never'):
 				map(nymUser.delete_msg,sendList)
 			    
 			else:
-			    print "mixminion exited abnormally with error code %d" % ec
+			    logger.error("mixminion exited abnormally with error code %d" % ec)
 			    sys.exit(2)
 				
 		    elif (com.ct() == Message.CToSCODE['Summarize']):
@@ -289,7 +285,7 @@
 			if (ec == 0):
 			    nymUser.markMid(mList, lifeCycle['synopsis-sent'])
 			else:
-			    print "mixminion exited abnormally with error code %d" % ec
+			    logger.error("mixminion exited abnormally with error code %d" % ec)
 			    sys.exit(2)
 
 		    elif (com.ct() == Message.CToSCODE['Delete']):
@@ -301,14 +297,31 @@
 		    else:
 			pass
     except Message.ParseError, inst:
-	print inst
+	logger.error("Parse error in incoming control message %s" % str(inst))
 	sys.exit(2) #TODO error code		
 	      
 def main(args):
     if len(args) < 2:
 	print usage_string
 	sys.exit(1)
-    #TODO load the config file here?
+    # Try to load the configuration file.
+    global config, logger
+    try:
+	os.stat(Config.SYSFILE)
+	config = Config.Config(Config.SYSFILE)
+    except OSError:
+	try:
+	    os.stat(Config.userfile())
+	    config = Config.Config(Config.userfile())
+	except OSError:
+	    config = Config.Config()
+    # The main logger object :
+    logger = logging.getLogger('nymbaron')
+    hdlr = logging.FileHandler(config.logfile)
+    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+    hdlr.setFormatter(formatter)
+    logger.addHandler(hdlr)
+    logger.setLevel(config.loglevel)
     
     if args[1] == "deliver":
 	parser = OptionParser(usage =
@@ -334,13 +347,12 @@
 		dest = "file", help = "The file to read the message " +
 		"from, or stdin if omitted")
 	(options, args) = parser.parse_args(args[2:])
+	logger.debug("Got an incoming control message")
 	try:
 	    msg = readMessage(options.file)
 	    processMessage(msg)
-	except Exception:#TODO catch a more detailed exception
+	except Exception: #TODO catch a more detailed exception
 	    # see if we got a base64 encoded message.
-	    import base64
-	    import re
 	    m = re.search("binary\\n\\n(.*)\\n---", msg, re.S)
 	    if m:
 		processMessage(base64.decodestring(m.group(1)))
@@ -349,7 +361,7 @@
 	sys.exit(0)
     
     if args[1] == "clean-surbs":
-	mapAccount(config, User.User.clean_surbs)
+	mapAccount(User.User.clean_surbs)
 	sys.exit(0)
 
     if args[1] == "encode-synopses":



More information about the Nym3-commit mailing list