155 lines
4.5 KiB
Python
155 lines
4.5 KiB
Python
# vi: ts=4 expandtab
|
|
#
|
|
# Copyright (C) 2012 Canonical Ltd.
|
|
# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
|
|
# Copyright (C) 2012 Yahoo! Inc.
|
|
#
|
|
# Author: Scott Moser <scott.moser@canonical.com>
|
|
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
|
|
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 3, as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import logging
|
|
import logging.config
|
|
import logging.handlers
|
|
|
|
import collections
|
|
import os
|
|
import sys
|
|
|
|
from StringIO import StringIO
|
|
|
|
# Logging levels for easy access
|
|
CRITICAL = logging.CRITICAL
|
|
FATAL = logging.FATAL
|
|
ERROR = logging.ERROR
|
|
WARNING = logging.WARNING
|
|
WARN = logging.WARN
|
|
INFO = logging.INFO
|
|
DEBUG = logging.DEBUG
|
|
NOTSET = logging.NOTSET
|
|
|
|
# Default basic format
|
|
DEF_CON_FORMAT = '%(asctime)s - %(filename)s[%(levelname)s]: %(message)s'
|
|
|
|
|
|
def setupBasicLogging(level=DEBUG):
|
|
root = logging.getLogger()
|
|
console = logging.StreamHandler(sys.stderr)
|
|
console.setFormatter(logging.Formatter(DEF_CON_FORMAT))
|
|
console.setLevel(level)
|
|
root.addHandler(console)
|
|
root.setLevel(level)
|
|
|
|
|
|
def flushLoggers(root):
|
|
if not root:
|
|
return
|
|
for h in root.handlers:
|
|
if isinstance(h, (logging.StreamHandler)):
|
|
try:
|
|
h.flush()
|
|
except IOError:
|
|
pass
|
|
flushLoggers(root.parent)
|
|
|
|
|
|
def setupLogging(cfg=None):
|
|
# See if the config provides any logging conf...
|
|
if not cfg:
|
|
cfg = {}
|
|
|
|
log_cfgs = []
|
|
log_cfg = cfg.get('logcfg')
|
|
if log_cfg and isinstance(log_cfg, (str, basestring)):
|
|
# If there is a 'logcfg' entry in the config,
|
|
# respect it, it is the old keyname
|
|
log_cfgs.append(str(log_cfg))
|
|
elif "log_cfgs" in cfg:
|
|
for a_cfg in cfg['log_cfgs']:
|
|
if isinstance(a_cfg, (basestring, str)):
|
|
log_cfgs.append(a_cfg)
|
|
elif isinstance(a_cfg, (collections.Iterable)):
|
|
cfg_str = [str(c) for c in a_cfg]
|
|
log_cfgs.append('\n'.join(cfg_str))
|
|
else:
|
|
log_cfgs.append(str(a_cfg))
|
|
|
|
# See if any of them actually load...
|
|
am_tried = 0
|
|
for log_cfg in log_cfgs:
|
|
try:
|
|
am_tried += 1
|
|
# Assume its just a string if not a filename
|
|
if log_cfg.startswith("/") and os.path.isfile(log_cfg):
|
|
# Leave it as a file and do not make it look like
|
|
# something that is a file (but is really a buffer that
|
|
# is acting as a file)
|
|
pass
|
|
else:
|
|
log_cfg = StringIO(log_cfg)
|
|
# Attempt to load its config
|
|
logging.config.fileConfig(log_cfg)
|
|
# The first one to work wins!
|
|
return
|
|
except Exception:
|
|
# We do not write any logs of this here, because the default
|
|
# configuration includes an attempt at using /dev/log, followed
|
|
# up by writing to a file. /dev/log will not exist in very early
|
|
# boot, so an exception on that is expected.
|
|
pass
|
|
|
|
# If it didn't work, at least setup a basic logger (if desired)
|
|
basic_enabled = cfg.get('log_basic', True)
|
|
|
|
sys.stderr.write(("WARN: no logging configured!"
|
|
" (tried %s configs)\n") % (am_tried))
|
|
if basic_enabled:
|
|
sys.stderr.write("Setting up basic logging...\n")
|
|
setupBasicLogging()
|
|
|
|
|
|
def getLogger(name='cloudinit'):
|
|
return logging.getLogger(name)
|
|
|
|
|
|
# Fixes this annoyance...
|
|
# No handlers could be found for logger XXX annoying output...
|
|
try:
|
|
from logging import NullHandler
|
|
except ImportError:
|
|
class NullHandler(logging.Handler):
|
|
def emit(self, record):
|
|
pass
|
|
|
|
|
|
def _resetLogger(log):
|
|
if not log:
|
|
return
|
|
handlers = list(log.handlers)
|
|
for h in handlers:
|
|
h.flush()
|
|
h.close()
|
|
log.removeHandler(h)
|
|
log.setLevel(NOTSET)
|
|
log.addHandler(NullHandler())
|
|
|
|
|
|
def resetLogging():
|
|
_resetLogger(logging.getLogger())
|
|
_resetLogger(getLogger())
|
|
|
|
|
|
resetLogging()
|