da97433d5cd26e422a370d186f98659383c06721csovant#!/usr/bin/python
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant# CDDL HEADER START
da97433d5cd26e422a370d186f98659383c06721csovant#
da97433d5cd26e422a370d186f98659383c06721csovant# The contents of this file are subject to the terms of the
da97433d5cd26e422a370d186f98659383c06721csovant# Common Development and Distribution License, Version 1.0 only
da97433d5cd26e422a370d186f98659383c06721csovant# (the "License"). You may not use this file except in compliance
da97433d5cd26e422a370d186f98659383c06721csovant# with the License.
da97433d5cd26e422a370d186f98659383c06721csovant#
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac# You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac# or http://forgerock.org/license/CDDLv1.0.html.
da97433d5cd26e422a370d186f98659383c06721csovant# See the License for the specific language governing permissions
da97433d5cd26e422a370d186f98659383c06721csovant# and limitations under the License.
da97433d5cd26e422a370d186f98659383c06721csovant#
da97433d5cd26e422a370d186f98659383c06721csovant# When distributing Covered Code, include this CDDL HEADER in each
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac# file and include the License file at legal-notices/CDDLv1_0.txt.
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac# If applicable, add the following below this CDDL HEADER, with the
3437829f938dbb44527d91fbbc5f430a1243c5a5JnRouvignac# fields enclosed by brackets "[]" replaced with your own identifying
da97433d5cd26e422a370d186f98659383c06721csovant# information:
da97433d5cd26e422a370d186f98659383c06721csovant# Portions Copyright [yyyy] [name of copyright owner]
da97433d5cd26e422a370d186f98659383c06721csovant#
da97433d5cd26e422a370d186f98659383c06721csovant# CDDL HEADER END
da97433d5cd26e422a370d186f98659383c06721csovant#
da97433d5cd26e422a370d186f98659383c06721csovant#
da97433d5cd26e422a370d186f98659383c06721csovant# Copyright 2009 Sun Microsystems, Inc.
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant# Global variable containing the list of servers ("Server" class instances) deployed
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant# Define ChangelogServer class
da97433d5cd26e422a370d186f98659383c06721csovantclass OIDDict:
da97433d5cd26e422a370d186f98659383c06721csovant """OIDDict is a dictionary class that help lookup OID <-> litteral name
da97433d5cd26e422a370d186f98659383c06721csovant of both objeclasses, and attributtypes"""
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def __init__(self, schema=None):
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.attrDict = {}
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.objDict = {}
da97433d5cd26e422a370d186f98659383c06721csovant self.sup = {}
da97433d5cd26e422a370d186f98659383c06721csovant self.may = {}
da97433d5cd26e422a370d186f98659383c06721csovant self.must = {}
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.allmay = []
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.allmust = []
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def _getOID(self, line):
da97433d5cd26e422a370d186f98659383c06721csovant """given a schema entry definition for objectclass/attributtype
da97433d5cd26e422a370d186f98659383c06721csovant return the tuple (OID,List of names)
da97433d5cd26e422a370d186f98659383c06721csovant the List of aliases starts from list of names[1:] when exist. for ex :
da97433d5cd26e422a370d186f98659383c06721csovant attributeTypes: ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name X-ORIGIN 'RFC 4519' )
da97433d5cd26e422a370d186f98659383c06721csovant (2.5.4.4,['sn','surname']
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant More details : https://www.opends.org/wiki/page/AttributeTypeDescriptionFormat
da97433d5cd26e422a370d186f98659383c06721csovant """
da97433d5cd26e422a370d186f98659383c06721csovant pNdx = line.find('(')
da97433d5cd26e422a370d186f98659383c06721csovant nNdx = line.find('NAME',pNdx)
da97433d5cd26e422a370d186f98659383c06721csovant OID = line[pNdx+1:nNdx].strip()
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant # populate the NAME to OID : "dict" dictionary
da97433d5cd26e422a370d186f98659383c06721csovant NAMES = self._getStr(line,'NAME')
da97433d5cd26e422a370d186f98659383c06721csovant if NAMES:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant if line.startswith('objectClasses:'):
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant # TODO encoded schema is not handled for now
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.objDict.update({OID:NAMES})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for name in NAMES:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.objDict.update({name:OID})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant elif line.startswith('attributeTypes:'):
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant # TODO encoded schema is not handled for now
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.attrDict.update({OID:NAMES})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for name in NAMES:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.attrDict.update({name:OID})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant # populate SUP and MUST / MAY, : "sup", "may", "must" dictionaries
da97433d5cd26e422a370d186f98659383c06721csovant if line.startswith('objectClasses:'):
da97433d5cd26e422a370d186f98659383c06721csovant r = self._getStr(line,'SUP')
da97433d5cd26e422a370d186f98659383c06721csovant if r:
da97433d5cd26e422a370d186f98659383c06721csovant self.sup.update({NAMES[0]:r})
da97433d5cd26e422a370d186f98659383c06721csovant r = self._getStr(line,'MUST')
da97433d5cd26e422a370d186f98659383c06721csovant if r:
da97433d5cd26e422a370d186f98659383c06721csovant self.must.update({NAMES[0]:r})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for m in r:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant if not m in self.allmust:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.allmust.append(m)
da97433d5cd26e422a370d186f98659383c06721csovant r = self._getStr(line,'MAY')
da97433d5cd26e422a370d186f98659383c06721csovant if r:
da97433d5cd26e422a370d186f98659383c06721csovant self.may.update({NAMES[0]:r})
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for m in r:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant if not m in self.allmay:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self.allmay.append(m)
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant return OID, NAMES
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def _getStr(self, line, myStr, right=None):
da97433d5cd26e422a370d186f98659383c06721csovant """extract a list of attributes for a given myStr section.
da97433d5cd26e422a370d186f98659383c06721csovant The section should contain () when multivalued.
da97433d5cd26e422a370d186f98659383c06721csovant If another section comes after it starts with a Upercase.
da97433d5cd26e422a370d186f98659383c06721csovant example MUST (sn cn) MAY ( description ... )
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant line : line to parse
da97433d5cd26e422a370d186f98659383c06721csovant myStr : name of the section ex(MAY)
da97433d5cd26e422a370d186f98659383c06721csovant right : right boundary,
da97433d5cd26e422a370d186f98659383c06721csovant if None, function will figure out end of section"""
da97433d5cd26e422a370d186f98659383c06721csovant left = line.find(myStr)
da97433d5cd26e422a370d186f98659383c06721csovant if left == -1:
da97433d5cd26e422a370d186f98659383c06721csovant return None
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant if not right:
da97433d5cd26e422a370d186f98659383c06721csovant right = len(line)
da97433d5cd26e422a370d186f98659383c06721csovant lpNdx = line.find('(', left)
da97433d5cd26e422a370d186f98659383c06721csovant if lpNdx > 0:
da97433d5cd26e422a370d186f98659383c06721csovant spaces=line[left+len(myStr) : lpNdx]
da97433d5cd26e422a370d186f98659383c06721csovant if len(spaces.strip()) == 0:
da97433d5cd26e422a370d186f98659383c06721csovant right = line.find(')',lpNdx)
da97433d5cd26e422a370d186f98659383c06721csovant left = lpNdx + 1
da97433d5cd26e422a370d186f98659383c06721csovant else:
da97433d5cd26e422a370d186f98659383c06721csovant left = left+len(myStr)+1
da97433d5cd26e422a370d186f98659383c06721csovant else:
da97433d5cd26e422a370d186f98659383c06721csovant left = left+len(myStr)
da97433d5cd26e422a370d186f98659383c06721csovant strs = line[left:right]
da97433d5cd26e422a370d186f98659383c06721csovant realStrs = []
da97433d5cd26e422a370d186f98659383c06721csovant for s in strs.split(' '):
da97433d5cd26e422a370d186f98659383c06721csovant if len(s) > 0:
da97433d5cd26e422a370d186f98659383c06721csovant if s[0] >= 'A' and s[0] <= 'Z':
da97433d5cd26e422a370d186f98659383c06721csovant break
da97433d5cd26e422a370d186f98659383c06721csovant elif s[0] != '$' and s[0] != '|':
da97433d5cd26e422a370d186f98659383c06721csovant if s[0] == '\'' and s[-1] == '\'':
da97433d5cd26e422a370d186f98659383c06721csovant s = s[1:-1]
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant realStrs.append(s.lower())
da97433d5cd26e422a370d186f98659383c06721csovant return realStrs
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def getMust(self, objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant """will return the attributes the objectclassname MUST implement"""
da97433d5cd26e422a370d186f98659383c06721csovant if self.must.has_key(objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant ret = self.must.get(objectclassname)
da97433d5cd26e422a370d186f98659383c06721csovant else:
da97433d5cd26e422a370d186f98659383c06721csovant ret = []
da97433d5cd26e422a370d186f98659383c06721csovant for h in self.getHierarchy(objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant # avoiding duplication of MUSTs
da97433d5cd26e422a370d186f98659383c06721csovant ret.extend([e for e in self.getMust(h) if ret.count(e) == 0])
da97433d5cd26e422a370d186f98659383c06721csovant return ret
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def getMay(self, objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant """will return the attributes the objectclassname MAY implement"""
da97433d5cd26e422a370d186f98659383c06721csovant if self.may.has_key(objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant ret = self.may.get(objectclassname)
da97433d5cd26e422a370d186f98659383c06721csovant else:
da97433d5cd26e422a370d186f98659383c06721csovant ret = []
da97433d5cd26e422a370d186f98659383c06721csovant for h in self.getHierarchy(objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant # avoiding duplication of MAYs
da97433d5cd26e422a370d186f98659383c06721csovant ret.extend([e for e in self.getMay(h) if ret.count(e) == 0])
da97433d5cd26e422a370d186f98659383c06721csovant return ret
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def getSup(self, objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant """will return the objectclassname that this objectclassname inherit"""
da97433d5cd26e422a370d186f98659383c06721csovant if objectclassname == 'top':
da97433d5cd26e422a370d186f98659383c06721csovant return None
da97433d5cd26e422a370d186f98659383c06721csovant else:
da97433d5cd26e422a370d186f98659383c06721csovant ret = self.sup.get(objectclassname)
da97433d5cd26e422a370d186f98659383c06721csovant return ret[0]
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def getHierarchy(self, objectclassname):
da97433d5cd26e422a370d186f98659383c06721csovant hierachy = []
da97433d5cd26e422a370d186f98659383c06721csovant up = self.getSup(objectclassname)
da97433d5cd26e422a370d186f98659383c06721csovant while up:
da97433d5cd26e422a370d186f98659383c06721csovant if hierachy.count(up) == 0:
da97433d5cd26e422a370d186f98659383c06721csovant hierachy.append(up)
da97433d5cd26e422a370d186f98659383c06721csovant up = self.getSup(up)
da97433d5cd26e422a370d186f98659383c06721csovant return hierachy
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant def parseSchema(self, ref_content):
da97433d5cd26e422a370d186f98659383c06721csovant """get the schema as a string
da97433d5cd26e422a370d186f98659383c06721csovant lookit up line by line, extracting OID/literal name for objectclasses
da97433d5cd26e422a370d186f98659383c06721csovant and attributetypes only."""
da97433d5cd26e422a370d186f98659383c06721csovant lines=[]
da97433d5cd26e422a370d186f98659383c06721csovant line=''
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for f in ref_content.splitlines():
da97433d5cd26e422a370d186f98659383c06721csovant if len(line) == 0 and \
da97433d5cd26e422a370d186f98659383c06721csovant not (f.startswith("objectClasses") or \
da97433d5cd26e422a370d186f98659383c06721csovant f.startswith("attributeTypes")):
da97433d5cd26e422a370d186f98659383c06721csovant # not handled for now
da97433d5cd26e422a370d186f98659383c06721csovant continue
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant elif len(line) > 0 and len(f) > 0 and f[0].isspace():
da97433d5cd26e422a370d186f98659383c06721csovant # line continuation aggregated into 'line'
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant line += f[1:]
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovant elif f.startswith("objectClasses") or f.startswith("attributeTypes"):
da97433d5cd26e422a370d186f98659383c06721csovant if len(line) > 0:
da97433d5cd26e422a370d186f98659383c06721csovant lines.append(line)
da97433d5cd26e422a370d186f98659383c06721csovant # populate the OID <-> Names dictionary
da97433d5cd26e422a370d186f98659383c06721csovant self._getOID(line)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant line = f[:-1]
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant line = f
da97433d5cd26e422a370d186f98659383c06721csovant if len(line) > 0:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant # parsing the last line
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant self._getOID(line)
da97433d5cd26e422a370d186f98659383c06721csovant lines.append(line)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant f=open('/tmp/lines.ldif','w')
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant f.write('\n'.join(lines))
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant f.close()
da97433d5cd26e422a370d186f98659383c06721csovant
da97433d5cd26e422a370d186f98659383c06721csovantif __name__ == '__main__':
da97433d5cd26e422a370d186f98659383c06721csovant """get example schema.ldif file with :
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant ldapsearch -b 'cn=schema' -Dcn=directory\ manager -s base -wpassword objectclass=* objectClasses attributeTypes > /tmp/schema.ldif
da97433d5cd26e422a370d186f98659383c06721csovant """
da97433d5cd26e422a370d186f98659383c06721csovant objectClassesFileName='/tmp/schema.ldif'
da97433d5cd26e422a370d186f98659383c06721csovant f = open(objectClassesFileName)
da97433d5cd26e422a370d186f98659383c06721csovant fc = f.readlines()
da97433d5cd26e422a370d186f98659383c06721csovant f.close()
da97433d5cd26e422a370d186f98659383c06721csovant oidDict = OIDDict()
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant oidDict.parseSchema(''.join(fc))
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print '[ Objectclasses dictionary ]'.center(80, '-')
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for k,v in oidDict.objDict.items():
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print "%s\t%s"%(k,v)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print '[ AttributeTypes dictionary ]'.center(80, '-')
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for k,v in oidDict.attrDict.items():
da97433d5cd26e422a370d186f98659383c06721csovant print "%s\t%s"%(k,v)
da97433d5cd26e422a370d186f98659383c06721csovant print '[ must ]'.center(80, '-')
da97433d5cd26e422a370d186f98659383c06721csovant for k,v in oidDict.must.items():
da97433d5cd26e422a370d186f98659383c06721csovant print "%s\t%s"%(k,v)
da97433d5cd26e422a370d186f98659383c06721csovant print '[ may ]'.center(80, '-')
da97433d5cd26e422a370d186f98659383c06721csovant for k,v in oidDict.may.items():
da97433d5cd26e422a370d186f98659383c06721csovant print "%s\t%s"%(k,v)
da97433d5cd26e422a370d186f98659383c06721csovant print '[ sup ]'.center(80, '-')
da97433d5cd26e422a370d186f98659383c06721csovant for k,v in oidDict.sup.items():
da97433d5cd26e422a370d186f98659383c06721csovant print "%s\t%s"%(k,v)
da97433d5cd26e422a370d186f98659383c06721csovant for cn in ['rFC822LocalPart','inetOrgPerson','top','doMain','2.5.6.7','BLAH']:
da97433d5cd26e422a370d186f98659383c06721csovant print cn.center(80, '-')
da97433d5cd26e422a370d186f98659383c06721csovant try:
da97433d5cd26e422a370d186f98659383c06721csovant print 'SUP'.center(40,'.')
da97433d5cd26e422a370d186f98659383c06721csovant print 'SUP',oidDict.getSup(cn)
da97433d5cd26e422a370d186f98659383c06721csovant print 'HIERARCHY',oidDict.getHierarchy(cn)
da97433d5cd26e422a370d186f98659383c06721csovant print 'MUST'.center(40,'.')
da97433d5cd26e422a370d186f98659383c06721csovant print 'MUST',oidDict.getMust(cn)
da97433d5cd26e422a370d186f98659383c06721csovant print 'MAY'.center(40,'.')
da97433d5cd26e422a370d186f98659383c06721csovant print 'MAY',oidDict.getMay(cn)
da97433d5cd26e422a370d186f98659383c06721csovant except Exception, e:
da97433d5cd26e422a370d186f98659383c06721csovant print e.message
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print '[ all must ]'.center(80,'-')
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant mustSize = 0
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for m in oidDict.allmust:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant mustSize += len(m)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print 'got %s MUSTs size = %sKb' % (len(oidDict.allmust),mustSize/1024.0)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print oidDict.allmust
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print '[ all may ]'.center(80,'-')
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant maySize = 0
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant for m in oidDict.allmay:
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant maySize += len(m)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print 'got %s MAYs size = %sKb' % (len(oidDict.allmay),maySize/1024.0)
28eeffb99d4c7f8ff501c22d1d21501cbfe3ad32csovant print oidDict.allmay