s4: Remove autogenerated attributes from minschema and fullschema output
[kai/samba.git] / source4 / scripting / bin / fullschema
1 #!/usr/bin/python
2
3 #  work out the minimal schema for a set of objectclasses 
4 #
5
6 import base64
7 import optparse
8 import os
9 import sys
10
11 # Find right directory when running from source tree
12 sys.path.insert(0, "bin/python")
13
14 import samba
15 from samba import getopt as options, Ldb
16 from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError
17 import sys
18
19 parser = optparse.OptionParser("fullschema <URL>")
20 sambaopts = options.SambaOptions(parser)
21 parser.add_option_group(sambaopts)
22 credopts = options.CredentialsOptions(parser)
23 parser.add_option_group(credopts)
24 parser.add_option_group(options.VersionOptions(parser))
25 parser.add_option("--dump-classes", action="store_true")
26 parser.add_option("--dump-attributes", action="store_true")
27
28 opts, args = parser.parse_args()
29 opts.dump_all = True
30
31 if opts.dump_classes:
32     opts.dump_all = False
33 if opts.dump_attributes:
34     opts.dump_all = False
35 if opts.dump_all:
36     opts.dump_classes = True
37     opts.dump_attributes = True
38
39 if len(args) != 1:
40     parser.print_usage()
41     sys.exit(1)
42
43 url = args[0]
44
45 lp_ctx = sambaopts.get_loadparm()
46
47 creds = credopts.get_credentials(lp_ctx)
48 ldb = Ldb(url, credentials=creds, lp=lp_ctx, options=["modules:paged_searches"])
49
50 # the attributes we need for objectclasses
51 class_attrs = ["objectClass", 
52                "cn",
53                "subClassOf", 
54                "governsID", 
55                "possSuperiors", 
56                "possibleInferiors",
57                "mayContain",
58                "mustContain",
59                "auxiliaryClass",
60                "rDNAttID",
61                "adminDisplayName",
62                "adminDescription",
63                "objectClassCategory",
64                "lDAPDisplayName",
65                "schemaIDGUID",
66                "systemOnly",
67                "systemPossSuperiors",
68                "systemMayContain",
69                "systemMustContain",
70                "systemAuxiliaryClass",
71                "defaultSecurityDescriptor",
72                "systemFlags",
73                "defaultHidingValue",
74                "defaultObjectCategory", 
75                
76                # this attributes are not used by w2k3
77                "schemaFlagsEx",
78                "msDs-IntId",
79                "msDs-Schema-Extensions",
80                "classDisplayName",
81                "isDefunct"]
82
83 attrib_attrs = ["objectClass",
84                 "cn",
85                 "attributeID", 
86                 "attributeSyntax",
87                 "isSingleValued",
88                 "rangeLower",
89                 "rangeUpper",
90                 "mAPIID",
91                 "linkID",
92                 "adminDisplayName",
93                 "oMObjectClass",
94                 "adminDescription",
95                 "oMSyntax", 
96                 "searchFlags",
97                 "extendedCharsAllowed",
98                 "lDAPDisplayName",
99                 "schemaIDGUID",
100                 "attributeSecurityGUID",
101                 "systemOnly",
102                 "systemFlags",
103                 "isMemberOfPartialAttributeSet",
104                 
105                 # this attributes are not used by w2k3
106                 "schemaFlagsEx",
107                 "msDs-IntId",
108                 "msDs-Schema-Extensions",
109                 "classDisplayName",
110                 "isEphemeral",
111                 "isDefunct"]
112
113 class Objectclass(dict):
114
115     def __init__(self, ldb, name):
116         """create an objectclass object"""
117         self.name = name
118
119
120 class Attribute(dict):
121
122     def __init__(self, ldb, name):
123         """create an attribute object"""
124         self.name = name
125         self["cn"] = get_object_cn(ldb, name)
126
127
128
129 def fix_dn(dn):
130     """fix a string DN to use ${SCHEMADN}"""
131     return dn.replace(rootDse["schemaNamingContext"][0], "${SCHEMADN}")
132
133
134 def write_ldif_one(o, attrs):
135     """dump an object as ldif"""
136     print "dn: CN=%s,${SCHEMADN}" % o["cn"]
137     for a in attrs:
138         if not o.has_key(a):
139             continue
140         # special case for oMObjectClass, which is a binary object
141         v = o[a]
142         for j in v:
143             value = fix_dn(j)
144             if a != "cn":
145                 if a == "oMObjectClass":
146                     print "%s:: %s" % (a, base64.b64encode(value))
147                 elif a.endswith("GUID"):
148                     print "%s: %s" % (a, ldb.schema_format_value(a, value))
149                 else:
150                     print "%s: %s" % (a, value)
151     print ""
152
153
154 # get the rootDSE
155 res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
156 rootDse = res[0]
157
158 if opts.dump_attributes:
159     res = ldb.search(expression="objectClass=attributeSchema", 
160                      base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs)
161     
162     for msg in res:
163         o = Objectclass(ldb, msg["ldapDisplayName"])
164         for a in msg:
165             o[a] = msg[a]
166         write_ldif_one(o, attrib_attrs)
167             
168 if opts.dump_classes:
169     res = ldb.search(expression="objectClass=classSchema", 
170                      base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs)
171
172     for msg in res:
173         o = Objectclass(ldb, msg["ldapDisplayName"])
174         for a in msg:
175             o[a] = msg[a]
176         write_ldif_one(o, class_attrs)
177