Interface changes in LDAP role mapper

In the existing code, role mapping was global. Hence, we could have one
single config at a time.  Now, with the changed backend, there can be
multiple LDAP configs and the role mapping is tied to the config.

This commit make sure openbmctool ldap configuration options
compatible with both redfish and non-redfish enabled OpenBMC systems.

Tested By:

1. Configuring ldap active directory configuration:
$ python openbmctool.py -U root -P 0penBmc -H $BMC_IP ldap enable -a "ldap://$LDAP_SERVER/" -B "cn=user,cn=Users,dc=Corp,dc=xyz,dc=com" -b "dc=Corp,dc=xyz,dc=com" -p "ldap1" -S sub -t ActiveDirectory
Attempting login...
Role map exists for the server type ActiveDirectory
User root has been logged out

2. View ldap configuration
$ python openbmctool.py -U root -P 0penBmc -H $BMC_IP ldap view-config
Attempting login...
{
  "data": {
    "Enabled": true,
    "GroupNameAttribute": "primaryGroupID",
    "LDAPBaseDN": "dc=Corp,dc=xyz,dc=com",
    "LDAPBindDN": "cn=user,cn=Users,dc=Corp,dc=xyz,dc=com",
    "LDAPBindDNPassword": "",
    "LDAPSearchScope": "xyz.openbmc_project.User.Ldap.Config.SearchScope.sub",
    "LDAPServerURI": "ldap://$LDAP_SERVER/",
    "LDAPType": "xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory",
    "UserNameAttribute": "sAMAccountName"
  },
  "message": "200 OK",
  "status": "ok"
}

3.List privilege-mappings
$ python openbmctool.py -U root -P 0penBmc -H $BMC_IP ldap privilege-mapper list
Attempting login...
{
  "data": {
    "/xyz/openbmc_project/user/ldap/active_directory/role_map/1": {
      "GroupName": "G1",
      "Privilege": "priv-admin"
    },
    "/xyz/openbmc_project/user/ldap/active_directory/role_map/2": {
      "GroupName": "G2",
      "Privilege": "priv-operator"
    },
    "/xyz/openbmc_project/user/ldap/active_directory/role_map/3": {
      "GroupName": "G3",
      "Privilege": "priv-user"
    }
  },
  "message": "200 OK",
  "status": "ok"
}
User root has been logged out

4. Disable LDAP
$ python openbmctool.py -U root -P 0penBmc -H $BMC_IP ldap disable
Attempting login...
{
  "data": null,
  "message": "200 OK",
  "status": "ok"
}
User root has been logged out

5. Configure OpenLDAP
$ python openbmctool.py -U root -P 0penBmc -H $BMC_IP ldap enable -a $LDAP_SERVER -B "cn=Administrator,dc=ldap,dc=com" -b "dc=ldap,dc=com" -p "ldap" -S sub -t OpenLDAP
Attempting login...
Server type OpenLDAP has been enabled. Create role map before using it...
User root has been logged out

6. View LDAP configuration
$ python openbmctool.py -U xyzjxp -P abc@123 -H $BMC_IP ldap view-config
Attempting login...
{
  "data": {
    "Enabled": true,
    "GroupNameAttribute": "gidNumber",
    "LDAPBaseDN": "dc=ldap,dc=com",
    "LDAPBindDN": "cn=Administrator,dc=ldap,dc=com",
    "LDAPBindDNPassword": "",
    "LDAPSearchScope": "xyz.openbmc_project.User.Ldap.Config.SearchScope.sub",
    "LDAPServerURI": $LDAP_SERVER,
    "LDAPType": "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap",
    "UserNameAttribute": "cn"
  },
  "message": "200 OK",
  "status": "ok"
}

7. Create privilege role map
$ python openbmctool.py -H $BMC_IP -U root -P 0penBmc ldap privilege-mapper create -g G3 -p priv-user
Attempting login...
legacy: False
{
  "data": "/xyz/openbmc_project/user/ldap/openldap/role_map/1",
  "message": "200 OK",
  "status": "ok"
}

