diff --git a/src/python/dm/common/objects/ldapUserInfo.py b/src/python/dm/common/objects/ldapUserInfo.py
new file mode 100755
index 0000000000000000000000000000000000000000..e9be08a8e86babfff1658684ab4bea0d1ab6fb30
--- /dev/null
+++ b/src/python/dm/common/objects/ldapUserInfo.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+from dmObject import DmObject
+
+class LdapUserInfo(DmObject):
+
+    DEFAULT_KEY_LIST = [ 'userDn', 'userAttrs' ]
+
+    def __init__(self, dict):
+        DmObject.__init__(self, dict)
+
diff --git a/src/python/dm/common/utility/ldapClient.py b/src/python/dm/common/utility/ldapClient.py
index 2a9df07603eeb59b703f75a0c8d599b292bf1296..b19c0b45b885e338d62fc627b6172a28b990998a 100755
--- a/src/python/dm/common/utility/ldapClient.py
+++ b/src/python/dm/common/utility/ldapClient.py
@@ -33,6 +33,8 @@ class LdapClient:
             try:
                 result = func(*args, **kwargs)
                 return result
+            except ldap.NO_SUCH_OBJECT, ex:
+                raise ObjectNotFound(str(ex))
             except DmException, ex:
                 raise
             except Exception, ex:
diff --git a/src/python/dm/common/utility/ldapUserManager.py b/src/python/dm/common/utility/ldapUserManager.py
index 7c551e2014d0b400374921e7a1cf16d2cf232956..8f1e53aacb4f3241be4ce2f18fa419b518d110ca 100755
--- a/src/python/dm/common/utility/ldapUserManager.py
+++ b/src/python/dm/common/utility/ldapUserManager.py
@@ -10,6 +10,7 @@ from base64 import b16decode
 from base64 import b64encode
 from base64 import b64decode
 
+from dm.common.objects.ldapUserInfo import LdapUserInfo
 from dm.common.utility.loggingManager import LoggingManager
 from dm.common.utility.configurationManager import ConfigurationManager
 from dm.common.exceptions.configurationError import ConfigurationError
@@ -18,6 +19,7 @@ from dm.common.exceptions.objectNotFound import ObjectNotFound
 from dm.common.exceptions.authenticationError import AuthenticationError
 from dm.common.exceptions.communicationError import CommunicationError
 from dm.common.exceptions.invalidArgument import InvalidArgument
+from dm.common.exceptions.objectAlreadyExists import ObjectAlreadyExists
 from dm.common.exceptions.dmException import DmException
 from ldapClient import LdapClient
 
@@ -51,27 +53,82 @@ class LdapUserManager(LdapClient):
         ldapClient = self.getLdapClient()
         resultList = ldapClient.search_s(userDn, ldap.SCOPE_BASE)
         userTuple = resultList[0]
-        return userTuple
+        return LdapUserInfo({'userDn' : userTuple[0], 'userAttrs' : userTuple[1]})
 
+    @LdapClient.executeLdapCall
     def modifyUserInfo(self, username, attrDict):
         """ Modify user. """
         logger = self.getLogger()
         ldapClient = self.getLdapClient()
-        userDn,userAttrs = self.getUserInfo(username)
-        logger.debug('Modifying user %s attrs %s' % (username, attrDict))
+        ldapUserInfo = self.getUserInfo(username)
+        userDn = ldapUserInfo.get('userDn')
+        userAttrs = ldapUserInfo.get('userAttrs')
         userAttrs2 = copy.copy(userAttrs)
         for name,value in attrDict.items():
-            if not userAttrs2.has_key(name):
-                raise InvalidArgument('No such attribute: %s' % name)
-            if type(value) == types.ListType:
-                userAttrs2[name] = value
+            ldapName = name
+            ldapValue = value
+            if name == 'passwordHashValue':
+                ldapName = 'userPassword'
+                ldapValue = self.encodePasswordHash(value)
+            if not userAttrs2.has_key(ldapName):
+                raise InvalidArgument('No such attribute: %s' % ldapName)
+
+            if type(ldapValue) == types.ListType:
+                userAttrs2[ldapName] = ldapValue
             else:
-                if name == 'userPassword':
-                    value = self.encodePasswordHash(value)
-                userAttrs2[name] = [str(value)]
+                userAttrs2[ldapName] = [str(ldapValue)]
 
