Modifying eDirectory Schema using LDIF files

  • 7008201
  • 24-Mar-2011
  • 03-Apr-2015

Environment

Novell Directory Services 8
Novell eDirectory 8.5 for All Platforms
Novell eDirectory 8.6 for All Platforms
Novell eDirectory 8.7 for All Platforms
Novell eDirectory 8.8 for All Platforms


Situation

NDS Error: schema is in use (-644)
Modifying eDirectory Schema using LDIF files
How to modify schema using LDIF
Using LDIF to modify schema
Removing optional attributes from existing an Class definition

Resolution

Before you can delete a schema definition, you must make sure that it is not used anywhere in your entire tree.  eDirectory will only verify that the definition is not used by any object held on the server holding the [Root] replica which you send your schema modification request to. If there is an object somewhere in the tree that does use the schema definition, it will either become unknown, be deleted (if the class was removed), or have the attribute removed the tree that does use the schema definition, it will either become unknown, be deleted (if the class was removed), or have the attribute removed when the next DSRepair is run. 
 
If you attempt to delete a schema definition after you have cleaned up any references to that definition, you will still frequently get an -644 error, saying the definition is still in use.  This is usually because the deleted attribute values or objects have not yet been fully processed and purged out of the system.  You can force this process to occur earlier than the normal schedule by typing on the NetWare Console SET DSTRACE = *B, or from iMonitor, go to the Agent Configuration page, select the Agent Triggers link which will bring up a page with seven check box options.  Select the Reference Check box, the click submit.  Both these choices will initiate the Backlinker process, which causes the deleted objects or values to be processed and purged (among other things).  After this has completed, you can then successfully delete the schema definition.
You can add new class definitions, either Auxiliary, Abstract, or Structural.  Sample LDIF for this:

version: 1

# define attributes
dn: cn=schema
changetype: modify
add: attributetypes
attributetypes: (2.16.840.1.113719.1.3.801
  NAME 'novlTestAttr1'
  DESC 'test attribute'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
  SINGLE-VALUE )


dn: cn=schema
changetype: modify
add: attributetypes
attributetypes: (2.16.840.1.113719.1.3.802
  NAME 'novlTestAttr2'
  DESC 'test attribute'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE )


dn: cn=schema
changetype: modify
add: attributetypes
attributetypes: (2.16.840.1.113719.1.3.803
  NAME 'novlTestAttr3'
  DESC 'test attribute'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
  SINGLE-VALUE X-NDS_PUBLIC_READ '1')

#define different class types
dn: cn=schema
changetype: modify
add: objectclasses
objectclasses: ( 2.16.840.1.113719.1.3.900
  NAME 'novlPerson1'
  DESC 'Test Abstract class'
  SUP top
  ABSTRACT
  MAY ( novlTestAttr1 )
 )


dn: cn=schema
changetype: modify
add: objectclasses
objectclasses: ( 2.16.840.1.113719.1.3.901
  NAME 'novlPerson2'
  DESC 'Test Aux class'
  AUXILIARY
  MAY ( novlTestAttr1 )
 )


dn: cn=schemaNovell Directory Services 8
Novell eDirectory 8.5 for All Platforms
Novell eDirectory 8.6 for All Platforms

changetype: modify
add: objectclasses
objectclasses: ( 2.16.840.1.113719.1.3.902
  NAME 'novlPerson3'
  DESC 'Test Structural class'
  SUP inetOrgPerson
  STRUCTURAL
  MAY ( novlTestAttr2 $ novlTestAttr3 )
 )

_______________________________________________________________________
You can modify some parts of an existing attribute definition.   Some flag values can be changed.

version: 1

#change the value of the Public Read flag
dn: cn=schema
changetype: modify
delete: attributetypes
attributetypes: (2.16.840.1.113719.1.3.803 )
-
add: attributetypes
attributetypes: (2.16.840.1.113719.1.3.803
  NAME 'novlTestAttr3'
  DESC 'test attribute'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
  SINGLE-VALUE X-NDS_PUBLIC_READ '0')