8. List privilege role mappings
$ python openbmctool.py -U test -P test@123 -H $BMC_IP ldap privilege-mapper list
Attempting login...
{
  "data": {
    "/xyz/openbmc_project/user/ldap/openldap/role_map/1": {
      "GroupName": "G3",
      "Privilege": "priv-user"
    }
  },
  "message": "200 OK",
  "status": "ok"
}

$ python openbmctool.py -U test -P test@123 -H $BMC_IP ldap view-config
Attempting login...
{
  "data": {
    "LDAPBaseDN": "dc=ldap,dc=com",
    "LDAPBindDN": "uid=test,dc=ldap,dc=com",
    "LDAPSearchScope": "xyz.openbmc_project.User.Ldap.Config.SearchScope.sub",
    "LDAPServerURI": $LDAP_SERVER,
    "LDAPType": "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap"
  },
  "message": "200 OK",
  "status": "ok"
}

Change-Id: I4df361c229d742381fa6edcd77c125ad6556b20e
Signed-off-by: Ravi Teja <raviteja28031990@gmail.com>
diff --git a/thalerj/openbmctool.py b/thalerj/openbmctool.py
old mode 100755
new mode 100644
index 6583b77..14df78e
--- a/thalerj/openbmctool.py
+++ b/thalerj/openbmctool.py
@@ -34,6 +34,10 @@
 jsonHeader = {'Content-Type' : 'application/json'}
 xAuthHeader = {}
 baseTimeout = 60
+serverTypeMap = {
+        'ActiveDirectory' : 'active_directory',
+        'OpenLDAP' : 'openldap'
+        }
 
 def hilight(textToColor, color, bold):
     """
@@ -2783,7 +2787,7 @@
         print("GenerateCSR complete.")
     return resp.text
 
-def enableLDAP(host, args, session):
+def enableLDAPConfig(host, args, session):
     """
          Called by the ldap function. Configures LDAP.
 
@@ -2794,6 +2798,22 @@
             be provided in json format for programmatic consumption
     """
 
+    if(isRedfishSupport):
+        return enableLDAP(host, args, session)
+    else:
+        return enableLegacyLDAP(host, args, session)
+
+def enableLegacyLDAP(host, args, session):
+    """
+         Called by the ldap function. Configures LDAP on Lagecy systems.
+
+         @param host: string, the hostname or IP address of the bmc
+         @param args: contains additional arguments used by the ldap subcommand
+         @param session: the active session to use
+         @param args.json: boolean, if this flag is set to true, the output will
+            be provided in json format for programmatic consumption
+    """
+
     url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
     scope = {
              'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
@@ -2802,8 +2822,8 @@
             }
 
     serverType = {
-            'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
-            'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
+             'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
+             'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
             }
 
     data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
@@ -2817,6 +2837,102 @@
 
     return res.text
 
+def enableLDAP(host, args, session):
+    """
+         Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
+
+         @param host: string, the hostname or IP address of the bmc
+         @param args: contains additional arguments used by the ldap subcommand
+         @param session: the active session to use
+         @param args.json: boolean, if this flag is set to true, the output will
+            be provided in json format for programmatic consumption
+    """
+
+    scope = {
+             'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
+             'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
+             'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
+            }
+
+    serverType = {
+            'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
+            'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
+            }
+
+    url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
+
+    serverTypeEnabled = getLDAPTypeEnabled(host,session)
+    serverTypeToBeEnabled = args.serverType
+
+    #If the given LDAP type is already enabled, then return
+    if (serverTypeToBeEnabled == serverTypeEnabled):
+      return("Server type " + serverTypeToBeEnabled + " is already enabled...")
+
+    try:
+
+        #  Copy the role map from the currently enabled LDAP server type
+        #  to the newly enabled server type
+        #  Disable the currently enabled LDAP server type. Unless
+        #  it is disabled, we cannot enable a new LDAP server type
+        if (serverTypeEnabled is not None):
+
+            if (serverTypeToBeEnabled != serverTypeEnabled):
+                res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
+
+            data = "{\"data\": 0 }"
+            res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
+
+        data = {"data": args.baseDN}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+            print("Updates to the property LDAPBaseDN failed...")
+            return(res.text)
+
+        data = {"data": args.bindDN}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property LDAPBindDN failed...")
+           return(res.text)
+
+        data = {"data": args.bindPassword}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property LDAPBindDNPassword failed...")
+           return(res.text)
+
+        data = {"data": scope[args.scope]}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property LDAPSearchScope failed...")
+           return(res.text)
+
+        data = {"data": args.uri}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property LDAPServerURI failed...")
+           return(res.text)
+
+        data = {"data": args.groupAttrName}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property GroupNameAttribute failed...")
+           return(res.text)
+
+        data = {"data": args.userAttrName}
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (res.status_code != requests.codes.ok):
+           print("Updates to the property UserNameAttribute failed...")
+           return(res.text)
+
+        #After updating the properties, enable the new server type
+        data = "{\"data\": 1 }"
+        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
+
+    except(requests.exceptions.Timeout):
+        return(connectionErrHandler(args.json, "Timeout", None))
+    except(requests.exceptions.ConnectionError) as err:
+        return connectionErrHandler(args.json, "ConnectionError", err)
+    return res.text
 
 def disableLDAP(host, args, session):
     """
