diff --git a/src/python/dm/__init__.py b/src/python/dm/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..64fb7c078e180aba8caf527978f382a31d614730
--- /dev/null
+++ b/src/python/dm/__init__.py
@@ -0,0 +1 @@
+__version__ = "Development Snapshot (2015.03.31)"
diff --git a/src/python/dm/common/api/__init__.py b/src/python/dm/common/api/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/python/dm/common/api/dmApi.py b/src/python/dm/common/api/dmApi.py
new file mode 100755
index 0000000000000000000000000000000000000000..4c6f46212e8a0a049da43b91a0fc666232b4d87f
--- /dev/null
+++ b/src/python/dm/common/api/dmApi.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+import json
+from dm.common.exceptions.dmException import DmException
+from dm.common.utility.loggingManager import LoggingManager
+
+class DmApi(object):
+    """ Base dm api class. """
+    def __init__(self, username = None, password = None):
+        self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
+
+    @classmethod
+    def getLogger(cls):
+        logger = LoggingManager.getInstance().getLogger(cls.__name__)
+        return logger
+
+    @classmethod
+    def toDmObjectList(cls, dictList, dmObjectClass):
+        dmObjectList = []
+        for dict in dictList:
+            dmObjectList.append(dmObjectClass(dict))
+        return dmObjectList 
+
+    # Exception decorator for all api calls
+    @classmethod
+    def execute(cls, func):
+        def decorate(*args, **kwargs):
+            try:
+                response = func(*args, **kwargs)
+                return response
+            except DmException, ex:
+                raise
+            except Exception, ex:
+                cls.getLogger().exception('%s' % ex)
+                raise DmException(exception=ex)
+        return decorate
diff --git a/src/python/dm/common/api/dmRestApi.py b/src/python/dm/common/api/dmRestApi.py
new file mode 100755
index 0000000000000000000000000000000000000000..0c8e18c67fc7dcd9d7b66432dbf019294b4fc6ed
--- /dev/null
+++ b/src/python/dm/common/api/dmRestApi.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+import socket
+import json
+
+from dm.common.utility.loggingManager import LoggingManager
+from dm.common.client.sessionManager import SessionManager
+from dm.common.utility.configurationManager import ConfigurationManager 
+from dm.common.exceptions.authorizationError import AuthorizationError
+from dm.common.api.dmApi import DmApi
+
+class DmRestApi(DmApi):
+    """ Base dm REST api class. """
+
+    def __init__(self, username=None, password=None, host=None, port=None, protocol=None):
+        DmApi.__init__(self)
+        self.configurationManager = ConfigurationManager.getInstance()
+        if username == None and password == None:
+            username = self.configurationManager.getServiceUsername()
+            password = self.configurationManager.getServicePassword()
+        if host == None:
+            host = self.configurationManager.getServiceHost()
+        if port == None:
+            port = self.configurationManager.getServicePort()
+        if protocol == None:
+            protocol = self.configurationManager.getServiceProtocol()
+        self.username = username
+        self.password = password
+        self.host = host
+        self.port = port
+        self.protocol = protocol
+        self.sessionManager = None
+
+    @classmethod
+    def toJson(cls, o):
+        return json.dumps(o)
+
+    @classmethod
+    def fromJson(cls, s):
+        return json.loads(s)
+
+    def __getWebServiceUrl(self, url):
+        if url.find('://') < 0:
+            return '%s://%s:%s' % (self.protocol, socket.gethostbyname(self.host), self.port)
+
+        # Break the URL down into component pieces
+        from urlparse import urlparse
+        o = urlparse(url)
+        wsUrl = '%s://%s' % (o[0], o[1])
+        return wsUrl
+
+    def getContextRoot(self):
+        return self.configurationManager.getContextRoot()
+
+    def setUsername(self, username):
+        self.username = username
+
+    def getUsername(self):
+        return self.username
+
+    def setPassword(self, password):
+        self.password = password
+
+    def getPassword(self):
+        return self.password
+
+    def setHost(self, host):
+        self.host = host
+
+    def getHost(self):
+        return self.host
+
+    def setPort(self, port):
+        self.port = port
+
+    def getPort(self):
+        return self.port
+
+    def setProtocol(self, protocol):
+        self.protocol = protocol
+
+    def getProtocol(self):
+        return self.protocol
+
+    def getSessionManager(self):
+        if not self.sessionManager:
+            self.sessionManager = SessionManager()
+        return self.sessionManager
+
+    def getConfigManager(self):
+        return self.configurationManager
+
+    def sendSessionRequest(self, url, method, contentType='html', data={}):
+        """ Send authorized session request. """
+        sm = self.getSessionManager()
+        if not sm.hasSession():
+            if self.username == None:
+                raise AuthorizationError('Username not supplied.')
+            if self.password == None:
+                raise AuthorizationError('Password not supplied.')
+            wsUrl = self.__getWebServiceUrl(url)
+            # establishSession() sets the 'wsUrl' so the explicit call
+            # to setHost() is not required
+            sm.establishSession(wsUrl, self.username, self.password)
+        (response, responseData) = sm.sendSessionRequest(url, method, contentType, data)
+        return json.loads(responseData)
+
+    def sendRequest(self, url, method, contentType='html', data={}):
+        """ Send non-authorized request. """
+        sm = self.getSessionManager()
+        # Because there's no call to establishSession(), explicitly call
+        # setHost()
+        sm.setHost(self.__getWebServiceUrl(url))
+        (response, responseData) = self.getSessionManager().sendRequest(url, method, contentType, data)
+        return json.loads(responseData)
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    api = DmRestApi('sveseli', 'sveseli')
+    #api.sendRequest('https://zagreb.svdev.net:10232/dm/directory/list', 'GET', data='')
+    import urllib
+    from dm.common.utility.configurationManager import ConfigurationManager
+    cm = ConfigurationManager.getInstance()
+    cm.setSessionCacheFile('/tmp/session')
+    #print 'Non-session request'
+    #print api.sendRequest('https://zagreb.svdev.net:10232/dm/directory/list?path=/tmp', 'GET')
+    print 'Session request'
+    data = { 'path' : '/tmp/xyz' }
+    #print api.sendSessionRequest('https://zagreb.svdev.net:10232/dm/file/write?path=/tmp/xyz&content=xyz', 'POST', contentType='application/x-www-form-urlencoded', data=urllib.urlencode(data))
+    #print api.sendSessionRequest('https://zagreb.svdev.net:10232/dm/file/write', 'POST', data=data)
+    postdata='path=/tmp/xyz'
+    postdata+='&content=%s' % urllib.quote_plus('Hey there')
+    print api.sendSessionRequest('https://zagreb.svdev.net:10232/dm/file/write', 'POST', contentType='application/x-www-form-urlencoded', data=postdata)
+
+
+
diff --git a/src/python/dm/common/cli/__init__.py b/src/python/dm/common/cli/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/python/dm/common/cli/dmCli.py b/src/python/dm/common/cli/dmCli.py
new file mode 100755
index 0000000000000000000000000000000000000000..03927efff5527d050a15f2152ff3e35cb15f1410
--- /dev/null
+++ b/src/python/dm/common/cli/dmCli.py
@@ -0,0 +1,293 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import os.path
+import stat
+from optparse import OptionGroup
+
+import dm
+from dm.common.utility.loggingManager import LoggingManager
+from dm.common.utility.configurationManager import ConfigurationManager
+from dm.common.utility.osUtility import OsUtility
+from dm.common.objects.dmObject import DmObject
+from dm.common.exceptions.dmException import DmException
+from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.invalidArgument import InvalidArgument
+from dm.common.exceptions.internalError import InternalError
+from dm.common.cli.dmOptionParser import DmOptionParser
+from dm.common.constants import dmStatus
+
+class DmCli(object):
+    """ Base dm command line interface class. """
+    DEFAULT_SESSION_CACHE_FILE = OsUtility.getUserHomeDir() + '/.dm/.session.cache'
+    def __init__(self, validArgCount=0):
+        self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
+        # Do not log into a file for CLIs
+        LoggingManager.getInstance().setFileLogLevel('CRITICAL') 
+        LoggingManager.getInstance().setConsoleLogLevel('CRITICAL') 
+        self.parser = DmOptionParser()
+        self.options = {}
+        self.args = []
+        self.validArgCount = validArgCount
+        self.serviceHost = None
+        self.servicePort = None
+        self.optionGroupDict = {}
+
+        commonGroup = 'Common Options'
+        self.addOptionGroup(commonGroup, None)
+        self.addOptionToGroup(commonGroup, '-h', '--help', action='help', help='Show this help message and exit.')
+        self.addOptionToGroup(commonGroup, '-?', '',       action='help', help='Show this help message and exit.')
+        self.addOptionToGroup(commonGroup, '-v', '--version', action='store_true', dest='version', default=False, help='Print version and exit.')
+        self.addOptionToGroup(commonGroup, '-d', '--debug', dest='consoleLogLevel', help='Set debug level (valid values: CRITICAL, ERROR, WARNING, INFO, DEBUG). Console log level can also be set via DM_CONSOLE_LOG_LEVEL environment variable,')
+        self.addOptionToGroup(commonGroup, '', '--display-format', dest='displayFormat', default=DmObject.TEXT_DISPLAY_FORMAT, help='Display format for output objects. Possible options are: %s, %s, and %s (default: %s).' % (DmObject.TEXT_DISPLAY_FORMAT, DmObject.DICT_DISPLAY_FORMAT, DmObject.JSON_DISPLAY_FORMAT, DmObject.TEXT_DISPLAY_FORMAT)) 
+        self.addOptionToGroup(commonGroup, '', '--display-keys', dest='displayKeys', default=DmObject.DEFAULT_KEYS, help='List of output object keys to display. Possible options are: %s, %s, and string containing comma-separated keys (default: %s, represents class default keys).' % (DmObject.DEFAULT_KEYS, DmObject.ALL_KEYS, DmObject.DEFAULT_KEYS)) 
+
+        # These will be set via env variables
+        self.addOptionToGroup(commonGroup, '', '--service-host', dest='serviceHost', default=self.getDefaultServiceHost(), help='Service host (default: %s, can be set via DM_SERVICE_HOST environment variable).' % self.getDefaultServiceHost())
+        self.addOptionToGroup(commonGroup, '', '--service-port', dest='servicePort', default=self.getDefaultServicePort(), help='Service port (default: %s, can be set via DM_SERVICE_PORT environment variable).' % self.getDefaultServicePort())
+        self.addOptionToGroup(commonGroup, '', '--service-protocol', dest='serviceProtocol', default=self.getDefaultServiceProtocol(), help='Service protocol (default: %s, can be set via DM_SERVICE_PROTOCOL environment variable).' % self.getDefaultServiceProtocol())
+
+        # SSL options, disabled for now.
+        #self.addOptionToGroup(commonGroup, '', '--ssl-key', dest='sslKeyFile', help='SSL key file (needed if service requires peer verification, can be set via DM_SSL_KEY_FILE environment variable).')
+        #self.addOptionToGroup(commonGroup, '', '--ssl-cert', dest='sslCertFile', help='SSL certificate file (needed if service requires peer verification, can be set via DM_SSL_CERT_FILE environment variable).')
+        #self.addOptionToGroup(commonGroup, '', '--ssl-ca-cert', dest='sslCaCertFile', help='SSL CA certificate file (needed if client requires peer verification, can be set via DM_SSL_CA_CERT_FILE environment variable).')
+        
+    def getDefaultServiceHost(self):
+        return ConfigurationManager.getInstance().getServiceHost()
+
+    def getDefaultServicePort(self):
+        return ConfigurationManager.getInstance().getServicePort()
+
+    def getDefaultServiceProtocol(self):
+        return ConfigurationManager.getInstance().getServiceProtocol()
+
+    def getUsername(self):
+        return None
+
+    def getPassword(self):
+        return None
+
+    def getDisplayFormat(self):
+        return self.options.displayFormat
+
+    def getDisplayKeys(self):
+        return self.options.displayKeys
+
+    def getLogger(self):
+        return self.logger
+
+    def getParser(self):
+        return self.parser
+
+    def addOption(self, *args, **kwargs):
+        self.parser.add_option(*args, **kwargs)
+
+    def addOptionToGroup(self, groupName, *args, **kwargs):
+        """ Add group option. Group must be created using addOptionGroup(). """
+        group = self.optionGroupDict.get(groupName)
+        group.add_option(*args, **kwargs)
+
+    def addOptionGroup(self, groupName, desc):
+        group = OptionGroup(self.parser, groupName, desc)
+        self.parser.add_option_group(group)
+        self.optionGroupDict[groupName] = group
+
+    def processArgs(self):
+        pass
+
+    def parseArgs(self, usage=None):
+        if usage:
+            self.parser.usage = usage
+        try:
+            (self.options, self.args) = self.parser.parse_args()
+            self.processArgs()
+        except SystemExit, rc:
+            sys.stdout.flush()
+            sys.stderr.flush()
+            sys.exit(int(str(rc)))
+
+        if self.validArgCount < len(self.args):
+            # Positional args are not enabled and we have some
+            msg = 'Invalid positional argument(s):'
+            for arg in self.args[self.validArgCount:]:
+                msg += ' ' + arg
+            msg += ' (This command allows %s positional arguments.)' % self.validArgCount
+            raise InvalidArgument(msg)
+
+        optDict = self.options.__dict__
+        if optDict.get('version'):
+            print 'DM Software Version: %s' % (dm.__version__)
+            sys.exit(0)
+
+        # Logging level. First try from command line, then from env variable.
+        consoleLogLevel = optDict.get('consoleLogLevel', None)
+        if consoleLogLevel:
+            LoggingManager.getInstance().setConsoleLogLevel(consoleLogLevel)
+        else:
+            consoleLogLevel = ConfigurationManager.getInstance().getConsoleLogLevelFromEnvVar()
+            if consoleLogLevel:
+                LoggingManager.getInstance().setConsoleLogLevel(consoleLogLevel)
+
+        # Service host, port, etc.
+        configManager = ConfigurationManager.getInstance()
+        self.serviceHost = self.options.serviceHost
+        configManager.setServiceHost(self.serviceHost)
+        self.servicePort = self.options.servicePort
+        configManager.setServicePort(self.servicePort)
+        self.serviceProtocol = self.options.serviceProtocol
+        configManager.setServiceProtocol(self.serviceProtocol)
+
+        # SSL options, comment out for now
+        #self.sslCaCertFile = self.options.sslCaCertFile
+        #if self.sslCaCertFile:
+        #    configManager.setSslCaCertFile(self.sslCaCertFile)
+        #self.sslCertFile = self.options.sslCertFile
+        #if self.sslCertFile:
+        #    configManager.setSslCertFile(self.sslCertFile)
+        #self.sslKeyFile = self.options.sslKeyFile
+        #if self.sslKeyFile:
+        #    configManager.setSslKeyFile(self._sslKeyFile)
+
+        # Check session cache.
+        try:
+            self.checkSessionCache()
+        except Exception, ex:
+            self.logger.warn('Disabling session cache: %s' % ex)
+            configManager.setSessionCacheFile(None)
+
+        return (self.options, self.args)
+
+    def checkSessionCache(self):
+        configManager = ConfigurationManager.getInstance()
+        sessionCacheFile = configManager.getSessionCacheFile()
+        if sessionCacheFile is None:
+            sessionCacheFile = DmCli.DEFAULT_SESSION_CACHE_FILE 
+        sessionCacheFile = sessionCacheFile.strip()
+        if len(sessionCacheFile):
+            sessionCacheDir = os.path.dirname(sessionCacheFile)
+            OsUtility.createDir(sessionCacheDir, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR)
+            configManager.setSessionCacheFile(sessionCacheFile)
+            configManager.setRequireSessionCredentials(True)
+
+    def usage(self, s=None):
+        """ Print help provided by optparse. """
+        if s:
+            print >>sys.stderr, 'Error: ', s, '\n'
+        self.parser.print_help()
+        sys.exit(dmStatus.DM_ERROR)
+
+    def getOptions(self):
+        return self.options
+
+    def getNArgs(self):
+        """ Returns the number of command line arguments. """
+        return len(self.args)
+
+    def getArgs(self):
+        """ Returns the command line argument list. """
+        return self.args
+
+    def getArg(self, i):
+        """ Returns the i-th command line argument. """
+        return self.args[i]
+
+    def getServiceHost(self):
+        #return self.serviceHost
+        return ConfigurationManager.getInstance().getServiceHost()
+
+    def getServicePort(self):
+        #return self.servicePort
+        return ConfigurationManager.getInstance().getServicePort()
+
+    def getServiceProtocol(self):
+        #return self.serviceProtocol
+        return ConfigurationManager.getInstance().getServiceProtocol()
+
+    def getSslCaCertFile(self):
+        return self.sslCaCertFile
+
+    def getSslCertFile(self):
+        return self.sslCertFile
+
+    def getSslKeyFile(self):
+        return self.sslKeyFile
+
+    def displayDmObject(self, dmObject):
+        if isinstance(dmObject, dmObject):
+            return '%s' % dmObject.getJsonRep()
+        else:
+            return '%s' % dmObject
+
+    def runCommand(self):
+        """ This method must be implemented by the derived class. """
+        raise InternalError('Method runCommand() must be overriden in the derived class.')
+
+    def run(self):
+        """ This method invokes runCommand() and handles any exceptions. """
+        try:
+            self.runCommand()
+        except DmException, ex:
+            self.logger.exception('%s' % ex)
+            print '%s' % ex.getErrorMessage()
+            raise SystemExit(ex.getErrorCode())
+        except SystemExit, ex:
+            raise
+        except Exception, ex:
+            self.logger.exception('%s' % ex)
+            print >>sys.stderr, '%s' % ex
+            raise SystemExit(dmStatus.DM_ERROR)
+
+    def getId(self):
+        id = self.options.id
+        if id == None:
+            raise InvalidRequest('Missing id.')
+        return id
+
+    def displayDmObject(self, dmObject):
+        optDict = self._options.__dict__
+        if isinstance(dmObject, DmObject):
+            if optDict.get('dict'):
+                 return '%s' % dmObject
+            else:
+                 return dmObject.display()
+        else:
+            return '%s' % dmObject
+
+#######################################################################
+# Testing
+
+if __name__ == '__main__':
+    cli = DmCli(3)
+    cli.addOption("-f", "--file", dest="filename", help="write report to FILE", metavar="FILE")
+    cli.addOption("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print log messages to stdout")
+    (options, args) = cli.parseArgs()
+    print 'After parse:'
+    print 'OPTIONS: ', options
+    print 'ARGS: ', args
+    print 'From CLI'
+    print 'OPTIONS: ', cli.getOptions()
+    print 'ARGS: ', cli.getArgs()
+    print
+    print 'FILENAME'
+    print 'options.filename', options.filename
+    print 'cli.getOptions().filename', cli.getOptions().filename
+    o = cli.getOptions()
+    print 'o.filename', o.filename
+    print 'cli.getArgs()', cli.getArgs()
+    print 'len(cli.getArgs())', len(cli.getArgs())
+
+    for a in cli.getArgs():
+        print 'arg', a
+
+    first_arg = cli.getArg(0)
+    print 'first_arg', first_arg
+
+    second_arg = cli.getArg(1)
+    print 'second_arg', second_arg
+
+    try:
+        third_arg = cli.getArg(2)
+        print 'third_arg', third_arg
+    except:
+        print 'no third arg'
diff --git a/src/python/dm/common/cli/dmOptionParser.py b/src/python/dm/common/cli/dmOptionParser.py
new file mode 100755
index 0000000000000000000000000000000000000000..149b94ec528543be0d35ec8b9c615d80bb385e6d
--- /dev/null
+++ b/src/python/dm/common/cli/dmOptionParser.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import sys
+from optparse import OptionParser
+from cStringIO import StringIO
+
+class DmOptionParser(OptionParser):
+    def __init__(self):
+        OptionParser.__init__(self, add_help_option=False)
+
+    def replaceKeys(self, output):
+        replacementMap = {
+            'usage:' : 'Usage:',
+            'options:' : 'Options:',
+        }
+        result = output
+        for (key, value) in replacementMap.items():
+            result = result.replace(key, value)
+        return result
+
+    def printUsage(self, file=None):
+        self.print_usage(file)
+
+    # Replaces base class method
+    def print_usage(self, file=None):
+        sysStdout = sys.stdout
+        cliStdout = StringIO()
+        sys.stdout = cliStdout
+        OptionParser.print_usage(self, file)
+        sys.stdout = sysStdout
+        print self.replaceKeys(cliStdout.getvalue())
+
+    def printHelp(self, file=None):
+        self.printHelp(file)
+
+    # Replaces base class method
+    def print_help(self, file=None):
+        sysStdout = sys.stdout
+        cliStdout = StringIO()
+        sys.stdout = cliStdout
+        OptionParser.print_help(self, file)
+        sys.stdout = sysStdout
+        print self.replaceKeys(cliStdout.getvalue())
+
+#######################################################################
+# Testing
+
+if __name__ == '__main__':
+    p = DmOptionParser()
+    p.add_option('-f', '--file', dest='filename',
+        help='write report to FILE', metavar='FILE')
+    p.add_option('-q', '--quiet',
+        action='store_false', dest='verbose', default=True,
+        help='do not print log messages to standard output')
+    p.parse_args()
+    p.print_usage()
+    p.print_help()
diff --git a/src/python/dm/common/cli/dmRestCli.py b/src/python/dm/common/cli/dmRestCli.py
new file mode 100755
index 0000000000000000000000000000000000000000..0107fdac4d5bd9bf97fb7b013f57141689f97506
--- /dev/null
+++ b/src/python/dm/common/cli/dmRestCli.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+
+from dm.common.cli.dmCli import DmCli
+
+class DmRestCli(DmCli):
+    """ Base dm REST cli class. """
+
+    def __init__(self, validArgCount=0):
+        DmCli.__init__(self, validArgCount)
+
diff --git a/src/python/dm/common/cli/dmRestSessionCli.py b/src/python/dm/common/cli/dmRestSessionCli.py
new file mode 100755
index 0000000000000000000000000000000000000000..30f93a2b8daffdd84009708d15952cea3c365747
--- /dev/null
+++ b/src/python/dm/common/cli/dmRestSessionCli.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+from dm.common.cli.dmRestCli import DmRestCli
+
+class DmRestSessionCli(DmRestCli):
+    """ Base dm session cli class. """
+
+    def __init__(self, validArgCount=0):
+        DmRestCli.__init__(self, validArgCount)
+        self.username = None
+        self.password = None
+
+        loginGroup = 'Login Options'
+        self.addOptionGroup(loginGroup, None)
+        self.addOptionToGroup(loginGroup, '', '--username', dest='username', help='Login username.')
+        self.addOptionToGroup(loginGroup, '', '--password', dest='password', help='Login password.')
+
+    def parseArgs(self, usage=None):
+        DmRestCli.parseArgs(self, usage)
+        self.username = self.options.username
+        self.password = self.options.password
+        return (self.options, self.args)
+
+    def getUsername(self):
+        return self.username
+
+    def getPassword(self):
+        return self.password
+
+    def hasCredentials(self):
+        return (self.username != None and self.password != None)
+
+#######################################################################
+# Testing
+
+if __name__ == '__main__':
+        pass
diff --git a/src/python/dm/common/constants/__init__.py b/src/python/dm/common/constants/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/python/dm/common/constants/dmHttpHeaders.py b/src/python/dm/common/constants/dmHttpHeaders.py
new file mode 100755
index 0000000000000000000000000000000000000000..fc8af0e6610ebe37e2811e563e04091e1338a383
--- /dev/null
+++ b/src/python/dm/common/constants/dmHttpHeaders.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+
+#######################################################################
+
+DM_SESSION_ROLE_HTTP_HEADER = 'Dm-Session-Role'
+DM_STATUS_CODE_HTTP_HEADER = 'Dm-Status-Code'
+DM_STATUS_MESSAGE_HTTP_HEADER = 'Dm-Status-Message'
+DM_EXCEPTION_TYPE_HTTP_HEADER = 'Dm-Exception-Type'
+
diff --git a/src/python/dm/common/constants/dmHttpStatus.py b/src/python/dm/common/constants/dmHttpStatus.py
new file mode 100755
index 0000000000000000000000000000000000000000..24460c024f5e969e465ddb0d543a077ac6764726
--- /dev/null
+++ b/src/python/dm/common/constants/dmHttpStatus.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+
+DM_HTTP_OK = 200 
+DM_HTTP_UNAUTHORIZED = 401 
+DM_HTTP_INTERNAL_ERROR = 500 
diff --git a/src/python/dm/common/constants/dmRole.py b/src/python/dm/common/constants/dmRole.py
new file mode 100755
index 0000000000000000000000000000000000000000..801a9391de13d8542c93f1b839573c24028e8efa
--- /dev/null
+++ b/src/python/dm/common/constants/dmRole.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+#######################################################################
+
+DM_ADMIN_ROLE = 'admin'
+DM_USER_ROLE = 'user'
+
+
diff --git a/src/python/dm/common/constants/dmServiceConstants.py b/src/python/dm/common/constants/dmServiceConstants.py
new file mode 100755
index 0000000000000000000000000000000000000000..1a1419358cf3136cd95f1d98c844e427a38f6d7f
--- /dev/null
+++ b/src/python/dm/common/constants/dmServiceConstants.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+#######################################################################
+
+DM_SERVICE_PROTOCOL_HTTP = 'http'
+DM_SERVICE_PROTOCOL_HTTPS = 'https'
diff --git a/src/python/dm/common/constants/dmStatus.py b/src/python/dm/common/constants/dmStatus.py
new file mode 100755
index 0000000000000000000000000000000000000000..3a6fadd95c6af0d2130aa420a2ad51147136bbaf
--- /dev/null
+++ b/src/python/dm/common/constants/dmStatus.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+#######################################################################
+
+DM_OK = 0
+DM_ERROR = 1
+DM_INTERNAL_ERROR = 2
+DM_COMMUNICATION_ERROR = 3 
+DM_CONFIGURATION_ERROR = 4
+DM_AUTHORIZATION_ERROR = 5
+DM_AUTHENTICATION_ERROR = 6
+DM_DB_ERROR = 7
+DM_URL_ERROR = 8 
+DM_TIMEOUT = 9;
+DM_INVALID_ARGUMENT = 10
+DM_INVALID_REQUEST = 11
+DM_INVALID_SESSION = 12;    
+DM_COMMAND_FAILED =13 
+DM_OBJECT_NOT_FOUND = 14
+DM_OBJECT_ALREADY_EXISTS = 15
+DM_INVALID_OBJECT_STATE = 16;
+
+
+
diff --git a/src/python/dm/common/exceptions/__init__.py b/src/python/dm/common/exceptions/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/python/dm/common/exceptions/authenticationError.py b/src/python/dm/common/exceptions/authenticationError.py
new file mode 100755
index 0000000000000000000000000000000000000000..d905fdb62918dbd7d263fa9cd8745888af37931f
--- /dev/null
+++ b/src/python/dm/common/exceptions/authenticationError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Authentication error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class AuthenticationError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_AUTHENTICATION_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/authorizationError.py b/src/python/dm/common/exceptions/authorizationError.py
new file mode 100755
index 0000000000000000000000000000000000000000..09d348851c720c03d499c4b83060c8f8b794a1b3
--- /dev/null
+++ b/src/python/dm/common/exceptions/authorizationError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Authorization error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class AuthorizationError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_AUTHORIZATION_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/commandFailed.py b/src/python/dm/common/exceptions/commandFailed.py
new file mode 100755
index 0000000000000000000000000000000000000000..3b757e5204bf0abe45f9b8d21281b440dc661087
--- /dev/null
+++ b/src/python/dm/common/exceptions/commandFailed.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Command failed exception class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class CommandFailed(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_COMMAND_FAILED, **kwargs)
diff --git a/src/python/dm/common/exceptions/communicationError.py b/src/python/dm/common/exceptions/communicationError.py
new file mode 100755
index 0000000000000000000000000000000000000000..eb0e025f2bf4a1407bd4cef40aa395a976b64631
--- /dev/null
+++ b/src/python/dm/common/exceptions/communicationError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Communication error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class CommunicationError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_COMMUNICATION_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/configurationError.py b/src/python/dm/common/exceptions/configurationError.py
new file mode 100755
index 0000000000000000000000000000000000000000..cd6ae7a9113a1902ca97afcce96cd256c95ed3d0
--- /dev/null
+++ b/src/python/dm/common/exceptions/configurationError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Configuration error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class ConfigurationError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_CONFIGURATION_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/dbError.py b/src/python/dm/common/exceptions/dbError.py
new file mode 100755
index 0000000000000000000000000000000000000000..e9d498c36a1f0b2c15a6ae956071fb3adb5de56a
--- /dev/null
+++ b/src/python/dm/common/exceptions/dbError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# DB error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class DbError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_DB_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/dmException.py b/src/python/dm/common/exceptions/dmException.py
new file mode 100755
index 0000000000000000000000000000000000000000..517427a20e5f1d174fbf1a725ffd554659dd8d68
--- /dev/null
+++ b/src/python/dm/common/exceptions/dmException.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+#
+# Base DM exception class.
+#
+
+#######################################################################
+
+import exceptions
+import json
+
+from dm.common.constants import dmStatus 
+
+#######################################################################
+
+class DmException(exceptions.Exception):
+    """
+    Base DM exception class. 
+                
+    Usage:
+        DmException(errorMessage, errorCode)
+        DmException(args=errorMessage)
+        DmException(exception=exceptionObject)      
+    """ 
+    def __init__(self, error='', code=dmStatus.DM_ERROR, **kwargs):
+        args = error
+        if args == '':
+            args = kwargs.get('args', '')
+        ex = kwargs.get('exception', None)
+        if ex != None:
+            if isinstance(ex, exceptions.Exception):
+                exArgs = '%s' % (ex)
+            if args == '':
+                args = exArgs
+            else:
+                args = "%s (%s)" % (args, exArgs)
+        exceptions.Exception.__init__(self, args)
+        self.code = code
+
+    def getArgs(self):
+        return self.args
+
+    def getErrorCode(self):
+        return self.code
+
+    def getErrorMessage(self):
+        return '%s' % (self.args)
+
+    def getClassName(self):
+        return '%s' % (self.__class__.__name__)
+    
+    def getExceptionType(self):
+        return '%s' % (self.__class__.__name__).split('.')[-1]
+
+    def getJsonRep(self):
+        return json.dumps({
+            'errorMessage'  : self.getErrorMessage(),
+            'errorCode'     : self.getErrorCode(),
+            'exceptionType' : self.getExceptionType(),
+        })
+
+    def getFullJsonRep(self):
+        return self.getJsonRep();
+
diff --git a/src/python/dm/common/exceptions/dmExceptionMap.py b/src/python/dm/common/exceptions/dmExceptionMap.py
new file mode 100755
index 0000000000000000000000000000000000000000..c5edee4ab46f52657f7e499f121086fc485483b5
--- /dev/null
+++ b/src/python/dm/common/exceptions/dmExceptionMap.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+from dm.common.constants import dmStatus
+
+DM_EXCEPTION_MAP = {
+    dmStatus.DM_ERROR : 'dmException.DmException',
+    dmStatus.DM_INTERNAL_ERROR : 'internalError.InternalError',
+    dmStatus.DM_COMMUNICATION_ERROR : 'communicationError.CommunicationError',
+    dmStatus.DM_CONFIGURATION_ERROR : 'configurationError.ConfigurationError',
+    dmStatus.DM_AUTHORIZATION_ERROR : 'authorizationError.AuthorizationError',
+    dmStatus.DM_AUTHENTICATION_ERROR : 'authenticationError.AuthenticationError',
+    dmStatus.DM_DB_ERROR : 'dbError.DbError',
+    dmStatus.DM_URL_ERROR : 'urlError.UrlError',
+    dmStatus.DM_INVALID_ARGUMENT: 'invalidArgument.InvalidArgument',
+    dmStatus.DM_INVALID_REQUEST: 'invalidRequest.InvalidRequest',
+    dmStatus.DM_INVALID_SESSION: 'invalidSession.InvalidSession',
+    dmStatus.DM_COMMAND_FAILED: 'commandFailed.CommandFailed',
+    dmStatus.DM_OBJECT_NOT_FOUND : 'objectNotFound.ObjectNotFound',
+    dmStatus.DM_OBJECT_ALREADY_EXISTS: 'objectAlreadyExists.ObjectAlreadyExists',
+    dmStatus.DM_INVALID_OBJECT_STATE: 'invalidObjectState.InvalidObjectState',
+}
+
diff --git a/src/python/dm/common/exceptions/dmHttpError.py b/src/python/dm/common/exceptions/dmHttpError.py
new file mode 100755
index 0000000000000000000000000000000000000000..947369c97f96c5bc7d83b8399c99a6769b5107ba
--- /dev/null
+++ b/src/python/dm/common/exceptions/dmHttpError.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import cherrypy
+from cherrypy import HTTPError
+
+class DmHttpError(HTTPError):
+    def __init__ (self, httpCode, httpError, dmEx):
+        HTTPError.__init__(self, httpCode, httpError)
+        self.dmException = dmEx
+
+    def set_response(self):
+        HTTPError.set_response(self)
+        cherrypy.response.headers['Dm-Status-Code'] = self.dmException.getErrorCode()
+        cherrypy.response.headers['Dm-Status-Message'] = self.dmException.getErrorMessage()
+        cherrypy.response.headers['Dm-Exception-Type'] = self.dmException.getExceptionType()
diff --git a/src/python/dm/common/exceptions/internalError.py b/src/python/dm/common/exceptions/internalError.py
new file mode 100755
index 0000000000000000000000000000000000000000..a393f0c7f209a5c0bc63ce641ce75f9ba2c5ce01
--- /dev/null
+++ b/src/python/dm/common/exceptions/internalError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Internal error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class InternalError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_INTERNAL_ERROR, **kwargs)
diff --git a/src/python/dm/common/exceptions/invalidArgument.py b/src/python/dm/common/exceptions/invalidArgument.py
new file mode 100755
index 0000000000000000000000000000000000000000..8dfb9095e49796bb767dfa56847590c7e98ab7df
--- /dev/null
+++ b/src/python/dm/common/exceptions/invalidArgument.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Invalid argument error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class InvalidArgument(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_INVALID_ARGUMENT, **kwargs)
diff --git a/src/python/dm/common/exceptions/invalidObjectState.py b/src/python/dm/common/exceptions/invalidObjectState.py
new file mode 100755
index 0000000000000000000000000000000000000000..74c761b0732ba96f7e4f5df27aee27027b48b463
--- /dev/null
+++ b/src/python/dm/common/exceptions/invalidObjectState.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Object not found error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class ObjectNotFound(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_INVALID_OBJECT_STATE, **kwargs)
diff --git a/src/python/dm/common/exceptions/invalidRequest.py b/src/python/dm/common/exceptions/invalidRequest.py
new file mode 100755
index 0000000000000000000000000000000000000000..b95dea05ad9a1e83013437caf3694edded23ee70
--- /dev/null
+++ b/src/python/dm/common/exceptions/invalidRequest.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Invalid request error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class InvalidRequest(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_INVALID_REQUEST, **kwargs)
diff --git a/src/python/dm/common/exceptions/invalidSession.py b/src/python/dm/common/exceptions/invalidSession.py
new file mode 100755
index 0000000000000000000000000000000000000000..420bbda2229c644f342c51581b17ace9cc913555
--- /dev/null
+++ b/src/python/dm/common/exceptions/invalidSession.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Invalid request error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class InvalidRequest(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_INVALID_SESSION, **kwargs)
diff --git a/src/python/dm/common/exceptions/objectAlreadyExists.py b/src/python/dm/common/exceptions/objectAlreadyExists.py
new file mode 100755
index 0000000000000000000000000000000000000000..de8fd390492e191533c71b3cd6f7b5dfa7adc231
--- /dev/null
+++ b/src/python/dm/common/exceptions/objectAlreadyExists.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Object already exists error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class ObjectAlreadyExists(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_OBJECT_ALREADY_EXISTS, **kwargs)
diff --git a/src/python/dm/common/exceptions/objectNotFound.py b/src/python/dm/common/exceptions/objectNotFound.py
new file mode 100755
index 0000000000000000000000000000000000000000..63590cbf2107d68bab54a20ed219c8efbb0ff0fa
--- /dev/null
+++ b/src/python/dm/common/exceptions/objectNotFound.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Object not found error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class ObjectNotFound(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_OBJECT_NOT_FOUND, **kwargs)
diff --git a/src/python/dm/common/exceptions/urlError.py b/src/python/dm/common/exceptions/urlError.py
new file mode 100755
index 0000000000000000000000000000000000000000..84aae0339ea3bf0f2dc989ded2ef085d1634eec0
--- /dev/null
+++ b/src/python/dm/common/exceptions/urlError.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+#
+# Url error class.
+#
+
+#######################################################################
+
+from dm.common.constants import dmStatus 
+from dm.common.exceptions.dmException import DmException
+
+#######################################################################
+
+class UrlError(DmException):
+    def __init__ (self, error='', **kwargs):
+        DmException.__init__(self, error, dmStatus.DM_URL_ERROR, **kwargs)
diff --git a/src/python/dm/common/utility/__init__.py b/src/python/dm/common/utility/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/python/dm/common/utility/configurationManager.py b/src/python/dm/common/utility/configurationManager.py
new file mode 100755
index 0000000000000000000000000000000000000000..9f4afe20f234eed4082a75982c6434d54623677d
--- /dev/null
+++ b/src/python/dm/common/utility/configurationManager.py
@@ -0,0 +1,713 @@
+#!/usr/bin/env python
+
+# 
+# Configuration manager singleton.
+#
+
+#######################################################################
+
+import os
+import socket
+import pwd
+import UserDict
+import ConfigParser
+
+from dm.common.constants import dmServiceConstants
+from dm.common.exceptions.configurationError import ConfigurationError
+
+#######################################################################
+
+# Defaults.
+
+DEFAULT_DM_ROOT_DIR = '/opt/dm'
+DEFAULT_DM_INSTALL_DIR = '%s'                     # requires install dir
+DEFAULT_DM_CONFIG_FILE = '%s/etc/%s.%s.conf'      # requires install dir/db name/service name
+DEFAULT_DM_SERVICE_NAME= 'web-service'
+
+DEFAULT_DM_LOG_FILE = '%s/var/log/%s.%s.log'         # requires install dir/db name/service name
+DEFAULT_DM_CONSOLE_LOG_LEVEL = 'CRITICAL'
+DEFAULT_DM_FILE_LOG_LEVEL = 'INFO'
+#DEFAULT_DM_LOG_RECORD_FORMAT = '%(asctime)s,%(msecs)03d [%(levelname)s] %(module)s:%(lineno)d %(user)s@%(host)s %(name)s (%(process)d): %(message)s'
+#DEFAULT_DM_LOG_RECORD_FORMAT = '%(asctime)s,%(msecs)03d %(levelname)s %(module)s:%(lineno)d %(process)d:  %(message)s'
+DEFAULT_DM_LOG_RECORD_FORMAT = '%(asctime)s,%(msecs)03d %(levelname)s %(process)d:  %(message)s'
+DEFAULT_DM_LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
+
+DEFAULT_DM_CHERRYPY_LOG_LEVEL = 'ERROR'
+DEFAULT_DM_CHERRYPY_LOG_FILE = '%s/var/log/%s.%s.cherrypy.error'     # requires install dir/db name/service name
+DEFAULT_DM_CHERRYPY_ACCESS_FILE = '%s/var/log/%s.%s.cherrypy.access' # requires install dir/db name/service name
+
+DEFAULT_DM_SERVICE_PORT = 22236           # 222DM
+DEFAULT_DM_SERVICE_HOST = '127.0.0.1'
+DEFAULT_DM_SERVICE_PROTOCOL = dmServiceConstants.DM_SERVICE_PROTOCOL_HTTP
+DEFAULT_DM_SERVICE_USERNAME = ''
+DEFAULT_DM_SERVICE_PASSWORD = ''
+
+DEFAULT_DM_DB = 'postgresql'
+DEFAULT_DM_DB_HOST = '127.0.0.1'
+DEFAULT_DM_DB_PORT = 11136
+DEFAULT_DM_DB_PASSWORD = ''
+DEFAULT_DM_DB_NAME = 'dm'
+DEFAULT_DM_DB_SCHEMA = DEFAULT_DM_DB_NAME
+DEFAULT_DM_DB_USER = DEFAULT_DM_DB_NAME
+DEFAULT_DM_DB_PASSWORD_FILE = '%s/etc/%s.db.passwd' # requires install dir/db name
+
+DEFAULT_DM_CONTEXT_ROOT = '/dm'
+
+# Session cache file
+DEFAULT_DM_SESSION_CACHE_FILE = None
+
+# Enforce session credentials.
+DEFAULT_DM_REQUIRE_SESSION_CREDENTIALS = False
+
+# SSL variables
+DEFAULT_DM_SSL_CA_CERT_FILE = None
+DEFAULT_DM_SSL_CERT_FILE = None
+DEFAULT_DM_SSL_KEY_FILE = None
+
+class ConfigurationManager(UserDict.UserDict):
+    """ 
+    Singleton class used for keeping system configuration data. The class
+    initializes its data using predefined defaults, or from certain 
+    environment variables.
+
+    Usage:
+        from dm.common.utility import configurationManager
+        cm = configurationManager.getInstance()
+        cm.setConsoleLogLevel('info')
+        level = cm.getConsoleLogLevel()
+        cm['myKey'] = 'myValue'
+        value = cm.get('myKey')
+    """
+
+    # Get singleton instance.
+    @classmethod
+    def getInstance(cls):
+        """ Get configuration manager singleton instance. """
+        from dm.common.utility.configurationManager import ConfigurationManager
+        try:
+            cm = ConfigurationManager()
+        except ConfigurationManager, ex:
+            cm = ex
+        return cm
+
+    # Singleton.
+    __instance = None
+
+    def __init__(self):
+        if ConfigurationManager.__instance:
+            raise ConfigurationManager.__instance
+        ConfigurationManager.__instance = self
+        UserDict.UserDict.__init__(self)
+        self['user'] = pwd.getpwuid(os.getuid())[0]
+        self['host'] = socket.gethostname()
+
+        self['defaultRootDir'] = DEFAULT_DM_ROOT_DIR
+        self.__setFromEnvVar('rootDir', 'DM_ROOT_DIR')
+        self['defaultInstallDir'] = DEFAULT_DM_INSTALL_DIR % self.getRootDir()
+        self.__setFromEnvVar('installDir', 'DM_INSTALL_DIR')
+        self['defaultServiceName'] = DEFAULT_DM_SERVICE_NAME 
+        self.__setFromEnvVar('serviceName', 'DM_SERVICE_NAME')
+        self['defaultDbName'] = DEFAULT_DM_DB_NAME 
+        self.__setFromEnvVar('dbName', 'DM_DB_NAME')
+        self.__resetDynamicDefaults()
+
+        self['defaultConsoleLogLevel'] = DEFAULT_DM_CONSOLE_LOG_LEVEL
+        self['defaultFileLogLevel'] = DEFAULT_DM_FILE_LOG_LEVEL
+        self['defaultLogRecordFormat'] = DEFAULT_DM_LOG_RECORD_FORMAT
+        self['defaultLogDateFormat'] = DEFAULT_DM_LOG_DATE_FORMAT
+
+        self['defaultCherrypyLogLevel'] = DEFAULT_DM_CHERRYPY_LOG_LEVEL
+
+        self['defaultServicePort'] = DEFAULT_DM_SERVICE_PORT
+        self['defaultServiceHost'] = DEFAULT_DM_SERVICE_HOST
+        self['defaultServiceProtocol'] = DEFAULT_DM_SERVICE_PROTOCOL
+        self['defaultServiceUsername'] = DEFAULT_DM_SERVICE_USERNAME  
+        self['defaultServicePassword'] = DEFAULT_DM_SERVICE_PASSWORD
+        self['defaultDb'] = DEFAULT_DM_DB
+        self['defaultDbHost'] = DEFAULT_DM_DB_HOST
+        self['defaultDbPort'] = DEFAULT_DM_DB_PORT
+        self['defaultDbPassword'] = DEFAULT_DM_DB_PASSWORD
+
+        self['defaultContextRoot'] = DEFAULT_DM_CONTEXT_ROOT
+
+        self['defaultSessionCacheFile'] = DEFAULT_DM_SESSION_CACHE_FILE
+        self['defaultRequireSessionCredentials'] = DEFAULT_DM_REQUIRE_SESSION_CREDENTIALS
+
+        self['defaultSslCaCertFile'] = DEFAULT_DM_SSL_CA_CERT_FILE
+        self['defaultSslCertFile'] = DEFAULT_DM_SSL_CERT_FILE
+        self['defaultSslKeyFile'] = DEFAULT_DM_SSL_KEY_FILE
+                                                                                        # Settings that might come from environment variables.
+        self.__setFromEnvVar('logFile', 'DM_LOG_FILE')
+        self.__setFromEnvVar('consoleLogLevel', 'DM_CONSOLE_LOG_LEVEL')
+        self.__setFromEnvVar('fileLogLevel', 'DM_FILE_LOG_LEVEL')
+        self.__setFromEnvVar('logRecordFormat', 'DM_LOG_RECORD_FORMAT')
+        self.__setFromEnvVar('logDateFormat', 'DM_LOG_DATE_FORMAT')
+
+        self.__setFromEnvVar('cherrypyLogLevel', 'DM_CHERRYPY_LOG_LEVEL')
+        self.__setFromEnvVar('cherrypyLogFile', 'DM_CHERRYPY_LOG_FILE')
+        self.__setFromEnvVar('cherrypyAccessFile', 'DM_CHERRYPY_ACCESS_FILE')
+
+        self.__setFromEnvVar('serviceProtocol', 'DM_SERVICE_PROTOCOL')
+        self.__setFromEnvVar('serviceHost', 'DM_SERVICE_HOST')
+        self.__setFromEnvVar('servicePort', 'DM_SERVICE_PORT')
+        self.__setFromEnvVar('serviceUsername', 'DM_SERVICE_USERNAME')
+        self.__setFromEnvVar('servicePassword', 'DM_SERVICE_PASSWORD')
+
+        self.__setFromEnvVar('contextRoot', 'DM_CONTEXT_ROOT')
+
+        self.__setFromEnvVar('sessionCacheFile', 'DM_SESSION_CACHE_FILE')
+
+        self.__setFromEnvVar('sslCaCertFile', 'DM_SSL_CA_CERT_FILE')
+        self.__setFromEnvVar('sslCertFile', 'DM_SSL_CERT_FILE')
+        self.__setFromEnvVar('sslKeyFile', 'DM_SSL_KEY_FILE')
+
+        self.__setFromEnvVar('configFile', 'DM_CONFIG_FILE')
+        self.__setFromEnvVar('dbPasswordFile', 'DM_DB_PASSWORD_FILE')
+
+        # Settings that might come from file.
+        self.__setFromVarFile('dbPassword', self.getDbPasswordFile())
+
+        # Variables we do not keep in a dictionary
+        self.configParser = None
+
+    # Reset defaults that depend on install dir and service name
+    def __resetDynamicDefaults(self):
+        self['defaultConfigFile'] = DEFAULT_DM_CONFIG_FILE % (self.getInstallDir(), self.getDbName(), self.getServiceName())
+        self['defaultLogFile'] = DEFAULT_DM_LOG_FILE % (self.getInstallDir(), self.getDbName(), self.getServiceName())
+        self['defaultCherrypyAccessFile'] = DEFAULT_DM_CHERRYPY_ACCESS_FILE % (self.getInstallDir(), self.getDbName(), self.getServiceName())
+        self['defaultCherrypyLogFile'] = DEFAULT_DM_CHERRYPY_LOG_FILE % (self.getInstallDir(), self.getDbName(), self.getServiceName())
+        self['defaultDbUser'] = self.getDbName()
+        self['defaultDbSchema'] = self.getDbName()
+        self['defaultDbPasswordFile'] = DEFAULT_DM_DB_PASSWORD_FILE % (self.getInstallDir(), self.getDbName())
+
+    # This function will ignore errors if environment variable is not set.
+    def __setFromEnvVar(self, key, envVar):
+        """ 
+        Set value for the specified key from a given environment variable.
+        This function ignores errors for env. variables that are not set.
+        """
+        try:
+            self[key] = os.environ[envVar]
+        except:
+            pass
+
+    # This function will ignore errors if variable file is not present.
+    def __setFromVarFile(self, key, varFile):
+        """ 
+        Set value for the specified key from a given file. The first line  
+        in the file is variable value.
+        This function ignores errors.
+        """
+        try:
+            v = open(varFile, 'r').readline()
+            self[key] = v.lstrip().rstrip()
+        except Exception, ex:
+            pass
+
+    def __getKeyValue(self, key, default='__dm_default__'):
+        """
+        Get value for a given key.
+        Keys will be of the form 'logFile', and the default keys have
+        the form 'defaultLogFile'.
+        """
+        defaultKey = "default" + key[0].upper() + key[1:]
+        defaultValue = self.get(defaultKey, None)
+        if default != '__dm_default__':
+            defaultValue = default
+        return self.get(key, defaultValue)
+
+    def setOptionsFromConfigFile(self, configSection, keyList, configFile=None):
+        _configFile = configFile
+        if _configFile is None:
+           _configFile = self.getConfigFile()
+            
+        if _configFile is not None and os.path.exists(_configFile):
+            configParser = ConfigParser.RawConfigParser()
+            configParser.read(_configFile)
+            if not configParser.has_section(configSection):
+                return
+            for key in keyList:
+                if configParser.has_option(configSection, key):
+                    self[key] = configParser.get(configSection, key)
+
+    def clearConfigParser(self):
+        self.configParser = None
+
+    def getConfigParser(self, defaults={}):
+        if self.configParser is None:
+            configFile = self.getConfigFile()
+            if os.path.exists(configFile):
+                self.configParser = ConfigParser.ConfigParser(defaults)
+                self.configParser.read(configFile)
+                self.configParser.defaults = defaults
+        return self.configParser
+
+    def setConfigDefaults(self, defaults={}):
+        configParser = self.getConfigParser()
+        if configParser is not None:
+            configParser.defaults = defaults
+
+    def getConfigOption(self, configSection, key, defaultValue=None):
+        configParser = self.getConfigParser()
+        if self.hasConfigSection(configSection):
+            try:
+                return configParser.get(configSection, key)
+            except ConfigParser.NoOptionError, ex:
+                # ok, return default value
+                pass
+        return defaultValue
+
+    def getConfigSections(self):
+        configParser = self.getConfigParser()
+        if configParser is not None:
+            return configParser.sections()
+        return []
+
+    def hasConfigSection(self, name):
+        configSections = self.getConfigSections()
+        if name in configSections:
+            return True
+        return False
+
+    def getConfigItems(self, configSection):
+        configParser = self.getConfigParser()
+        if configParser is not None and configParser.has_section(configSection):
+            return configParser.items(configSection)
+        return []
+
+    @classmethod
+    def getConfigParserFromConfigFile(cls, configFile):
+        if not os.path.exists(configFile):
+            return None
+        configParser = ConfigParser.RawConfigParser()
+        configParser.read(configFile)
+        return configParser
+
+    @classmethod
+    def getOptionFromConfigParser(cls, configParser, configSection, key, defaultValue=None):
+        if configParser is not None and configParser.has_section(configSection):
+            return configParser.get(configSection, key)
+        else:
+            return defaultValue
+
+    @classmethod
+    def getConfigSectionsFromConfigParser(cls, configParser):
+        if configParser is not None:
+            return configParser.sections()
+        return []
+
+    @classmethod
+    def getModuleClassConstructorTuple(cls, value):
+        """ Extract (module,class,constructor) tuple from the given value. """
+        itemList = value.split('(')
+        if not itemList:
+            return ()
+        itemList2 = itemList[0].split('.')
+        moduleNameList = itemList2[0:-1]
+        className = itemList2[-1]
+        moduleName = className[0].lower() + className[1:]
+        if len(moduleNameList): 
+            moduleName = '.'.join(moduleNameList)
+        constructor = '%s(%s' % (className, ''.join(itemList[1:]))
+        return (moduleName,className,constructor)
+
+    def getHost(self):
+        return self['host']
+    
+    def getUser(self):
+        return self['user']
+
+    def getDefaultRootDir(self):
+        return self['defaultRootDir']
+
+    def setRootDir(self, rootDir):
+        self['rootDir'] = rootDir
+
+    def getRootDir(self, default='__dm_default__'):
+        return self.__getKeyValue('rootDir', default)
+
+    def getDefaultInstallDir(self):
+        return self['defaultInstallDir']
+
+    def setInstallDir(self, installDir):
+        self['installDir'] = installDir
+        self.__resetDynamicDefaults()
+
+    def getInstallDir(self, default='__dm_default__'):
+        return self.__getKeyValue('installDir', default)
+
+    def getDefaultServiceName(self):
+        return self['defaultServiceName']
+
+    def setServiceName(self, serviceName):
+        self['serviceName'] = serviceName
+        self.__resetDynamicDefaults()
+
+    def getServiceName(self, default='__dm_default__'):
+        return self.__getKeyValue('serviceName', default)
+
+    def getDefaultDbName(self):
+        return self['defaultDbName']
+
+    def setDbName(self, dbName):
+        self['dbName'] = dbName
+        self.__resetDynamicDefaults()
+
+    def getDbName(self, default='__dm_default__'):
+        return self.__getKeyValue('dbName', default)
+
+    def getDefaultLogFile(self):
+        return self['defaultLogFile']
+
+    def setLogFile(self, logFile):
+        self['logFile'] = logFile
+
+    def getLogFile(self, default='__dm_default__'):
+        return self.__getKeyValue('logFile', default)
+
+    def hasLogFile(self):
+        return self.has_key('logFile')
+
+    def getDefaultConsoleLogLevel(self):
+        return self['defaultConsoleLogLevel']
+
+    def setConsoleLogLevel(self, level):
+        self['consoleLogLevel'] = level 
+
+    def getConsoleLogLevel(self, default='__dm_default__'):
+        return self.__getKeyValue('consoleLogLevel', default)
+
+    def getConsoleLogLevelFromEnvVar(self):
+        return os.environ.get('DM_CONSOLE_LOG_LEVEL')
+
+    def hasConsoleLogLevel(self):
+        return self.has_key('consoleLogLevel')
+
+    def getDefaultFileLogLevel(self):
+        return self['defaultFileLogLevel']
+
+    def setFileLogLevel(self, level):
+        self['fileLogLevel'] = level 
+
+    def getFileLogLevel(self, default='__dm_default__'):
+        return self.__getKeyValue('fileLogLevel', default)
+
+    def hasFileLogLevel(self):
+        return self.has_key('fileLogLevel')
+
+    def getDefaultLogRecordFormat(self):
+        return self['defaultLogRecordFormat']
+
+    def setLogRecordFormat(self, format):
+        self['logRecordFormat'] = format
+
+    def getLogRecordFormat(self, default='__dm_default__'):
+        return self.__getKeyValue('logRecordFormat', default)
+
+    def hasLogRecordFormat(self):
+        return self.has_key('logRecordFormat')
+
+    def getDefaultLogDateFormat(self):
+        return self['defaultLogDateFormat']
+
+    def setLogDateFormat(self, format):
+        self['logDateFormat'] = format
+
+    def getLogDateFormat(self, default='__dm_default__'):
+        return self.__getKeyValue('logDateFormat', default)
+
+    def hasLogDateFormat(self):
+        return self.has_key('logDateFormat')
+
+    def getDefaultCherrypyLogLevel(self):
+        return self['defaultCherrypyLogLevel']
+
+    def setCherrypyLogLevel(self, level):
+        self['cherrypyLogLevel'] = level 
+
+    def getCherrypyLogLevel(self, default='__dm_default__'):
+        return self.__getKeyValue('cherrypyLogLevel', default)
+
+    def hasCherrypyLogLevel(self):
+        return self.has_key('cherrypyLogLevel')
+
+    def getDefaultCherrypyLogCherrypy(self):
+        return self['defaultCherrypyLogFile']
+
+    def setCherrypyLogFile(self, cherrypyLogFile):
+        self['cherrypyLogFile'] = cherrypyLogFile
+
+    def getCherrypyLogFile(self, default='__dm_default__'):
+        return self.__getKeyValue('cherrypyLogFile', default)
+
+    def hasCherrypyLogFile(self):
+        return self.has_key('cherrypyLogFile')
+
+    def getDefaultCherrypyAccessFile(self):
+        return self['defaultCherrypyAccessFile']
+
+    def setCherrypyAccessFile(self, cherrypyAccessFile):
+        self['cherrypyAccessFile'] = cherrypyAccessFile
+
+    def getCherrypyAccessFile(self, default='__dm_default__'):
+        return self.__getKeyValue('cherrypyAccessFile', default)
+
+    def hasCherrypyAccessFile(self):
+        return self.has_key('cherrypyAccessFile')
+
+    def isDbAvailable(self):
+        if os.access(self.getDbPasswordFile(), os.R_OK):
+            return True
+        return False
+
+    def getDefaultServiceProtocol(self):
+        return self['defaultServiceProtocol']
+
+    def setServiceProtocol(self, serviceProtocol):
+        self['serviceProtocol'] = serviceProtocol
+
+    def getServiceProtocol(self, default='__dm_default__'):
+        return self.__getKeyValue('serviceProtocol', default)
+
+    def hasServiceProtocol(self):
+        return self.has_key('serviceProtocol')
+
+    def getDefaultServicePort(self):
+        return self['defaultServicePort']
+
+    def setServicePort(self, servicePort):
+        self['servicePort'] = servicePort 
+
+    def getServicePort(self, default='__dm_default__'):
+        return int(self.__getKeyValue('servicePort', default))
+
+    def hasServicePort(self):
+        return self.has_key('servicePort')
+
+    def getDefaultServiceHost(self):
+        return self['defaultServiceHost']
+
+    def setServiceHost(self, serviceHost):
+        self['serviceHost'] = serviceHost
+
+    def getServiceHost(self, default='__dm_default__'):
+        return self.__getKeyValue('serviceHost', default)
+
+    def hasServiceHost(self):
+        return self.has_key('serviceHost')
+
+    def getDefaultServiceUsername(self):
+        return self['defaultServiceUsername']
+
+    def setServiceUsername(self, serviceUsername):
+        self['serviceUsername'] = serviceUsername 
+
+    def getServiceUsername(self, default='__dm_default__'):
+        return self.__getKeyValue('serviceUsername', default)
+
+    def hasServiceUsername(self):
+        return self.has_key('serviceUsername')
+
+    def getDefaultServicePassword(self):
+        return self['defaultServicePassword']
+
+    def setServicePassword(self, servicePassword):
+        self['servicePassword'] = servicePassword 
+
+    def getServicePassword(self, default='__dm_default__'):
+        return self.__getKeyValue('servicePassword', default)
+
+    def hasServicePassword(self):
+        return self.has_key('servicePassword')
+
+    def getDefaultDb(self):
+        return self['defaultDb']
+
+    def setDb(self, db):
+        self['db'] = db
+
+    def getDb(self, default='__dm_default__'):
+        return self.__getKeyValue('db', default) 
+
+    def hasDb(self):
+        return self.has_key('db')
+
+    def getDefaultDbHost(self):
+        return self['defaultDbHost']
+
+    def setDbHost(self, dbHost):
+        self['dbHost'] = dbHost
+
+    def getDbHost(self, default='__dm_default__'):
+        return self.__getKeyValue('dbHost', default) 
+
+    def hasDbHost(self):
+        return self.has_key('dbHost')
+
+    def getDefaultDbPort(self):
+        return self['defaultDbPort']
+
+    def setDbPort(self, dbPort):
+        self['dbPort'] = dbPort
+
+    def getDbPort(self, default='__dm_default__'):
+        return self.__getKeyValue('dbPort', default) 
+
+    def hasDbPort(self):
+        return self.has_key('dbPort')
+
+    def getDefaultDbPassword(self):
+        return self['defaultDbPassword']
+
+    def setDbPassword(self, dbPassword):
+        self['dbPassword'] = dbPassword
+
+    def getDbPassword(self, default='__dm_default__'):
+        return self.__getKeyValue('dbPassword', default) 
+
+    def hasDbPassword(self):
+        return self.has_key('dbPassword')
+
+    def getDefaultDbPasswordFile(self):
+        return self['defaultDbPasswordFile']
+
+    def getDbPasswordFile(self, default='__dm_default__'):
+        return self.__getKeyValue('dbPasswordFile', default) 
+
+    def setDbPasswordFile(self, f):
+        self['dbPasswordFile'] = f
+
+    def hasDbPasswordFile(self):
+        return self.has_key('dbPasswordFile')
+
+    def getDefaultDbUser(self):
+        return self['defaultDbUser']
+
+    def getDbUser(self, default='__dm_default__'):
+        return self.__getKeyValue('dbUser', default) 
+
+    def setDbUser(self, dbUser):
+        self['dbUser'] = dbUser
+
+    def hasDbUser(self):
+        return self.has_key('dbUser')
+
+    def getDbSchema(self, default='__dm_default__'):
+        return self.__getKeyValue('dbSchema', default)
+
+    def getDefaultConfigFile(self):
+        return self['defaultConfigFile']
+
+    def setConfigFile(self, configFile):
+        self['configFile'] = configFile
+        # Must reinitialize config parser at this point
+        self.configParser = None
+
+    def getConfigFile(self, default='__dm_default__'):
+        return self.__getKeyValue('configFile', default)
+
+    def hasConfigFile(self):
+        return self.has_key('configFile')
+
+    def getDefaultContextRoot(self):
+        return self['defaultContextRoot']
+
+    def setContextRoot(self, contextRoot):
+        self['contextRoot'] = contextRoot
+
+    def getContextRoot(self, default='__dm_default__'):
+        return self.__getKeyValue('contextRoot', default)
+
+    def hasContextRoot(self):
+        return self.has_key('contextRoot')
+
+    def getDefaultSessionCacheFile(self):
+        return self['defaultSessionCacheFile']
+
+    def setSessionCacheFile(self, sessionCacheFile):
+        self['sessionCacheFile'] = sessionCacheFile
+
+    def getSessionCacheFile(self, default='__dm_default__'):
+        return self.__getKeyValue('sessionCacheFile', default)
+
+    def hasSessionCacheFile(self):
+        return self.has_key('sessionCacheFile')
+
+    def getDefaultRequireSessionCredentials(self):
+        return self['defaultRequireSessionCredentials']
+
+    def setRequireSessionCredentials(self, requireSessionCredentials):
+        self['requireSessionCredentials'] = requireSessionCredentials
+
+    def getRequireSessionCredentials(self, default='__dm_default__'):
+        return self.__getKeyValue('requireSessionCredentials', default)
+
+    def hasRequireSessionCredentials(self):
+        return self.has_key('requireSessionCredentials')
+
+    def getDefaultSslCaCertFile(self):
+        return self['defaultSslCaCertFile']
+
+    def setSslCaCertFile(self, sslCaCertFile):
+        self['sslCaCertFile'] = sslCaCertFile
+
+    def getSslCaCertFile(self, default='__dm_default__'):
+        return self.__getKeyValue('sslCaCertFile', default)
+
+    def hasSslCaCertFile(self):
+        return self.has_key('sslCaCertFile')
+
+    def getDefaultSslCertFile(self):
+        return self['defaultSslCertFile']
+
+    def setSslCertFile(self, sslCertFile):
+        self['sslCertFile'] = sslCertFile
+
+    def getSslCertFile(self, default='__dm_default__'):
+        return self.__getKeyValue('sslCertFile', default)
+
+    def hasSslCertFile(self):
+        return self.has_key('sslCertFile')
+
+    def getDefaultSslKeyFile(self):
+        return self['defaultSslKeyFile']
+
+    def setSslKeyFile(self, sslKeyFile):
+        self['sslKeyFile'] = sslKeyFile
+
+    def getSslKeyFile(self, default='__dm_default__'):
+        return self.__getKeyValue('sslKeyFile', default)
+
+    def hasSslKeyFile(self):
+        return self.has_key('sslKeyFile')
+
+    def getDefaultUsername(self):
+        return self['defaultUsername']
+
+    def setUsername(self, username):
+        self['username'] = username
+
+    def getUsername(self, default='__dm_default__'):
+        return self.__getKeyValue('username', default)
+
+    def hasUsername(self):
+        return self.has_key('username')
+
+    def getDefaultPassword(self):
+        return self['defaultPassword']
+
+    def setPassword(self, password):
+        self['password'] = password
+
+    def getPassword(self, default='__dm_default__'):
+        return self.__getKeyValue('password', default)
+
+    def hasPassword(self):
+        return self.has_key('password')
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    cm = ConfigurationManager.getInstance()
+    print cm
diff --git a/src/python/dm/common/utility/consoleLoggingHandler.py b/src/python/dm/common/utility/consoleLoggingHandler.py
new file mode 100755
index 0000000000000000000000000000000000000000..c8353c2e812e4454b6011e2f223d6c36f7477fe9
--- /dev/null
+++ b/src/python/dm/common/utility/consoleLoggingHandler.py
@@ -0,0 +1,42 @@
+#!/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")
+                                                                                                                        
diff --git a/src/python/dm/common/utility/cryptUtility.py b/src/python/dm/common/utility/cryptUtility.py
new file mode 100755
index 0000000000000000000000000000000000000000..19a722592a550fa6941e1ff6f8ef9a74ee9fe30e
--- /dev/null
+++ b/src/python/dm/common/utility/cryptUtility.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+import random
+import string
+import crypt
+#import md5
+import hashlib
+import base64
+
+class CryptUtility:
+
+    CRYPT_TYPE = 6  # SHA-512 (man crypt)
+    SALT_CHARACTERS = string.lowercase + string.uppercase + string.digits
+    SALT_DELIMITER = '$'
+    SALT_LENGTH_IN_BYTES = 4
+
+    PBKDF2_ENCRYPTION = 'sha1' # use SHA-1 for compatibility with java
+    PBKDF2_KEY_LENGTH_IN_BYTES = 24
+    PBKDF2_ITERATIONS = 1003
+
+    @classmethod
+    def getRandomWord(cls, length):
+        return ''.join(random.choice(CryptUtility.SALT_CHARACTERS) for i in range(length))
+
+    @classmethod
+    def cryptPassword(cls, password):
+        """ Return crypted password. """
+        #calculator = md5.md5()
+        #calculator.update(salt)
+        #md5Salt = calculator.hexdigest()
+        #return crypt.crypt(cleartext, md5Salt)
+
+        salt = CryptUtility.getRandomWord(CryptUtility.SALT_LENGTH_IN_BYTES)
+        salt = '%s%s%s%s%s'.format(CryptUtility.SALT_DELIMITER, CryptUtility.CRYPT_TYPE, CryptUtility.SALT_DELIMITER, salt, CryptUtility.SALT_DELIMITER)
+        return crypt.crypt(password, salt)
+
+    @classmethod
+    def verifyPassword(cls, password, cryptedPassword):
+        """ Verify crypted password. """
+        return cryptedPassword == crypt.crypt(password, cryptedPassword)
+
+    @classmethod
+    def cryptPasswordWithPbkdf2(cls, password):
+        """ Crypt password with pbkdf2 package and encode with b64. """
+        salt = CryptUtility.getRandomWord(CryptUtility.SALT_LENGTH_IN_BYTES)
+        return cls.saltAndCryptPasswordWithPbkdf2(password, salt)
+
+    @classmethod
+    def saltAndCryptPasswordWithPbkdf2(cls, password, salt):
+        """ Crypt salted password with pbkdf2 package and encode with b64. """
+        cryptedPassword = hashlib.pbkdf2_hmac(
+            CryptUtility.PBKDF2_ENCRYPTION, 
+            password, salt, 
+            CryptUtility.PBKDF2_ITERATIONS, 
+            CryptUtility.PBKDF2_KEY_LENGTH_IN_BYTES)
+        encodedPassword = base64.b64encode(cryptedPassword)
+        return '%s%s%s' % (salt, CryptUtility.SALT_DELIMITER, encodedPassword)
+
+    @classmethod
+    def verifyPasswordWithPbkdf2(cls, password, cryptedPassword):
+        """ Verify crypted password. """
+        # Get salt
+        salt = '%s' % cryptedPassword.split(CryptUtility.SALT_DELIMITER)[0]
+        # Verify crypted password
+        return cryptedPassword == cls.saltAndCryptPasswordWithPbkdf2(password, salt)
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    import sys
+    #password = "dm"
+    password = sys.argv[1]
+    print 'Clear text: ', password
+    #cryptedPassword = CryptUtility.cryptPassword(password)
+    #print 'Crypted: ', cryptedPassword
+    #isVerified = CryptUtility.verifyPassword(password, cryptedPassword)
+    #print 'Verify: ', isVerified
+
+    cryptedPassword = CryptUtility.cryptPasswordWithPbkdf2(password)
+    print 'Crypted: ', cryptedPassword
+    isVerified = CryptUtility.verifyPasswordWithPbkdf2(password, cryptedPassword)
+    print 'Verify: ', isVerified
+
diff --git a/src/python/dm/common/utility/dmModuleManager.py b/src/python/dm/common/utility/dmModuleManager.py
new file mode 100755
index 0000000000000000000000000000000000000000..625611b236fc1e1c1b3440ef6ec542fb458616bb
--- /dev/null
+++ b/src/python/dm/common/utility/dmModuleManager.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+
+#
+# Module manager class.
+#
+
+#######################################################################
+
+import threading
+
+#######################################################################
+
+class DmModuleManager:
+    """ Singleton class used for managing dm modules. """
+
+    # Get singleton instance.
+    @classmethod
+    def getInstance(cls):
+        from dm.common.utility.dmModuleManager import DmModuleManager
+        try:
+            mgr = DmModuleManager()
+        except DmModuleManager, ex:
+            mgr = ex
+        return mgr
+
+    # 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.loggingManager import LoggingManager
+            self.logger = LoggingManager.getInstance().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
diff --git a/src/python/dm/common/utility/dmSubprocess.py b/src/python/dm/common/utility/dmSubprocess.py
new file mode 100755
index 0000000000000000000000000000000000000000..5a4d39860ef735b3f805d3dcb809303e9d2ed73f
--- /dev/null
+++ b/src/python/dm/common/utility/dmSubprocess.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+
+# 
+# Subprocess class
+#
+
+import os
+import subprocess
+import platform
+
+from dm.common.utility.loggingManager import LoggingManager
+from dm.common.exceptions.commandFailed import CommandFailed
+
+#######################################################################
+
+class DmSubprocess(subprocess.Popen):
+
+    # Get subprocess instance.
+    @classmethod
+    def getSubprocess(cls, command):
+        close_fds = True
+        if platform.system() != 'Windows':
+            close_fds = False
+        p = DmSubprocess(command, close_fds=close_fds)
+        return p
+
+    # Execute command
+    @classmethod
+    def executeCommand(cls, command):
+        """ Create subprocess and run it, return subprocess object. """
+        p = cls.getSubprocess(command)
+        p.run()
+        return p
+
+    # Execute command, ignore errors.
+    @classmethod
+    def executeCommandAndIgnoreFailure(cls, command):
+        """ Create subprocess, run it, igore any failures, and return subprocess object. """
+        p = cls.getSubprocess(command)
+        try:
+            p.run()
+        except CommandFailed, ex:
+            p.getLogger().debug('Command failed, stdout: %s, stderr: %s' % (p.getStdOut(), p.getStdErr()))
+        return p
+
+    @classmethod
+    def executeCommandAndLogToStdOut(cls, command):
+        """ Execute command, display output to stdout, maintain log file and return subprocess object. """
+        p = cls.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
+
+    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 more appropriate defaults. """
+        subprocess.Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
+        self.logger = LoggingManager.getInstance().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
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    p = DmSubprocess('ls -l', useExceptions=False)
+    p.run()
+    print p.getStdOut()
+    print p.getStdErr()
+    print p.getExitStatus()
+
diff --git a/src/python/dm/common/utility/encoder.py b/src/python/dm/common/utility/encoder.py
new file mode 100755
index 0000000000000000000000000000000000000000..61b0c3054574450932dd6c3412c5d1d35964cecd
--- /dev/null
+++ b/src/python/dm/common/utility/encoder.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import base64
+
+class Encoder:
+
+    @classmethod
+    def encode(cls, data):
+        # Encode twice, in order to avoid issues like '+' being
+        # interpreted as space after decoding
+        encodedData = base64.b64encode(base64.encodestring('%s' % data))
+        return encodedData
+
+    @classmethod
+    def decode(cls, encodedData):
+        data = base64.decodestring(base64.b64decode('%s' % encodedData))
+        return data
diff --git a/src/python/dm/common/utility/ldapUtility.py b/src/python/dm/common/utility/ldapUtility.py
new file mode 100755
index 0000000000000000000000000000000000000000..b0b07a2b6c73e787444f99594ab4c92ce725e5b1
--- /dev/null
+++ b/src/python/dm/common/utility/ldapUtility.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+import ldap
+
+from dm.common.exceptions.authenticationError import AuthenticationError
+from dm.common.exceptions.communicationError import CommunicationError
+
+class LdapUtility:
+
+    def __init__(self, serverUrl, dnFormat):
+        self.serverUrl = serverUrl
+        self.dnFormat = dnFormat
+         
+    def checkCredentials(self, username, password):
+        """Verifies credentials for username and password. """
+        ldapUsername = self.dnFormat % username
+        try:
+            # build client
+            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
+            ldapClient = ldap.initialize(self.serverUrl)
+            ldapClient.set_option(ldap.OPT_REFERRALS,0)
+            ldapClient.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
+
+            #ldapClient.ststart_tls_s()
+            #ldapClient.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
+            #ldapClient.set_option( ldap.OPT_X_TLS_DEMAND, True)
+            #ldapClient.set_option( ldap.OPT_DEBUG_LEVEL, 255)
+
+            # perform a synchronous bind
+            ldapClient.simple_bind_s(ldapUsername, password)
+            #ldapClient.whoami_s()
+        except ldap.INVALID_CREDENTIALS, ex:
+            ldapClient.unbind()
+            raise AuthenticationError('Invalid LDAP credentials for user %s' % username)
+        except ldap.SERVER_DOWN, ex:
+            raise CommunicationError('Cannot reach LDAP server %s' % self.serverUrl)
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    ldapUtility = LdapUtility(serverUrl='ldaps://ldap.anl.gov:636', dnFormat='uid=%s,dc=anl,dc=gov')
+    ldapUtility.checkCredentials('sveseli', 'sv')
diff --git a/src/python/dm/common/utility/loggingManager.py b/src/python/dm/common/utility/loggingManager.py
new file mode 100755
index 0000000000000000000000000000000000000000..52c6021679a9b4dd5a1f31a2622075220d92017d
--- /dev/null
+++ b/src/python/dm/common/utility/loggingManager.py
@@ -0,0 +1,305 @@
+#!/usr/bin/env python
+
+#
+# Logging manager singleton.
+#
+
+#######################################################################
+
+import re
+import sys
+import os.path
+import logging
+from dm.common.utility.configurationManager import ConfigurationManager
+from dm.common.exceptions.configurationError import ConfigurationError
+
+#######################################################################
+
+
+class LoggingManager:
+    """ 
+    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
+    """
+
+    # Get singleton instance.
+    @classmethod
+    def getInstance(cls):
+        from dm.common.utility.loggingManager import LoggingManager
+        try:
+            lm = LoggingManager()
+        except LoggingManager, ex:
+            lm = ex
+        return lm
+
+    # 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 expressions of the form <regex>=<log level>. """
+        lines = levelRegExList.split('\n')
+        for line in lines:
+            try:
+                 (regex, level) = line.rsplit('=', 1)
+                 pattern = re.compile(regex)
+                 tuple = (pattern, logging.getLevelName(level.upper()))
+                 self.levelRegExList.append(tuple)
+            except Exception, ex:
+                 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.getConfigFile()
+        configParser = cm.getConfigParserFromConfigFile(configFile)
+        configSections = cm.getConfigSectionsFromConfigParser(configParser)
+
+        # Console handler.
+        defaults = { 
+            'level' : cm.getConsoleLogLevel(),
+            'format' : cm.getLogRecordFormat(),
+            'dateFormat' : cm.getLogDateFormat(),
+            'handler' : 'ConsoleLoggingHandler(sys.stdout,)'
+        }
+        consoleHandler = self.__configureHandler(configParser, '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(configParser, '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(configParser, 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(configParser, defaultLevel='debug')
+
+    def configureLoggers(self, configParser, defaultLevel='error'):
+        rootLogLevel = 'error'
+        levelRegEx = '^.*$=%s' % (defaultLevel)
+        if configParser is not None and configParser.has_section('LoggerLevels'):
+            rootLogLevel = ConfigurationManager.getOptionFromConfigParser(configParser, 'LoggerLevels', 'root', rootLogLevel)
+            levelRegEx = ConfigurationManager.getOptionFromConfigParser(configParser, '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)
+
+    # Configure particular handler with given defaults.
+    def __configureHandler(self, configParser, configSection, defaults):
+        """ Configure specified handler with a given defaults. """
+        handlerOption = defaults['handler']
+        try:
+            if configParser is not None:
+                handlerOption = configParser.get(configSection, 'handler')
+        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, errMsg = 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.
+        cm = ConfigurationManager.getInstance()
+        if handler != None:
+            try:
+                level = cm.getOptionFromConfigParser(configParser, configSection, 'level', defaults['level'])
+                intLevel = self.getIntLogLevel(level.upper())
+                handler.setLevel(intLevel)
+
+                format = cm.getOptionFromConfigParser(configParser, configSection, 'format', defaults['format'])
+                dateFormat = cm.getOptionFromConfigParser(configParser, configSection, 'dateFormat', defaults['dateFormat'])
+
+                handler.setFormatter(logging.Formatter(format, dateFormat))
+            except Exception, ex:
+                raise ConfigurationError(exception=ex)
+
+            # Apply filters to handler
+            filter = None
+            try:
+                filter = configParser.get(configSection, 'filter')
+                if filter:
+                    handler.addFilter(logging.Filter(filter))
+            except Exception, ex:
+                pass
+        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 = LoggingManager.getInstance()
+    logger = lm.getLogger('Main')
+    logger.error('Error In Main')
+    logger.debug('Debug In Main')
+    logger.warn('Warn In Main')
+    logger.info('Info In Main')
+    logger = lm.getLogger('Main')
+    logger.info('Info In Main')
+    logger = lm.getLogger('')
+    logger.info('Info using root logger')
+    logger = lm.getLogger('Main.2')
+    logger.info('Info in Main.2')
+    lm.setConsoleLogLevel('info')
+    logger.debug('You should not see this message')
+    lm.setConsoleLogLevel('debug')
+    logger.debug('Debug in Main.2')
diff --git a/src/python/dm/common/utility/objectCache.py b/src/python/dm/common/utility/objectCache.py
new file mode 100755
index 0000000000000000000000000000000000000000..529717b02b810620f5e7b90cad7b813b10da14c4
--- /dev/null
+++ b/src/python/dm/common/utility/objectCache.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+
+import threading
+import time
+from collections import deque
+
+class ObjectCache:
+    """
+    Cache objects identified by id. Objects are removed from cache
+    based on the last accessed algorithm.
+    """
+
+    # How much larger than object cache should time stamp deq be
+    # allowed to grow.
+    DEFAULT_TIME_STAMP_DEQ_SIZE_FACTOR = 2
+    # Cache info expiration time.
+    DEFAULT_OBJECT_LIFETIME = 60 # seconds
+
+    def __init__(self, cacheSize, objectLifetime=DEFAULT_OBJECT_LIFETIME):
+        self.lock = threading.RLock()
+        self.objectMap = {} # id/object map
+        self.timeStampDeq = deque() # timeStamp deq
+        self.cacheSize = cacheSize
+        self.objectLifetime = objectLifetime
+        self.deqSize = ObjectCache.DEFAULT_TIME_STAMP_DEQ_SIZE_FACTOR*cacheSize
+
+    def setCacheSize(self, cacheSize):
+        self.cacheSize = cacheSize
+
+    def setObjectLifetime(self, objectLifetime):
+        self.objectLifetime = objectLifetime
+
+    def __purgeOne(self):
+        # Get rid of one cached item based on the last accessed algorithm.
+        while True:
+            deqEntry = self.timeStampDeq.popleft()
+            oldId = deqEntry[0]
+            cachedEntry = self.objectMap.get(oldId)
+            if cachedEntry is not None:
+                # Timestamp entry is valid.
+                if cachedEntry == deqEntry:
+                    # Found an old item, get rid of it from the cache.
+                    del self.objectMap[oldId]
+                    break
+        # Done.
+        return
+
+    def __purgeTimeStampDeq(self):
+        # Get rid of stale entries.
+        timeStampDeq = deque()
+        while len(self.timeStampDeq):
+            deqEntry = self.timeStampDeq.popleft()
+            id = deqEntry[0]
+            cachedEntry = self.objectMap.get(id)
+            if cachedEntry is not None:
+                # Timestamp entry is valid.
+                if cachedEntry == deqEntry:
+                    # Found current item, keep it.
+                    timeStampDeq.append(deqEntry)
+        # Done.
+        self.timeStampDeq = timeStampDeq 
+        return
+
+    def put(self, id, item, objectLifetime=None):
+        updateTime = time.time()
+        expirationTime = updateTime + self.objectLifetime
+        if objectLifetime is not None:
+            expirationTime = updateTime + objectLifetime
+        entry = (id, item, updateTime, expirationTime)
+        self.lock.acquire()
+        try:
+            self.objectMap[id] = entry
+            self.timeStampDeq.append(entry)
+            if len(self.objectMap) > self.cacheSize:
+                self.__purgeOne()
+            if len(self.timeStampDeq) > self.deqSize:
+                self.__purgeTimeStampDeq()
+        
+        finally:
+            self.lock.release()
+
+    def get(self, id):
+        return self.objectMap.get(id)
+
+    def remove(self, id):
+        self.lock.acquire()
+        try:
+            item = self.objectMap.get(id)
+            if item is not None:
+                del self.objectMap[id]
+            return item
+        finally:
+            self.lock.release()
+
+    def isEmpty(self):
+        return len(self.objectMap) == 0
+
+    def size(self):
+        return len(self.objectMap) 
+
+    def __str__(self):
+        return '%s' % self.timeStampDeq
+
+#######################################################################
+# Testing.
+if __name__ == '__main__':
+    c = ObjectCache(3)
+
+    class Item:
+        def __init__(self, id):
+            self.id = id
+        def getId(self):
+            return self.id
+        def __str__(self):
+            return '%s' % self.id
+
+    class Item2:
+        def __init__(self, name):
+            self.name = name 
+        def getName(self):
+            return self.name
+        def __str__(self):
+            return '%s' % self.name
+
+    for i in range(0,5):
+        item = Item(i)
+        c.put(i, item)
+        print 'Added item: ', item
+        print 'Cache: ', c
+        time.sleep(1)
+
+    for j in range(0,3):
+        item = Item(2)
+        c.put(2, item)
+        print 'Updated item: ', item
+        print 'Cache: ', c
+        time.sleep(1)
+
+    item = c.remove(2)
+    print 'Deleted item 2: ', item
+    print 'Cache: ', c
+    time.sleep(1)
+    item = c.get(2)
+    print 'Got item 2: ', item
+    print 'Cache: ', c
+    print
+    time.sleep(1)
+
+    print
+    c = ObjectCache(3)
+    c.put('sv', Item2('sv')) 
+    print c
+    i = c.get('sv')
+    print i
+    print 'Done'
+
diff --git a/src/python/dm/common/utility/osUtility.py b/src/python/dm/common/utility/osUtility.py
new file mode 100755
index 0000000000000000000000000000000000000000..9f9ac57e6840479451f0ea0d5264397dee9c3fdd
--- /dev/null
+++ b/src/python/dm/common/utility/osUtility.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+import os
+
+class OsUtility:
+
+    @classmethod
+    def createDir(cls, path, mode=None):
+        """ Create directory if it does not exist already. """
+        if not os.path.isdir(path):
+            os.makedirs(path)
+            if mode is not None:
+                os.chmod(path, mode)
+
+    @classmethod
+    def removeLink(cls, path):
+        """ Remove link on a given path. """
+        if not os.path.islink(path):
+            return
+        os.remove(path)
+
+    @classmethod
+    def removeFile(cls, path):
+        """ Remove file on a given path. """
+        if not os.path.isfile(path):
+            return
+        os.remove(path)
+
+    @classmethod
+    def removeAndIgnoreErrors(cls, path):
+        """ Remove file on a given path and ignore any errors. """
+        try:
+            os.remove(path)
+        except Exception, ex:
+            pass
+
+    @classmethod
+    def removeDir(cls, path):
+        """ Remove dir on a given path, even if it is not empty. """
+        if not os.path.isdir(path):
+            return
+        files=os.listdir(path)
+        for f in files:
+            fullpath=os.path.join(path, f)
+            if os.path.islink(fullpath) or not os.path.isdir(fullpath):
+                os.remove(fullpath)
+            else:
+                removeDir(fullpath)
+        os.rmdir(path)
+        
+    @classmethod
+    def chownPath(cls, path, uid, gid):
+        """ Change owner on a given path recursively.  """
+        if os.path.isfile(path):
+            os.chown(path, uid, gid)
+            return 
+        elif os.path.islink(path):
+            os.lchown(path, uid, gid)
+            return 
+        elif os.path.isdir(path):
+            files=os.listdir(path)
+            for f in files:
+                fullpath=os.path.join(path, f)
+                chownPath(fullpath, uid, gid)
+            os.chown(path, uid, gid)
+
+    @classmethod
+    def chownPathByUserName(cls, path, userName):
+        """ Change owner on a given path recursively.  """
+        import pwd
+        user = pwd.getpwnam(userName)
+        chownPath(path, user.pw_uid, user.pw_gid)
+
+    @classmethod
+    def findFiles(cls, dirPath, fileList=None):
+        """ List files in a given directory. Return list of absolute paths.
+            Do not follow symbolic links.
+        """
+        fList = fileList
+        if not fList:
+            fList = []
+        if os.path.isdir(dirPath):
+            files = os.listdir(dirPath)
+            for f in files:
+                fullPath = os.path.join(dirPath, f)
+                if os.path.isfile(fullPath):
+                    fList.append(fullPath)
+                elif os.path.isdir(fullPath):
+                    fList = findFiles(fullPath, fList)
+        return fList
+
+    @classmethod
+    def importNameFromFile(cls, name, filePath):
+        """ Import specified name from file. """
+        import sys
+        import os.path
+        dirName = os.path.dirname(filePath)
+        moduleName = os.path.basename(filePath).replace('.py', '')
+        sys.path = [dirName] + sys.path
+        cmd = 'from %s import %s as tmpObject' % (moduleName, name)
+        exec cmd
+        del sys.path[0]
+        return tmpObject
+
+    @classmethod
+    def getUserHomeDir(cls):
+        """ Get current user home directory. """
+        from os.path import expanduser
+        home = expanduser('~')
+        return home
+
+#######################################################################
+# Testing.
+
+if __name__ == '__main__':
+    pass
diff --git a/src/python/dm/common/utility/sslUtility.py b/src/python/dm/common/utility/sslUtility.py
new file mode 100755
index 0000000000000000000000000000000000000000..2ad61cbb327609e1b4424a0b5b597417e4671dab
--- /dev/null
+++ b/src/python/dm/common/utility/sslUtility.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+import ssl
+
+class SslUtility:
+
+    DEFAULT_SSL_CONTEXT = ssl._create_default_https_context
+
+    @classmethod
+    def useUnverifiedSslContext(cls, func):
+
+        def wrapper(*args, **kwargs):
+            # Disable SSL checking
+            ssl._create_default_https_context = ssl._create_unverified_context
+
+            # Perform function call 
+            result = func(*args, **kwargs)
+
+            # Revert back to original SSL settings
+            ssl._create_default_https_context = SslUtility.DEFAULT_SSL_CONTEXT 
+            return result
+
+        return wrapper
+
diff --git a/src/python/dm/common/utility/timeUtility.py b/src/python/dm/common/utility/timeUtility.py
new file mode 100755
index 0000000000000000000000000000000000000000..5300ff12bcc02761414fb8bf0f96f2008136bc78
--- /dev/null
+++ b/src/python/dm/common/utility/timeUtility.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import time
+class TimeUtility:
+
+    @classmethod
+    def getCurrentGMTimeStamp(cls):
+        """ Formats GMT timestamp. """
+        return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(time.time()))
+
+    @classmethod
+    def formatGMTimeStamp(cls, t):
+        """ Format GMT timestamp. """
+        return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(t))
+
+    @classmethod
+    def getCurrentLocalTimeStamp(cls):
+        """ Formats local timestamp. """
+        return time.strftime('%Y/%m/%d %H:%M:%S %Z', time.localtime(time.time()))
+
+    @classmethod
+    def formatLocalTimeStamp(cls, t):
+        """ Formats local timestamp. """
+        return time.strftime('%Y/%m/%d %H:%M:%S %Z', time.localtime(t))
+
+
diff --git a/src/python/dm/common/utility/timedRotatingFileLoggingHandler.py b/src/python/dm/common/utility/timedRotatingFileLoggingHandler.py
new file mode 100755
index 0000000000000000000000000000000000000000..04c8ffc80b661840a4a0ddc7700dc04628d7f709
--- /dev/null
+++ b/src/python/dm/common/utility/timedRotatingFileLoggingHandler.py
@@ -0,0 +1,28 @@
+#!/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