+        logger.debug('Modifying user %s attrs %s' % (username, userAttrs2))
         userLdif = ldap.modlist.modifyModlist(userAttrs, userAttrs2)
         ldapClient.modify_s(userDn, userLdif)
+        return LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs2})
+
+    @LdapClient.executeLdapCall
+    def createUserInfo(self, username, attrDict):
+        """ Create user. """
+        logger = self.getLogger()
+        ldapClient = self.getLdapClient()
+        try:
+            ldapUserInfo = self.getUserInfo(username)
+            raise ObjectAlreadyExists('User %s already exists.' % username)
+        except ObjectNotFound, ex:
+            pass
+        middleName = attrDict.get('middleName', '') 
+        fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))
+        if len(middleName):
+            fullName = '%s %s' % (fullName, middleName)
+        badgeNumber = attrDict.get('badgeNumber')
+        uid = 'd%s' % badgeNumber
+        if username != uid:
+            raise InvalidArgument('Username %s and badge number %s are not consistent.' % (username, badgeNumber))
+
+        userAttrs = {}
+        userAttrs['objectclass'] = ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'inetUser', 'shadowAccount', 'posixAccount', 'passwordObject', 'APSexten', 'apple-user']
+        userAttrs['cn'] = [attrDict.get('name', fullName)]
+        userAttrs['revcn'] = ['%s %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))]
+        userAttrs['loginShell'] = ['/sbin/nologin']
+        userAttrs['allowed-host'] = ['dmid-vm']
+        userAttrs['uidNumber'] = ['10%s' % badgeNumber]
+        userAttrs['uid'] = [uid]
+        userAttrs['homeDirectory'] = ['/data']
+        userAttrs['home7Directory'] = ['/data']
+        userAttrs['o'] = [attrDict.get('grp')]
+        userAttrs['inetUserStatus'] = ['active']
+        userAttrs['gidNumber'] = ['66001']
+        userAttrs['gecos'] = [attrDict.get('name', fullName)]
+        userAttrs['sn'] = [attrDict.get('lastName', '')]
+        userAttrs['givenName'] = [attrDict.get('firstName', '')]
+        passwordHash = attrDict.get('userPassword')
+        if not passwordHash:
+            passwordHash = attrDict.get('passwordHashValue')
+        if passwordHash:
+            userAttrs['userPassword'] = [self.encodePasswordHash(passwordHash)]
+        logger.debug('Creating user %s with attrs %s' % (username, userAttrs))
+
+        userDn = self.userDnFormat % str(username)
+        userLdif = ldap.modlist.addModlist(userAttrs)
+        ldapClient.add_s(userDn, userLdif)
+        return LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs})
 
     def createGroup(self, name):
         """ Create group if it does not exist. """
@@ -231,14 +288,20 @@ if __name__ == '__main__':
     print utility.getGroupInfo(u's1id-test03')
     user = utility.getUserInfo(u'd225159')
     print user
-    utility.modifyUserInfo(u'd225159', {'homeDirectory' : '/data'})
+    utility.modifyUserInfo(u'd225159', {'homeDirectory' : '/data/'})
     user = utility.getUserInfo(u'd225159')
     print user
     user = utility.getUserInfo(u'd65114')
     print user
 
-    passwordHash = LdapUserManager.decodePasswordHash(user[1]['userPassword'][0])
+    passwordHash = LdapUserManager.decodePasswordHash(user['userAttrs']['userPassword'][0])
     print passwordHash
+
+    attrDict = {'badgeNumber' : '000001', 'name' : 'Test, User 1.', 'firstName' : 'User', 'middleName' : '1.', 'lastName' : 'Test', 'passwordHashValue' : '84673F4A8774846B1C096511C7F6B1329CEE5CCC', 'inactive' : 'N', 'grp' : 'XSD-TEST', 'lastChangeDate' : '2015-02-03 15:52:15', 'email' : 'UTEST1@APS.ANL.GOV', 'isUserNotAnlEmployee' : 'N' }
+    user = utility.createUserInfo(u'd000001', attrDict)
+    user = utility.getUserInfo(u'd000001')
+    print user
+
     #print LdapUserManager.encodePasswordHash(passwordHash)
 
     #utility.addLocalUserToGroup(u'sveseli', u'id8i-test02')