@@ -2829,11 +2945,33 @@
             will be provided in json format for programmatic consumption
     """
 
-    url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
-    data = {"data": []}
-
     try:
-        res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        if (isRedfishSupport) :
+
+            url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
+
+            serverTypeEnabled = getLDAPTypeEnabled(host,session)
+
+            if (serverTypeEnabled is not None):
+                #To keep the role map in sync,
+                #If the server type being disabled has role map, then
+                #   - copy the role map to the other server type(s)
+                for serverType in serverTypeMap.keys():
+                    if (serverType != serverTypeEnabled):
+                        res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
+
+                #Disable the currently enabled LDAP server type
+                data = "{\"data\": 0 }"
+                res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
+
+            else:
+                return("LDAP server has not been enabled...")
+
+        else :
+            url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
+            data = {"data": []}
+            res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+
     except(requests.exceptions.Timeout):
         return(connectionErrHandler(args.json, "Timeout", None))
     except(requests.exceptions.ConnectionError) as err:
@@ -2841,7 +2979,6 @@
 
     return res.text
 
-
 def enableDHCP(host, args, session):
 
     """
@@ -3515,6 +3652,78 @@
 
     return res.text
 
+def getLDAPTypeEnabled(host,session):
+
+    """
+        Called by LDAP related functions to find the LDAP server type that has been enabled.
+        Returns None if LDAP has not been configured.
+
+        @param host: string, the hostname or IP address of the bmc
+        @param session: the active session to use
+    """
+
+    enabled = False
+    url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
+    for key,value in serverTypeMap.items():
+        data = {"data": []}
+        try:
+            res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        except(requests.exceptions.Timeout):
+            print(connectionErrHandler(args.json, "Timeout", None))
+            return
+        except(requests.exceptions.ConnectionError) as err:
+            print(connectionErrHandler(args.json, "ConnectionError", err))
+            return
+
+        enabled = res.json()['data']
+        if (enabled):
+            return key
+
+def syncRoleMap(host,args,session,fromServerType,toServerType):
+
+    """
+        Called by LDAP related functions to sync the role maps
+        Returns False if LDAP has not been configured.
+
+        @param host: string, the hostname or IP address of the bmc
+        @param session: the active session to use
+        @param fromServerType : Server type whose role map has to be copied
+        @param toServerType : Server type to which role map has to be copied
+    """
+
+    url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
+
+    try:
+        #Note: If the fromServerType has no role map, then
+        #the toServerType will not have any role map.
+
+        #delete the privilege mapping from the toServerType and
+        #then copy the privilege mapping from fromServerType to
+        #toServerType.
+        args.serverType = toServerType
+        res = deleteAllPrivilegeMapping(host, args, session)
+
+        data = {"data": []}
+        res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+        #Previously enabled server type has no role map
+        if (res.status_code != requests.codes.ok):
+
+            #fromServerType has no role map; So, no need to copy
+            #role map to toServerType.
+            return
+
+        objDict = json.loads(res.text)
+        dataDict = objDict['data']
+        for  key,value in dataDict.items():
+            data = {"data": [value["GroupName"], value["Privilege"]]}
+            res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
+
+    except(requests.exceptions.Timeout):
+        return(connectionErrHandler(args.json, "Timeout", None))
+    except(requests.exceptions.ConnectionError) as err:
+        return connectionErrHandler(args.json, "ConnectionError", err)
+    return res.text
+
 
 def createPrivilegeMapping(host, args, session):
     """
@@ -3527,12 +3736,27 @@
                 will be provided in json format for programmatic consumption
     """
 
