Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • DM/dm-docs
  • hammonds/dm-docs
  • hparraga/dm-docs
3 results
Show changes
Showing
with 784 additions and 0 deletions
#!/usr/bin/env python
#
# Console logging handler class
#
#######################################################################
import socket
import pwd
import os
from logging import StreamHandler
#######################################################################
class ConsoleLoggingHandler(StreamHandler):
""" Class that enables console logging. """
def __init__(self, *args):
StreamHandler.__init__(self, *args)
self._user = pwd.getpwuid(os.getuid())[0]
self._host = socket.gethostname()
def emit(self, record):
record.__dict__['user'] = self._user
record.__dict__['host'] = self._host
return StreamHandler.emit(self, record)
#######################################################################
# Testing.
if __name__ == '__main__':
import sys
import logging
exec 'sh = ConsoleLoggingHandler(sys.stdout,)'
sh.setLevel(logging.INFO)
rootLogger = logging.getLogger('')
logging.basicConfig(level=logging.DEBUG)
mainLogger = logging.getLogger('main')
mainLogger.debug("main debug")
mainLogger.info("main info")
#!/usr/bin/env python
#
# Module manager class.
#
#######################################################################
import threading
#######################################################################
# Get singleton instance.
def getInstance():
from dm.common.utility.dmModuleManager import DmModuleManager
try:
mgr = DmModuleManager()
except DmModuleManager, ex:
mgr = ex
return mgr
class DmModuleManager:
""" Singleton class used for managing dm modules. """
# Singleton.
__instanceLock = threading.RLock()
__instance = None
def __init__(self):
DmModuleManager.__instanceLock.acquire()
try:
if DmModuleManager.__instance:
raise DmModuleManager.__instance
DmModuleManager.__instance = self
from dm.common.utility import loggingManager
self._logger = loggingManager.getLogger(self.__class__.__name__)
self._lock = threading.RLock()
self._moduleList = []
self._modulesRunning = False
finally:
DmModuleManager.__instanceLock.release()
def addModule(self, m):
self._lock.acquire()
try:
self._logger.debug('Adding dm module: %s' % m.__class__.__name__)
self._moduleList.append(m)
finally:
self._lock.release()
def startModules(self):
self._lock.acquire()
try:
if self._modulesRunning:
return
for m in self._moduleList:
self._logger.debug('Starting dm module: %s' % m.__class__.__name__)
m.start()
self._modulesRunning = True
finally:
self._lock.release()
def stopModules(self):
self._lock.acquire()
try:
if not self._modulesRunning:
return
n = len(self._moduleList)
for i in range(0, n):
m = self._moduleList[n-1-i]
self._logger.debug('Stopping dm module: %s' % m.__class__.__name__)
m.stop()
self._modulesRunning = False
finally:
self._lock.release()
#######################################################################
# Testing.
if __name__ == '__main__':
pass
#!/usr/bin/env python
#
# Subprocess class
#
#######################################################################
import os
import subprocess
import platform
from dm.common.utility import loggingManager
from dm.common.exceptions.commandFailed import CommandFailed
#######################################################################
class DmSubprocess(subprocess.Popen):
def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=None, close_fds=False, shell=True, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, useExceptions=True, quietMode=False):
""" Overrides Popen constructor with defaults more appropriate DM. """
subprocess.Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
self._logger = loggingManager.getLogger(self.__class__.__name__)
self._stdout = None
self._stderr = None
self._args = args
self._useExceptions = useExceptions
self._quietMode = quietMode
def _commandLog(self):
# Not very useful to show the name of this file.
# Walk up the stack to find the caller.
import traceback
stack = traceback.extract_stack()
for i in range(2, len(stack)):
if stack[-i][0] != stack[-1][0]:
fileName, lineNumber, functionName, text = stack[-i]
break
else:
fileName = lineNumber = functionName = text = '?'
self._logger.debug('From [%s:%s] Invoking: [%s]' % (os.path.basename(fileName), lineNumber, self._args))
def run(self, input=None):
""" Run subprocess. """
if not self._quietMode:
self._commandLog()
(self._stdout, self._stderr) = subprocess.Popen.communicate(self, input)
if not self._quietMode:
self._logger.debug('Exit status: %s' % self.returncode)
if self.returncode != 0 and self._useExceptions:
if not self._quietMode:
self._logger.debug('StdOut: %s' % self._stdout)
self._logger.debug('StdErr: %s' % self._stderr)
error = self._stderr.strip()
if error == '':
error = self._stdout.strip()
raise CommandFailed('%s' % (error))
return (self._stdout, self._stderr)
def getLogger(self):
return self._logger
def getArgs(self):
return self._args
def getStdOut(self):
return self._stdout
def getStdErr(self):
return self._stderr
def getExitStatus(self):
return self.returncode
# Convenience function for getting subprocess.
def getSubprocess(command):
if platform.system() != 'Windows':
close_fds = True
else:
close_fds = False
p = DmSubprocess(command, close_fds=close_fds)
return p
# Convenience function for executing command.
def executeCommand(command):
""" Create subprocess and run it, return subprocess object. """
p = getSubprocess(command)
p.run()
return p
# Convenience function for executing command that may fail, and we do not
# care about the failure.
def executeCommandAndIgnoreFailure(command):
""" Create subprocess, run it, igore any failures, and return subprocess object. """
p = getSubprocess(command)
try:
p.run()
except CommandFailed, ex:
p.getLogger().debug('Command failed, stdout: %s, stderr: %s' % (p.getStdOut(), p.getStdErr()))
return p
def executeCommandAndLogToStdOut(command):
""" Execute command, display output to stdout, maintain log file and return subprocess object. """
p = getSubprocess(command)
p._commandLog()
while True:
outp = p.stdout.readline()
if not outp:
break
print outp,
retval = p.wait()
p._logger.debug('Exit status: %s' % retval)
if retval != 0:
error = ''
while True:
err = p.stderr.readline()
if not err:
break
error += err
raise CommandFailed(error)
return p
#######################################################################
# Testing.
if __name__ == '__main__':
p = DmSubprocess('ls -l', useExceptions=False)
p.run()
print p.getStdOut()
print p.getStdErr()
print p.getExitStatus()
#!/usr/bin/env python
#
# Logging manager singleton.
#
#######################################################################
import re
import sys
import os.path
import logging
import ConfigParser
from dm.common.utility import configurationManager
from dm.common.exceptions.configurationError import ConfigurationError
#######################################################################
# Get singleton instance.
def getInstance():
from dm.common.utility.loggingManager import LoggingManager
try:
lm = LoggingManager()
except LoggingManager, ex:
lm = ex
return lm
def getLogger(name='defaultLogger'):
""" Convenience function to obtain logger. """
return getInstance().getLogger(name)
def setConsoleLogLevel(level):
""" Convenience function to set the console log level. """
return getInstance().setConsoleLogLevel(level)
def setFileLogLevel(level):
""" Convenience function to set the file log level. """
return getInstance().setFileLogLevel(level)
class LoggingManager:
"""
Configuration:
The log manager class is initialized via a configuration file
that may have the following sections:
ConsoleLogging # Used for output on the screen
FileLogging # Used for logging into a file
Each section in the configuration file should have the following
keys:
handler # Indicates which handler class to use
level # Indicates logging level
format # Indicates format for log messages
dateformat # Indicates date format used for log messages
Given below is an example of a valid configuration file:
[ConsoleLogging]
handler=ConsoleLoggingHandler(sys.stdout,)
level=info
format=[%(levelname)s] %(message)s
dateformat=%m/%d/%y %H:%M:%S
[FileLogging]
handler=TimedRotatingFileLoggingHandler('/tmp/dm.log')
level=debug
format=%(asctime)s,%(msecs)d [%(levelname)s] %(module)s:%(lineno)d %(user)s@%(host)s %(name)s (%(process)d): %(message)s
dateformat=%m/%d/%y %H:%M:%S
"""
# Singleton.
__instance = None
def __init__(self):
if LoggingManager.__instance:
raise LoggingManager.__instance
LoggingManager.__instance = self
self._consoleHandler = None
self._fileHandlerList = []
self._maxIntLevel = logging.CRITICAL
self._minIntLevel = logging.NOTSET
self._levelRegExList = []
self._logger = logging.getLogger(self.__class__.__name__)
self._initFlag = False
def setMinLogLevel(self, minLogLevel=logging.INFO):
self._minIntLevel = minLogLevel
def parseLevelRegEx(self, levelRegExList):
""" Parse a list of expressions of the form <regex>=<log-level>. """
lines = levelRegExList.split('\n')
for line in lines:
try:
# Use the right split so we can have '='s in the regex
(regex, level) = line.rsplit('=', 1)
pattern = re.compile(regex)
tuple = (pattern, logging.getLevelName(level.upper()))
self._levelRegExList.append(tuple)
except Exception, ex:
# Do not fail, but log an error.
self._logger.error('Parser error in log configuration file: %s' % line)
self._logger.exception(ex)
# Get Log Level based on a string representation
def getIntLogLevel(self, levelStr):
level = logging.getLevelName(levelStr)
# Level should be an integer
try:
return int(level)
except ValueError, ex:
raise ConfigurationError('"%s" is not valid log level' % levelStr)
# Configure log handlers.
def configureHandlers(self):
""" Configure log handlers from the config file. """
cm = configurationManager.getInstance()
configFile = cm.getLogConfigFile()
configSections = self.__getConfigSections(configFile)
# Console handler.
defaults = {
'level' : cm.getConsoleLogLevel(),
'format' : cm.getLogRecordFormat(),
'dateformat' : cm.getLogDateFormat(),
'handler' : 'ConsoleLoggingHandler(sys.stdout,)'
}
consoleHandler = self.__configureHandler(configFile, 'ConsoleLogging', defaults)
if consoleHandler != None:
self._consoleHandler = consoleHandler
# File logging. # Do not configure if log directory does
# not exist.
defaults['handler'] = None
defaults['level'] = cm.getFileLogLevel()
if not os.path.exists(configFile):
# No config file, we'll configure default.
defaultLogFile = cm.getLogFile()
defaultLogDir = os.path.dirname(defaultLogFile)
if os.path.exists(defaultLogDir):
handler = 'TimedRotatingFileLoggingHandler("%s")' % defaultLogFile
defaults['handler'] = handler
fileHandler = self.__configureHandler(configFile, 'FileLogging', defaults)
if fileHandler != None:
self._fileHandlerList.append(fileHandler)
else:
# Parse all file loggers present in the config file
for configSection in configSections:
if configSection.startswith('FileLogging'):
fileHandler = self.__configureHandler(configFile, configSection, defaults)
if fileHandler != None:
self._fileHandlerList.append(fileHandler)
# Add handlers to the root logger. Use logging class here
# to make sure we can have a logger when we parse the
# logger expressions
rootLogger = logging.getLogger('')
for handler in [self._consoleHandler] + self._fileHandlerList:
rootLogger.addHandler(handler)
# Get a logger factory based on our current config
self.configureLoggers(configFile, defaultLevel=cm.getFileLogLevel())
def configureLoggers(self, configFile, defaultLevel='error'):
configParser = ConfigParser.ConfigParser()
configParser.read(configFile)
rootLogLevel = 'error'
levelRegEx = '^.*$=%s' % (defaultLevel)
if configParser.has_section('LoggerLevels'):
rootLogLevel = configParser.get('LoggerLevels', 'root', rootLogLevel)
levelRegEx = configParser.get('LoggerLevels', 'levelregex', levelRegEx)
rootLevelInt = logging.getLevelName(rootLogLevel.upper())
logging.getLogger('').root.setLevel(rootLevelInt)
logging.getLogger('').debug('Set root logger to %s' % rootLevelInt)
if not levelRegEx:
return
# Parse expressions of the form <regex>=<log-level>. """
lines = levelRegEx.split('\n')
for line in lines:
try:
# Use the right split so we can have '='s in the regex
(regex, level) = line.rsplit('=', 1)
pattern = re.compile(regex)
tuple = (pattern, logging.getLevelName(level.upper()))
self._levelRegExList.append(tuple)
except Exception, ex:
# Do not fail
self._logger.error('Parser error in log configuration file: %s' % line)
self._logger.exception(ex)
def __getOptionFromConfigFile(self, configParser, configSection, key, defaultValue=None):
""" Get specified option from the configuration file. """
if configParser.has_section(configSection):
return configParser.get(configSection, key, True)
else:
return defaultValue
# Get the sections in the config file
def __getConfigSections(self, configFile):
""" Return a list of the sections in the given config file """
configParser = ConfigParser.RawConfigParser()
configParser.read(configFile)
return configParser.sections()
# Configure particular handler with given defaults.
def __configureHandler(self, configFile, configSection, defaults):
""" Configure specified handler with a given defaults. """
configParser = ConfigParser.ConfigParser(defaults)
configParser.read(configFile)
handlerOption = defaults['handler']
try:
handlerOption = configParser.get(configSection, 'handler', True)
except Exception, ex:
pass
# If handlerOption is empty, handler cannot be instantiated.
handler = None
if handlerOption != None:
# Handler argument format: MyHandler(arg1, arg2, ...)
# Module will be in lowercase letters, but the class
# should be capitalized.
handlerName = re.sub('\(.*', '', handlerOption)
moduleName = handlerName[0].lower() + handlerName[1:]
try:
exec 'from dm.common.utility import %s' % (moduleName)
exec '_handler = %s.%s' % (moduleName, handlerOption)
except IOError, ex:
errno, _emsg = ex
import errno
# If the exception raised is an I/O permissions error, ignore
# it and disable this log handler. This allows non-root users
# to use the (system-wide) default log configuration
if _errno != errno.EACCES:
raise
_handler = None
except Exception, ex:
raise ConfigurationError(exception=ex)
# Only request setting from the config file if it was
# not set via environment variable, or programmatically.
if _handler != None:
try:
_level = self.__getOptionFromConfigFile(configParser,
configSection, 'level', defaults['level'])
intLevel = self.getIntLogLevel(_level.upper())
_handler.setLevel(intLevel)
_format = self.__getOptionFromConfigFile(configParser, configSection, 'format', defaults['format'])
_dateformat = self.__getOptionFromConfigFile(configParser, configSection, 'dateformat', defaults['dateformat'])
_handler.setFormatter(logging.Formatter(_format, _dateformat))
except Exception, ex:
raise ConfigurationError(exception=ex)
# Look to see if there is a filter to apply to the handler
filter = None
try:
filter = configParser.get(configSection, 'filter')
except Exception, ex:
pass
if filter:
_handler.addFilter(logging.Filter(filter))
return _handler
def getLogger(self, name='defaultLogger'):
if not self._initFlag:
self._initFlag = True
self.configureHandlers()
logger = logging.getLogger(name)
logger.setLevel(self.getLevel(name))
return logger
def getLevel(self, name):
# Match from the known regex list.
level = logging.NOTSET
# The last regex is most important.
for e in reversed(self._levelRegExList):
(pattern, level) = e
# If we return not None it is a match
if not None == pattern.match(name):
break
if level > self._maxIntLevel:
level = self._maxIntLevel
if level < self._minIntLevel:
level = self._minIntLevel
return level
def setConsoleLogLevel(self, level):
try:
# We need to override the logger levels and the handler
intLevel = self.getIntLogLevel(level.upper())
self._consoleHandler.setLevel(intLevel)
self._maxIntLevel = intLevel
self._logger.setLevel(intLevel)
except Exception, ex:
raise ConfigurationError(exception=ex)
def setFileLogLevel(self, level):
try:
# We need to override the logger levels and the handler
intLevel = self.getIntLogLevel(level.upper())
for handler in self._fileHandlerList:
handler.setLevel(intLevel)
self._maxIntLevel = intLevel
self._logger.setLevel(intLevel)
except Exception, ex:
raise ConfigurationError(exception=ex)
#######################################################################
# Testing.
if __name__ == '__main__':
lm = getInstance()
logger = lm.getLogger('Main')
logger.info('Info In Main')
logger = lm.getLogger('Main')
logger.info('Info In Main 2')
logger = lm.getLogger('')
logger.info('Info using root logger')
logger = lm.getLogger('Main.2')
logger.info('Info in Main.2')
logger.debug('You should not see this message')
lm.setConsoleLogLevel('debug')
logger.debug('Debug in Main.2')
#!/usr/bin/env python
#######################################################################
import socket
import pwd
import os
from logging.handlers import TimedRotatingFileHandler
#######################################################################
class TimedRotatingFileLoggingHandler(TimedRotatingFileHandler):
""" Class that enables logging into files. """
def __init__(self, filename, when='D', interval=1, backupCount=0, encoding=None):
TimedRotatingFileHandler.__init__(self, filename, when, interval, backupCount, encoding)
self._user = pwd.getpwuid(os.getuid())[0]
self._host = socket.gethostname()
def emit(self, record):
record.__dict__['user'] = self._user
record.__dict__['host'] = self._host
return TimedRotatingFileHandler.emit(self, record)
#######################################################################
# Testing.
if __name__ == '__main__':
pass
#!/usr/bin/env python
#
# Implementation for file system controller.
#
#######################################################################
import threading
from dm.common.objects.dmObject import DmObject
from dm.common.objects.dmObjectManager import DmObjectManager
from dm.common.utility.dmSubprocess import DmSubprocess
#######################################################################
class FsControllerImpl(DmObjectManager):
""" FS controller implementation class. """
def __init__(self):
DmObjectManager.__init__(self)
def getDirectoryList(self, path):
p = DmSubprocess('ls -l %s' % path)
p.run()
return DmObject({'path' : path, 'directoryList' : p.getStdOut()})
#!/usr/bin/env python
#######################################################################
import cherrypy
from dm.common.service.dmController import DmController
from dm.common.objects.dmObject import DmObject
from dm.common.exceptions.dmException import DmException
from dm.common.exceptions.internalError import InternalError
from dm.common.exceptions.invalidRequest import InvalidRequest
from dm.fs_service.impl.fsControllerImpl import FsControllerImpl
#######################################################################
class FsController(DmController):
def __init__(self):
DmController.__init__(self)
self._fsControllerImpl = FsControllerImpl()
@cherrypy.expose
def getDirectoryList(self, **kwargs):
try:
if not kwargs.has_key('path'):
raise InvalidRequest('Missing directory path.')
path = kwargs.get('path')
response = '%s' % self._fsControllerImpl.getDirectoryList(path).getJsonRep()
self.getLogger().debug('Returning: %s' % response)
except DmException, ex:
self.getLogger().error('%s' % ex)
self.handleException(ex)
response = ex.getJsonRep()
except Exception, ex:
self.getLogger().error('%s' % ex)
self.handleException(ex)
response = InternalError(ex).getJsonRep()
return self.formatJsonResponse(response)
#!/usr/bin/env python
#
# File system controller service
#
####################################################################
from dm.common.service.dmRestWebService import DmRestWebService
from dm.common.utility import dmModuleManager
from dm.fs_service.service import fsServiceRouteMapper
####################################################################
class FsService(DmRestWebService):
def __init__(self):
DmRestWebService.__init__(self, fsServiceRouteMapper)
def initDmModules(self):
self._logger.debug('Initializing dm modules')
# Add modules that will be started.
moduleManager = dmModuleManager.getInstance()
self._logger.debug('Initialized dm modules')
####################################################################
# Run service
if __name__ == '__main__':
service = FsService();
service.run()
#!/usr/bin/env python
#
# Route mapper for file system service.
#
#######################################################################
import sys
import os
import cherrypy
from dm.common.utility import loggingManager
from dm.fs_service.service.fsController import FsController
#######################################################################
def setupRoutes():
""" Setup RESTFul routes. """
# Static instances shared between different routes
fsController = FsController()
# Define routes.
# Make sure to have leading '/' for consistency.
routes = [
# ('GET') routes do not require authorization.
# ('PUT', 'POST', 'DELETE') routes require authorization.
#
# FS Controller routes
#
# Get directory listing
{
'name' : 'getDirectoryList',
'path' : '/directory/list',
'controller' : fsController,
'action' : 'getDirectoryList',
'method' : ['GET']
},
]
# Add routes to dispatcher.
d = cherrypy.dispatch.RoutesDispatcher()
logger = loggingManager.getLogger('setupRoutes')
for route in routes:
logger.debug('Connecting route: %s' % route)
d.connect(route['name'], route['path'], action=route['action'], controller=route['controller'], conditions=dict(method=route['method']))
return d
all:
for d in $(SUBDIRS); do $(MAKE) -C $$d $(ARCH); done
dist:
for d in $(SUBDIRS); do $(MAKE) -C $$d $(ARCH); done
clean:
for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done
distclean:
for d in $(SUBDIRS); do $(MAKE) -C $$d distclean; done
for d in $(SUBDIRS); do rm -f `find $$d -name 'RELEASE.local'`; done
tidy: distclean