_______________________________________________________________________
You can add a new superclass to an existing class definition, but you can't remove a superclass from a class definition once it has been added.  To remove it, you must delete the class definition it was added to (and recreate again if needed), and then you can delete the class that was referenced as the superclass, if desired.   Doing this WILL invalidate all existing objects of that class, and recreating the class with the same name WILL NOT make the objects valid again.  Sample LDIF for this:

version: 1

#replace operation to add a new superclass to an existing object class
dn: cn=schema
changetype: modify
delete: objectclasses
objectclasses: (2.16.840.1.113719.1.3.902)
-
add: objectclasses
objectclasses: (2.16.840.1.113719.1.3.902
  NAME 'novlPerson3'
  DESC 'Add a superclass to existing class'
  SUP ( inetOrgPerson $ novlPerson1 )
  STRUCTURAL
  MAY ( novlTestAttr2 $ novlTestAttr3 )
 )
_______________________________________________________________________
You can add an auxiliary class to an existing object instance.  Sample LDIF for this:

version: 1
#define a sample object instance
dn: o=novell
changetype: add
objectclass: organization
o: novell

dn: cn=user1, o=novell
changetype: add
objectclass: inetorgperson
cn: user1
surname: novl


#add an auxiliary class, populate the new attribute it defines
dn: cn=user1, o=novell
changetype: modify
add:objectclass
objectclass: novlPerson2
novlTestAttr1: 987654321
_______________________________________________________________________
You can remove an auxiliary class from an object instance, and automatically have all associated attributes also removed. 

Sample LDIF for this:


version: 1
 
dn: cn=user1, o=novell
changetype: modify
delete:objectclass
objectclass: novlPerson2 
_______________________________________________________________________
You can delete an attribute or object class definition (auxiliary or otherwise) if it is no longer in use.   You must delete any classes (or remove the attributes from the optional list) that use an attribute before you can delete the attribute itself.  Note that if you recently deleted the objects or values using this definition, you will probably get an -644 error.  See comments above if that is the case. Sample LDIF for this:

version: 1

# delete an object class definition
dn: cn=schema
changetype: modify
delete: objectclasses
objectclasses: (2.16.840.1.113719.1.3.901 )

# delete attribute definition

dn: cn=schema
changetype: modify
delete: attributetypes
attributetypes: (2.16.840.1.113719.1.3.801)
_______________________________________________________________________

It is sometimes necessary to remove an optional attribute from an existing class definition.  One case encountered a bug in iManager LUM enabling a user (KB 7006482), where if a user has any of the mandatory attributes of the posixAccount auxiliary class already present in the user base class or any of the super classes, then those attributes won't be added by the LUM enabling process.  The workaround in that case is to remove the attributes from the schema definition, since they aren't there by default (except for uniqueID).  An example of how to do that follows.  Deleting optionals from a class definition is a custom process that must be done individually for each tree.  The process consists of reading the current definition, and then modifying that definition and then running the resulting LDIF script.


Step 1. Read the current definition.  For this example, we will read the Person class definition.  ldapsearch command will read the schema definition.  Note in this example, no host or port are given, so it will read the definition from the local host.  If you are not running this on the server directly, you will need to add those parameters.  Save this output to a file so we can edit it:
novl1:~ # ldapsearch -x -s base -b cn=schema objectClasses=Person  >person.ldif

The contents of the file will look similar to this:


novl1:~ # cat person.ldif

# extended LDIF
#
# LDAPv3
# base <cn=schema> with scope baseObject
# filter: objectClasses=Person
# requesting: ALL
#

# schema