-    url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
-
-    data = {"data": [args.groupName,args.privilege]}
-
     try:
-        res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
+        if (isRedfishSupport):
+            url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
+
+            #To maintain the interface compatibility between op930 and op940, the server type has been made
+            #optional. If the server type is not specified, then create the role-mapper for the currently
+            #enabled server type.
+            serverType = args.serverType
+            if (serverType is None):
+                serverType = getLDAPTypeEnabled(host,session)
+                if (serverType is None):
+                     return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
+
+            data = {"data": [args.groupName,args.privilege]}
+            res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
+
+        else:
+            url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
+            data = {"data": [args.groupName,args.privilege]}
+            res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
+
     except(requests.exceptions.Timeout):
         return(connectionErrHandler(args.json, "Timeout", None))
     except(requests.exceptions.ConnectionError) as err:
@@ -3549,7 +3773,19 @@
          @param args.json: boolean, if this flag is set to true, the output
                 will be provided in json format for programmatic consumption
     """
-    url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
+
+    if (isRedfishSupport):
+        serverType = args.serverType
+        if (serverType is None):
+            serverType = getLDAPTypeEnabled(host,session)
+            if (serverType is None):
+                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
+
+        url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
+
+    else:
+        url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
+
     data = {"data": []}
 
     try:
@@ -3558,6 +3794,7 @@
         return(connectionErrHandler(args.json, "Timeout", None))
     except(requests.exceptions.ConnectionError) as err:
         return connectionErrHandler(args.json, "ConnectionError", err)
+
     return res.text
 
 def deletePrivilegeMapping(host, args, session):
@@ -3570,26 +3807,45 @@
          @param args.json: boolean, if this flag is set to true, the output
                 will be provided in json format for programmatic consumption
     """
-    (ldapNameSpaceObjects) = listPrivilegeMapping(host, args, session)
+
+    ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
     ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
     path = ''
-
-    # not interested in the config objet
-    ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
-
-    # search for the object having the mapping for the given group
-    for key,value in ldapNameSpaceObjects.items():
-        if value['GroupName'] == args.groupName:
-            path = key
-            break
-
-    if path == '':
-        return "No privilege mapping found for this group."
-
-    # delete the object
-    url = 'https://'+host+path+'/action/delete'
     data = {"data": []}
 
