ia64/xen-unstable

changeset 7301:d6d1c3cbc151

Rewritten XendLogging to not be a singleton class, and not have methods used
from nowhere at all.

Log to a temporary file if permission is denied to log to /var/log/xend.log,
as happens when you are not root. Fixes bug #305.

Remove all the log-related garbage from XendRoot -- just about every module
was going straight to XendLogging.log already, so there was no need to have
XendRoot replicate this functionality.

Remove XendRoot.event_handler, which hasn't been in use since the EventServer
was removed.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Mon Oct 10 16:15:48 2005 +0100 (2005-10-10)
parents 1ac39c7a0435
children f9bd8df8a098
files tools/python/xen/xend/XendLogging.py tools/python/xen/xend/XendRoot.py tools/python/xen/xend/server/SrvXendLog.py tools/python/xen/xend/server/event.py
line diff
     1.1 --- a/tools/python/xen/xend/XendLogging.py	Mon Oct 10 14:46:53 2005 +0100
     1.2 +++ b/tools/python/xen/xend/XendLogging.py	Mon Oct 10 16:15:48 2005 +0100
     1.3 @@ -13,79 +13,82 @@
     1.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     1.5  #============================================================================
     1.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
     1.7 +# Copyright (C) 2005 XenSource Ltd
     1.8  #============================================================================
     1.9  
    1.10 +
    1.11 +import tempfile
    1.12  import types
    1.13  import logging
    1.14 -from logging import Formatter, StreamHandler
    1.15 -from logging.handlers import RotatingFileHandler
    1.16 -
    1.17 -class XendLogging:
    1.18 -
    1.19 -    KB = 1024
    1.20 -    MB = 1024 * KB
    1.21 -    
    1.22 -    maxBytes = 1 * MB
    1.23 -    backupCount = 5
    1.24 -
    1.25 -    logStderrFormat = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
    1.26 -    logFileFormat   = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
    1.27 -    dateFormat = "%Y-%m-%d %H:%M:%S"
    1.28 +import logging.handlers
    1.29  
    1.30 -    def __init__(self, filename, level=logging.INFO, maxBytes=None, backupCount=None):
    1.31 -        """Initialise logging. Logs to 'filename' by default, but does not log to
    1.32 -        stderr unless addLogStderr() is called.
    1.33 -        """
    1.34 -        self.setLevel(level)
    1.35 -        if maxBytes:
    1.36 -            self.maxBytes = maxBytes
    1.37 -        if backupCount:
    1.38 -            self.backupCount = backupCount
    1.39 -        self.initLogFile(filename)
    1.40 -        self.initLogStderr()
    1.41 -
    1.42 -    def setLevel(self, level):
    1.43 -        if isinstance(level, types.StringType):
    1.44 -            level = logging._levelNames[level]
    1.45 -        self.getLogger().setLevel(level)
    1.46 -        self.level = level
    1.47  
    1.48 -    def getLogger(self):
    1.49 -        return logging.getLogger("xend")
    1.50 -
    1.51 -    def initLogFile(self, filename):
    1.52 -        """Create the file logger and add it.
    1.53 -        """
    1.54 -        self.logfile = RotatingFileHandler(filename,
    1.55 -                                           mode='a',
    1.56 -                                           maxBytes=self.maxBytes,
    1.57 -                                           backupCount=self.backupCount)
    1.58 -        self.logfilename = filename
    1.59 -        self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
    1.60 -        self.getLogger().addHandler(self.logfile)
    1.61 -
    1.62 -    def getLogFile(self):
    1.63 -        return self.logfile
    1.64 +__all__ = [ 'log', 'init', 'getLogFilename', 'addLogStderr',
    1.65 +            'removeLogStderr' ]
    1.66  
    1.67 -    def getLogFilename(self):
    1.68 -        return self.logfilename
    1.69 -
    1.70 -    def initLogStderr(self):
    1.71 -        """Create the stderr logger, but don't add it.
    1.72 -        """
    1.73 -        self.logstderr = StreamHandler()
    1.74 -        self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
    1.75 -
    1.76 -    def addLogStderr(self):
    1.77 -        """Add logging to stderr."""
    1.78 -        self.getLogger().addHandler(self.logstderr)
    1.79 -
    1.80 -    def removeLogStderr(self):
    1.81 -        """Remove logging to stderr."""
    1.82 -        self.getLogger().removeHandler(self.logstderr)
    1.83 -        
    1.84 -    def getLogStderr(self):
    1.85 -        return self.logstderr
    1.86  
    1.87  log = logging.getLogger("xend")
    1.88 -    
    1.89 +
    1.90 +
    1.91 +DEFAULT_MAX_BYTES = 1 << 20  # 1MB
    1.92 +DEFAULT_BACKUP_COUNT = 5
    1.93 +
    1.94 +STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
    1.95 +LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
    1.96 +DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
    1.97 +
    1.98 +
    1.99 +stderrHandler = logging.StreamHandler()
   1.100 +stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT, DATE_FORMAT))
   1.101 +
   1.102 +logfilename = None
   1.103 +
   1.104 +
   1.105 +def init(filename, level=logging.INFO, maxBytes=None, backupCount=None):
   1.106 +    """Initialise logging. Logs to 'filename' by default, but does not log to
   1.107 +    stderr unless addLogStderr() is called.
   1.108 +    """
   1.109 +
   1.110 +    def openFileHandler(fname):
   1.111 +        return logging.handlers.RotatingFileHandler(fname,
   1.112 +                                                    mode='a',
   1.113 +                                                    maxBytes=maxBytes,
   1.114 +                                                    backupCount=backupCount)
   1.115 +
   1.116 +    if not maxBytes:
   1.117 +        maxBytes = DEFAULT_MAX_BYTES
   1.118 +    if not backupCount:
   1.119 +        backupCount = DEFAULT_BACKUP_COUNT
   1.120 +
   1.121 +    # Rather unintuitively, getLevelName will get the number corresponding to
   1.122 +    # a level name, as well as getting the name corresponding to a level
   1.123 +    # number.  setLevel seems to take the number only though, so convert if we
   1.124 +    # are given a string.
   1.125 +    if isinstance(level, types.StringType):
   1.126 +        level = logging.getLevelName(level)
   1.127 +
   1.128 +    log.setLevel(level)
   1.129 +
   1.130 +    try:
   1.131 +        fileHandler = openFileHandler(filename)
   1.132 +        logfilename = filename
   1.133 +    except IOError:
   1.134 +        logfilename = tempfile.mkstemp("-xend.log")[1]
   1.135 +        fileHandler = openFileHandler(logfilename)
   1.136 +
   1.137 +    fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT))
   1.138 +    log.addHandler(fileHandler)
   1.139 +
   1.140 +
   1.141 +def getLogFilename():
   1.142 +    return logfilename
   1.143 +
   1.144 +
   1.145 +def addLogStderr():
   1.146 +    """Add logging to stderr."""
   1.147 +    log.addHandler(stderrHandler)
   1.148 +
   1.149 +
   1.150 +def removeLogStderr():
   1.151 +    """Remove logging to stderr."""
   1.152 +    log.removeHandler(stderrHandler)
     2.1 --- a/tools/python/xen/xend/XendRoot.py	Mon Oct 10 14:46:53 2005 +0100
     2.2 +++ b/tools/python/xen/xend/XendRoot.py	Mon Oct 10 16:15:48 2005 +0100
     2.3 @@ -13,6 +13,7 @@
     2.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     2.5  #============================================================================
     2.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
     2.7 +# Copyright (C) 2005 XenSource Ltd
     2.8  #============================================================================
     2.9  
    2.10  """Xend root class.
    2.11 @@ -29,7 +30,7 @@ import os.path
    2.12  import string
    2.13  import sys
    2.14  
    2.15 -from XendLogging import XendLogging
    2.16 +import XendLogging
    2.17  from XendError import XendError
    2.18  
    2.19  import sxp
    2.20 @@ -92,7 +93,6 @@ class XendRoot:
    2.21      def __init__(self):
    2.22          self.config_path = None
    2.23          self.config = None
    2.24 -        self.logging = None
    2.25          self.configure()
    2.26  
    2.27  
    2.28 @@ -114,84 +114,22 @@ class XendRoot:
    2.29          """
    2.30          return self.components.get(name)
    2.31  
    2.32 -    def _format(self, msg, args):
    2.33 -        if args:
    2.34 -            return str(msg) % args
    2.35 -        else:
    2.36 -            return str(msg)
    2.37 -
    2.38 -    def _log(self, mode, fmt, args):
    2.39 -        """Logging function that uses the logger if it exists, otherwise
    2.40 -        logs to stderr. We use this for XendRoot log messages because
    2.41 -        they may be logged before the logger has been configured.
    2.42 -        Other components can safely use the logger.
    2.43 -        """
    2.44 -        log = self.get_logger()
    2.45 -        if mode not in ['warning', 'info', 'debug', 'error']:
    2.46 -            mode = 'info'
    2.47 -        level = mode.upper()
    2.48 -        if log:
    2.49 -            getattr(log, mode)(fmt, *args)
    2.50 -        else:
    2.51 -            print >>sys.stderr, "xend", "[%s]" % level, self._format(fmt, args)
    2.52 -
    2.53 -    def logDebug(self, fmt, *args):
    2.54 -        """Log a debug message.
    2.55 -
    2.56 -        @param fmt: message format
    2.57 -        @param args: arguments
    2.58 +    def _logError(self, fmt, args):
    2.59 +        """Logging function to log to stderr. We use this for XendRoot log
    2.60 +        messages because they may be logged before the logger has been
    2.61 +        configured.  Other components can safely use the logger.
    2.62          """
    2.63 -        self._log('debug', fmt, args)
    2.64 -        
    2.65 -    def logInfo(self, fmt, *args):
    2.66 -        """Log an info message.
    2.67 -
    2.68 -        @param fmt: message format
    2.69 -        @param args: arguments
    2.70 -        """
    2.71 -        self._log('info', fmt, args)
    2.72 -
    2.73 -    def logWarning(self, fmt, *args):
    2.74 -        """Log a warning message.
    2.75 -
    2.76 -        @param fmt: message format
    2.77 -        @param args: arguments
    2.78 -        """
    2.79 -        self._log('warning', fmt, args)
    2.80 -        
    2.81 -    def logError(self, fmt, *args):
    2.82 -        """Log an error message.
    2.83 -
    2.84 -        @param fmt: message format
    2.85 -        @param args: arguments
    2.86 -        """
    2.87 -        self._log('error', fmt, args)
    2.88 -        
    2.89 -    def event_handler(self, event, val):
    2.90 -        self.logInfo("EVENT> %s %s", str(event), str(val))
    2.91 +        print >>sys.stderr, "xend [ERROR]", fmt % args
    2.92  
    2.93      def configure(self):
    2.94          self.set_config()
    2.95 -        self.configure_logger()
    2.96 -
    2.97 -    def configure_logger(self):
    2.98          logfile = self.get_config_value("logfile", self.logfile_default)
    2.99          loglevel = self.get_config_value("loglevel", self.loglevel_default)
   2.100 -        self.logging = XendLogging(logfile, level=loglevel)
   2.101 +        XendLogging.init(logfile, level = loglevel)
   2.102  
   2.103          from xen.xend.server import params
   2.104          if params.XEND_DEBUG:
   2.105 -            self.logging.addLogStderr()
   2.106 -
   2.107 -    def get_logging(self):
   2.108 -        """Get the XendLogging instance.
   2.109 -        """
   2.110 -        return self.logging
   2.111 -
   2.112 -    def get_logger(self):
   2.113 -        """Get the logger.
   2.114 -        """
   2.115 -        return self.logging and self.logging.getLogger()
   2.116 +            XendLogging.addLogStderr()
   2.117  
   2.118      def set_config(self):
   2.119          """If the config file exists, read it. If not, ignore it.
   2.120 @@ -200,7 +138,6 @@ class XendRoot:
   2.121          """
   2.122          self.config_path = os.getenv(self.config_var, self.config_default)
   2.123          if os.path.exists(self.config_path):
   2.124 -            #self.logInfo('Reading config file %s', self.config_path)
   2.125              try:
   2.126                  fin = file(self.config_path, 'rb')
   2.127                  try:
   2.128 @@ -210,10 +147,12 @@ class XendRoot:
   2.129                  config.insert(0, 'xend-config')
   2.130                  self.config = config
   2.131              except Exception, ex:
   2.132 -                self.logError('Reading config file %s: %s', self.config_path, str(ex))
   2.133 +                self._logError('Reading config file %s: %s',
   2.134 +                               self.config_path, str(ex))
   2.135                  raise
   2.136          else:
   2.137 -            self.logError('Config file does not exist: %s', self.config_path)
   2.138 +            self._logError('Config file does not exist: %s',
   2.139 +                           self.config_path)
   2.140              self.config = ['xend-config']
   2.141  
   2.142      def get_config(self, name=None):
   2.143 @@ -339,11 +278,6 @@ def instance():
   2.144          inst = XendRoot()
   2.145      return inst
   2.146  
   2.147 -def logger():
   2.148 -    """Get the logger.
   2.149 -    """
   2.150 -    return instance().get_logger()
   2.151 -
   2.152  def add_component(name, val):
   2.153      """Register a component with XendRoot.
   2.154      This is used to work-round import cycles.
     3.1 --- a/tools/python/xen/xend/server/SrvXendLog.py	Mon Oct 10 14:46:53 2005 +0100
     3.2 +++ b/tools/python/xen/xend/server/SrvXendLog.py	Mon Oct 10 16:15:48 2005 +0100
     3.3 @@ -13,11 +13,12 @@
     3.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     3.5  #============================================================================
     3.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
     3.7 +# Copyright (C) 2005 XenSource Ltd
     3.8  #============================================================================
     3.9  
    3.10  from xen.web import static
    3.11  
    3.12 -from xen.xend import XendRoot
    3.13 +from xen.xend import XendLogging
    3.14  
    3.15  from xen.web.SrvDir import SrvDir
    3.16  
    3.17 @@ -27,8 +28,8 @@ class SrvXendLog(SrvDir):
    3.18  
    3.19      def __init__(self):
    3.20          SrvDir.__init__(self)
    3.21 -        logging = XendRoot.instance().get_logging()
    3.22 -        self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
    3.23 +        self.logfile = static.File(XendLogging.getLogFilename(),
    3.24 +                                   defaultType="text/plain")
    3.25          self.logfile.type = "text/plain"
    3.26          self.logfile.encoding = None
    3.27  
     4.1 --- a/tools/python/xen/xend/server/event.py	Mon Oct 10 14:46:53 2005 +0100
     4.2 +++ b/tools/python/xen/xend/server/event.py	Mon Oct 10 16:15:48 2005 +0100
     4.3 @@ -25,6 +25,7 @@ from xen.xend import scheduler
     4.4  from xen.xend import sxp
     4.5  from xen.xend import PrettyPrint
     4.6  from xen.xend.XendError import XendError
     4.7 +from xen.xend import XendLogging
     4.8  from xen.xend import XendRoot
     4.9  
    4.10  
    4.11 @@ -146,11 +147,10 @@ class EventProtocol(protocol.Protocol):
    4.12  
    4.13      def op_log_stderr(self, _, v):
    4.14          mode = v[1]
    4.15 -        logging = xroot.get_logging()
    4.16          if mode == 'on':
    4.17 -            logging.addLogStderr()
    4.18 +            XendLogging.addLogStderr()
    4.19          else:
    4.20 -            logging.removeLogStderr()
    4.21 +            XendLogging.removeLogStderr()
    4.22  
    4.23      def op_domain_ls(self, _1, _2):
    4.24          xd = xroot.get_component("xen.xend.XendDomain")