dn: cn=schema
objectClasses: ( 2.5.6.6 NAME 'Person' SUP ndsLoginProperties STRUCTURAL MUST
 ( cn $ sn ) MAY ( description $ seeAlso $ telephoneNumber $ fullName $ givenN
 ame $ initials $ generationQualifier $ uid $ assistant $ assistantPhone $ cit
 y $ st $ company $ co $ directReports $ manager $ mailstop $ mobile $ persona
 lTitle $ pager $ workforceID $ instantMessagingID $ preferredName $ photo $ j
 obCode $ siteLocation $ employeeStatus $ employeeType $ costCenter $ costCent
 erDescription $ tollFreePhoneNumber $ otherPhoneNumber $ managerWorkforceID $
  roomNumber $ jackNumber $ departmentNumber $ vehicleInformation $ accessCard
 Number $ isManager $ gidNumber $ uidNumber $ userPassword ) X-NDS_NAMING ( 'c
 n' 'uid' ) X-NDS_CONTAINMENT ( 'Organization' 'organizationalUnit' 'domain' )
  X-NDS_NOT_CONTAINER '1' X-NDS_NONREMOVABLE '1' )

# search result

search: 2
result: 0 Success

# numResponses: 2

# numEntries: 1


Step 2: Edit the resulting output file to remove the comments from top and bottom, and add the required schema modification functions.  After editing, the file should look like this:


version: 1


# delete the uidNumber and gidNumber from current Person definition

dn: cn=schema
changetype: modify
delete: objectclasses
objectClasses: (2.5.6.6)
-
add: objectClasses
objectClasses: ( 2.5.6.6 NAME 'Person' SUP ndsLoginProperties STRUCTURAL MUST
 ( cn $ sn ) MAY ( description $ seeAlso $ telephoneNumber $ fullName $ givenN
 ame $ initials $ generationQualifier $ uid $ assistant $ assistantPhone $ cit
 y $ st $ company $ co $ directReports $ manager $ mailstop $ mobile $ persona
 lTitle $ pager $ workforceID $ instantMessagingID $ preferredName $ photo $ j
 obCode $ siteLocation $ employeeStatus $ employeeType $ costCenter $ costCent
 erDescription $ tollFreePhoneNumber $ otherPhoneNumber $ managerWorkforceID $
  roomNumber $ jackNumber $ departmentNumber $ vehicleInformation $ accessCard
 Number $ isManager $ userPassword ) X-NDS_NAMING ( 'c
 n' 'uid' ) X-NDS_CONTAINMENT ( 'Organization' 'organizationalUnit' 'domain' )
  X-NDS_NOT_CONTAINER '1' X-NDS_NONREMOVABLE '1' )

You can make the output "pretty" by unwrapping the lines, if desired.  But the LDIF file must still have a space at the beginning of each line that is a continuation of the current command.   I recommend just leaving the file as is, and only making the minimal changes needed to remove the attribute(s) you want removed from the definition.


Step 3: Run the ldif script.  Note that reading the schema does not require a user with rights, but modifying the schema does.

novl1:~ # ldapmodify -x -D cn=admin,o=novell -W -f person.ldif
Enter LDAP Password:
modifying entry "cn=schema"

The schema has now been changed.  The attributes that were removed from the person class definition in this instance are now not legal on any object of that class or object where Person is a superclass, like User, unless added back by a different class definition.  Running (n)dsrepair at this point will strip any values of the removed attributes that are present on any objects where they are now illegal.

Additional Information

You can perform any needed schema operation using LDIF scripts

Schema Modification rules: 
1) You can add or remove optional attributes to a class definition
2) You can add, but NOT remove mandatory attributes to a class definition (effective or auxiliary)
3) You can only add naming values to a class definition if it already has explicit (not inherited) naming.  You can not delete naming values from a class definition
4) You can add but not delete superclass values to a class definition
These rules are for preventing a previously legal object from begin made illegal by a schema change.  These rules are enforce by eDirectory, not by LDAP or LDIF processing.

Formerly known as TID# 10088759

Modifying the schema,is potentially a dangerous operation.
Therefore it is highly recommended to test any change in a test environment first.
Not only deleting attributes or object classes could lead to data loss, also changing existing attribute definitions or object classes could result in data data loss.
For more information refer to: KB 701639 - Data values lost if attribute's syntax is changed and is in use on objects.