+    if (isRedfishSupport):
+        if (args.serverType is None):
+            serverType = getLDAPTypeEnabled(host,session)
+            if (serverType is None):
+                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
+        # search for the object having the mapping for the given group
+        for key,value in ldapNameSpaceObjects.items():
+            if value['GroupName'] == args.groupName:
+                path = key
+                break
+
+        if path == '':
+            return "No privilege mapping found for this group."
+
+        # delete the object
+        url = 'https://'+host+path+'/action/Delete'
+
+    else:
+        # not interested in the config objet
+        ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
+
+        # search for the object having the mapping for the given group
+        for key,value in ldapNameSpaceObjects.items():
+            if value['GroupName'] == args.groupName:
+                path = key
+                break
+
+        if path == '':
+            return "No privilege mapping found for this group."
+
+        # delete the object
+        url = 'https://'+host+path+'/action/delete'
+
     try:
         res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
     except(requests.exceptions.Timeout):
@@ -3607,20 +3863,29 @@
          @param args.json: boolean, if this flag is set to true, the output
                 will be provided in json format for programmatic consumption
     """
+
     ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
     ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
     path = ''
-
-    # Remove the config object.
-    ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
     data = {"data": []}
 
+    if (isRedfishSupport):
+        if (args.serverType is None):
+            serverType = getLDAPTypeEnabled(host,session)
+            if (serverType is None):
+                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
+
+    else:
+        # Remove the config object.
+        ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
+
     try:
         # search for GroupName property and delete if it is available.
         for path in ldapNameSpaceObjects.keys():
             # delete the object
-            url = 'https://'+host+path+'/action/delete'
+            url = 'https://'+host+path+'/action/Delete'
             res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
+
     except(requests.exceptions.Timeout):
         return(connectionErrHandler(args.json, "Timeout", None))
     except(requests.exceptions.ConnectionError) as err:
@@ -3629,7 +3894,7 @@
 
 def viewLDAPConfig(host, args, session):
     """
-         Called by the ldap function. Prints out LDAP's configured properties
+         Called by the ldap function. Prints out active LDAP configuration properties
 
          @param host: string, the hostname or IP address of the bmc
          @param args: contains additional arguments used by the ldap subcommand
@@ -3638,15 +3903,28 @@
          @param session: the active session to use
          @return returns LDAP's configured properties.
     """
-    url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
+
     try:
-        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
+        if (isRedfishSupport):
+
+            url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
+
+            serverTypeEnabled = getLDAPTypeEnabled(host,session)
+
+            if (serverTypeEnabled is not None):
+                data = {"data": []}
+                res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
+            else:
+                return("LDAP server has not been enabled...")
+
+        else :
+            url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
+            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
+
     except(requests.exceptions.Timeout):
         return(connectionErrHandler(args.json, "Timeout", None))
     except(requests.exceptions.ConnectionError) as err:
         return connectionErrHandler(args.json, "ConnectionError", err)
-    except(requests.exceptions.RequestException) as err:
-        return connectionErrHandler(args.json, "RequestException", err)
     if res.status_code == 404:
         return "LDAP server config has not been created"
     return res.text
@@ -4189,9 +4467,11 @@
     parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
     parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
             help='Specifies the search scope:subtree, one level or base object.')
-    parser_ldap_config.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
+    parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
             help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
-    parser_ldap_config.set_defaults(func=enableLDAP)
+    parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
+    parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
+    parser_ldap_config.set_defaults(func=enableLDAPConfig)
 
     # disable LDAP
     parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
@@ -4208,21 +4488,29 @@
             help="sub-command help", dest='command')
 
     parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
+    parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
+            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
     parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
-    parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-user'],required=True,help="Privilege")
+    parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-operator','priv-user','priv-callback'],required=True,help="Privilege")
     parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
 
     #list group privilege mapping
     parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
+    parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
+            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
     parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
 
     #delete group privilege mapping
     parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
+    parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
+            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
     parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
     parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
 
     #deleteAll group privilege mapping
     parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
+    parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
+            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
     parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
 
     # set local user password
@@ -4489,6 +4777,7 @@
     global toolVersion
     toolVersion = "1.15"
     global isRedfishSupport
+
     parser = createCommandParser()
     args = parser.parse_args(argv)