|
Lines 68-126
if listener.baseConfig['ldap/server/type'] == 'slave':
Link Here
|
| 68 |
if listener.baseConfig['ldap/slave/filter']: |
68 |
if listener.baseConfig['ldap/slave/filter']: |
| 69 |
filter=listener.baseConfig['ldap/slave/filter'] |
69 |
filter=listener.baseConfig['ldap/slave/filter'] |
| 70 |
|
70 |
|
| 71 |
# |
|
|
| 72 |
# init flatmode if enabled |
| 73 |
# |
| 74 |
flatmode = False |
| 75 |
flatmode_ldap={ 'lo': None } |
| 76 |
flatmode_mapping = [] |
| 77 |
flatmode_container = {} |
| 78 |
flatmode_module_prefix = 'ldap/replication/flatmode/module/' |
| 79 |
flatmode_container_prefix = 'ldap/replication/flatmode/container/' |
| 80 |
|
| 81 |
univention.debug.debug( |
| 82 |
univention.debug.LISTENER, |
| 83 |
univention.debug.INFO, |
| 84 |
'replication flatmode enabled by UCR: %s' % listener.baseConfig.get('ldap/replication/flatmode','no')) |
| 85 |
|
| 86 |
if listener.baseConfig.is_true('ldap/replication/flatmode', False): |
| 87 |
# flatmode is enabled |
| 88 |
try: |
| 89 |
import univention.admin.uldap |
| 90 |
import univention.admin.objects |
| 91 |
import univention.admin.modules |
| 92 |
except Exception, ex: |
| 93 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'cannot import univention directory manager modules: %s' % str(ex)) |
| 94 |
else: |
| 95 |
# all modules imported |
| 96 |
for key_mod in listener.baseConfig.keys(): |
| 97 |
# iterate over all UCR variables |
| 98 |
if key_mod.startswith( flatmode_module_prefix ): |
| 99 |
# found module entry |
| 100 |
id=key_mod[ len( flatmode_module_prefix ) : ] |
| 101 |
val_mod = listener.baseConfig[ key_mod ] |
| 102 |
# find container entry |
| 103 |
key_cn = '%s%s' % (flatmode_container_prefix, id) |
| 104 |
if listener.baseConfig.get(key_cn): |
| 105 |
val_cn = listener.baseConfig[ key_cn ] |
| 106 |
# get module |
| 107 |
mod = univention.admin.modules.get( val_mod ) |
| 108 |
if not mod: |
| 109 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'replication flatmode: could not get module %s' % val_mod) |
| 110 |
else: |
| 111 |
entry = { 'module': mod, 'type': val_mod, 'container': val_cn } |
| 112 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: saving objects of type %s in %s' % (val_mod, val_cn)) |
| 113 |
flatmode_mapping.append( entry ) |
| 114 |
flatmode_container[ val_cn ] = False |
| 115 |
flatmode = True |
| 116 |
else: |
| 117 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'replication flatmode: cannot find UCR variable %s' % key_cn) |
| 118 |
|
| 119 |
univention.debug.debug( |
| 120 |
univention.debug.LISTENER, |
| 121 |
univention.debug.INFO, |
| 122 |
'replication flatmode activated: %s' % flatmode) |
| 123 |
|
| 124 |
STATE_DIR = '/var/lib/univention-directory-replication' |
71 |
STATE_DIR = '/var/lib/univention-directory-replication' |
| 125 |
LDIF_FILE = os.path.join(STATE_DIR, 'failed.ldif') |
72 |
LDIF_FILE = os.path.join(STATE_DIR, 'failed.ldif') |
| 126 |
|
73 |
|
|
Lines 561-567
def connect(ldif=0):
Link Here
|
| 561 |
|
508 |
|
| 562 |
local_ip='127.0.0.1' |
509 |
local_ip='127.0.0.1' |
| 563 |
local_port=listener.baseConfig.get('slapd/port', '7389').split(',')[0] |
510 |
local_port=listener.baseConfig.get('slapd/port', '7389').split(',')[0] |
| 564 |
|
511 |
|
| 565 |
try: |
512 |
try: |
| 566 |
connection=ldap.open(local_ip, int(local_port)) |
513 |
connection=ldap.open(local_ip, int(local_port)) |
| 567 |
connection.simple_bind_s('cn=update,'+listener.baseConfig['ldap/base'], pw) |
514 |
connection.simple_bind_s('cn=update,'+listener.baseConfig['ldap/base'], pw) |
|
Lines 625-632
def update_schema(attr):
Link Here
|
| 625 |
finally: |
572 |
finally: |
| 626 |
listener.unsetuid() |
573 |
listener.unsetuid() |
| 627 |
|
574 |
|
| 628 |
queue = [] |
|
|
| 629 |
|
| 630 |
print >>fp, '# This schema was automatically replicated from the master server' |
575 |
print >>fp, '# This schema was automatically replicated from the master server' |
| 631 |
print >>fp, '# Please do not edit this file\n' |
576 |
print >>fp, '# Please do not edit this file\n' |
| 632 |
subschema = ldap.schema.SubSchema(attr) |
577 |
subschema = ldap.schema.SubSchema(attr) |
|
Lines 674-810
def getOldValues( ldapconn, dn ):
Link Here
|
| 674 |
|
619 |
|
| 675 |
return old |
620 |
return old |
| 676 |
|
621 |
|
| 677 |
# check if target container exists; this function creates required containers if they are missing |
|
|
| 678 |
def flatmodeCreateContainer( ldapconn, dn ): |
| 679 |
if dn in flatmode_container: |
| 680 |
if flatmode_container[dn]: |
| 681 |
return |
| 682 |
|
| 683 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: testing required container: %s' % dn) |
| 684 |
old = getOldValues( ldapconn, dn ) |
| 685 |
|
| 686 |
if not old: |
| 687 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: required container does not exist: %s' % dn) |
| 688 |
tmpdn='' |
| 689 |
dnparts = univention.admin.uldap.explodeDn(dn, 0) |
| 690 |
dnparts.reverse() |
| 691 |
for dnpart in dnparts: |
| 692 |
if tmpdn: |
| 693 |
tmpdn = '%s,%s' % (dnpart, tmpdn) |
| 694 |
else: |
| 695 |
tmpdn = dnpart |
| 696 |
|
| 697 |
tmpold = {} |
| 698 |
tmpnew = {} |
| 699 |
objtype, objname = dnpart.split('=',1) |
| 700 |
if objtype == 'cn' or objtype == 'ou': |
| 701 |
# check if object exists in local ldap tree |
| 702 |
tmpold = getOldValues( ldapconn, tmpdn ) |
| 703 |
|
| 704 |
if objtype == 'cn' and not tmpold: |
| 705 |
tmpnew = { 'cn': [ objname ], 'objectClass': [ 'top', 'organizationalRole' ] } |
| 706 |
elif objtype == 'ou' and not tmpold: |
| 707 |
tmpnew = { 'ou': [ objname ], 'objectClass': [ 'top', 'organizationalUnit' ] } |
| 708 |
|
| 709 |
if tmpnew: |
| 710 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: creating required container: %s' % tmpdn) |
| 711 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'replication flatmode: calling handle( %s, tmpnew, tmpold ):\ntmpnew=%s' % (tmpdn, tmpnew)) |
| 712 |
handler( tmpdn, tmpnew, tmpold ) |
| 713 |
flatmode_container[dn] = True |
| 714 |
|
| 715 |
|
| 716 |
# This function converts object dn and object attributes for flatmode. |
| 717 |
# Special convertions for aach module type have to be added here. |
| 718 |
# "new" is modified "by reference" |
| 719 |
# the new value for "dn" is returned ("call by value") |
| 720 |
def flatmodeConvertObject( entry, dn, new ): |
| 721 |
global flatmode_mapping |
| 722 |
|
| 723 |
# map DN |
| 724 |
rdn = univention.admin.uldap.explodeDn(dn, 0)[0] |
| 725 |
dn = '%s,%s' % (rdn, entry['container']) |
| 726 |
|
| 727 |
# correct entryDN |
| 728 |
if new: |
| 729 |
new['entryDN'][0] = dn |
| 730 |
|
| 731 |
if new.get('uniqueMember'): |
| 732 |
if flatmode_ldap['lo'] is None: |
| 733 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'replication flatmode: second ldap connection is not established - local replica may be corrupt!') |
| 734 |
else: |
| 735 |
newMemberDNs = [] |
| 736 |
# convert all existing uniqueMember DNs |
| 737 |
for memberdn in new['uniqueMember']: |
| 738 |
try: |
| 739 |
obj = flatmode_ldap['lo'].get(memberdn,[]) |
| 740 |
except Exception, ex: |
| 741 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: could not get member %s' % memberdn) |
| 742 |
obj = None |
| 743 |
|
| 744 |
newmember = memberdn |
| 745 |
if obj: |
| 746 |
for entry in flatmode_mapping: |
| 747 |
# test if memberdn should also be remapped |
| 748 |
if entry['module'].identify( memberdn, obj ) or entry['module'].identify( memberdn, obj ): |
| 749 |
|
| 750 |
rdn = univention.admin.uldap.explodeDn(memberdn, 0)[0] |
| 751 |
newmember = '%s,%s' % (rdn, entry['container']) |
| 752 |
break |
| 753 |
|
| 754 |
newMemberDNs.append( newmember ) |
| 755 |
# set new DNs |
| 756 |
new['uniqueMember'] = newMemberDNs |
| 757 |
|
| 758 |
return dn |
| 759 |
|
| 760 |
# if flatmode is enabled handlerFlatmode checks for every object if mapping is required |
| 761 |
# if examined object matches to mapping "dn" and "new" are converted by flatmodeConvertObject |
| 762 |
def handlerFlatmode( ldapconn, dn, new, old ): |
| 763 |
global flatmode |
| 764 |
global flatmode_mapping |
| 765 |
global flatmode_container |
| 766 |
|
| 767 |
if not flatmode: |
| 768 |
return dn |
| 769 |
newdn = dn |
| 770 |
|
| 771 |
if dn in flatmode_container: |
| 772 |
flatmode_container[dn] = True |
| 773 |
|
| 774 |
for entry in flatmode_mapping: |
| 775 |
if entry['module'].identify( dn, new ) or entry['module'].identify( dn, old ): |
| 776 |
|
| 777 |
newdn = flatmodeConvertObject( entry, dn, new ) |
| 778 |
|
| 779 |
# test if required container is present |
| 780 |
if not flatmode_container[ entry['container'] ]: |
| 781 |
flatmodeCreateContainer( ldapconn, entry['container'] ) |
| 782 |
|
| 783 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'replication flatmode: mapped %s to %s' % (dn, newdn)) |
| 784 |
return newdn |
| 785 |
|
| 786 |
return newdn |
| 787 |
|
| 788 |
|
| 789 |
def flatmode_reconnect(): |
| 790 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication flatmode: ldap reconnect triggered') |
| 791 |
if ( flatmode_ldap.get('ldapserver') and \ |
| 792 |
flatmode_ldap.get('basedn') and \ |
| 793 |
flatmode_ldap.get('binddn') and \ |
| 794 |
flatmode_ldap.get('bindpw')): |
| 795 |
try: |
| 796 |
flatmode_ldap['lo'] = univention.uldap.access( host = flatmode_ldap['ldapserver'], |
| 797 |
base = flatmode_ldap['basedn'], |
| 798 |
binddn = flatmode_ldap['binddn'], |
| 799 |
bindpw = flatmode_ldap['bindpw'], |
| 800 |
start_tls = 2 ) |
| 801 |
except Exception, ex: |
| 802 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'replication flatmode: ldap reconnect failed: %s' % str(ex)) |
| 803 |
flatmode_ldap['lo'] = None |
| 804 |
else: |
| 805 |
if flatmode_ldap['lo'] is None: |
| 806 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, 'replication flatmode: ldap reconnect failed') |
| 807 |
|
| 808 |
def _delete_dn_recursive(l, dn): |
622 |
def _delete_dn_recursive(l, dn): |
| 809 |
try: |
623 |
try: |
| 810 |
l.delete_s(dn) |
624 |
l.delete_s(dn) |
|
Lines 824-842
def _backup_dn_recursive(l, dn):
Link Here
|
| 824 |
if not os.path.exists(backup_directory): |
638 |
if not os.path.exists(backup_directory): |
| 825 |
os.makedirs(backup_directory) |
639 |
os.makedirs(backup_directory) |
| 826 |
os.chmod(backup_directory, 0700) |
640 |
os.chmod(backup_directory, 0700) |
| 827 |
|
641 |
|
| 828 |
backup_file = os.path.join(backup_directory, str(time.time())) |
642 |
backup_file = os.path.join(backup_directory, str(time.time())) |
| 829 |
fd = open(backup_file, 'w+') |
643 |
fd = open(backup_file, 'w+') |
| 830 |
fd.close() |
644 |
fd.close() |
| 831 |
os.chmod(backup_file, 0600) |
645 |
os.chmod(backup_file, 0600) |
| 832 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.PROCESS, 'replication: dump %s to %s' % (dn, backup_file)) |
646 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.PROCESS, 'replication: dump %s to %s' % (dn, backup_file)) |
| 833 |
|
647 |
|
| 834 |
fd = open(backup_file, 'w+') |
648 |
fd = open(backup_file, 'w+') |
| 835 |
ldif_writer = ldifparser.LDIFWriter(fd) |
649 |
ldif_writer = ldifparser.LDIFWriter(fd) |
| 836 |
for dn,entry in l.search_s(dn, ldap.SCOPE_SUBTREE, '(objectClass=*)', attrlist=['*', '+']): |
650 |
for dn,entry in l.search_s(dn, ldap.SCOPE_SUBTREE, '(objectClass=*)', attrlist=['*', '+']): |
| 837 |
ldif_writer.unparse(dn,entry) |
651 |
ldif_writer.unparse(dn,entry) |
| 838 |
fd.close() |
652 |
fd.close() |
| 839 |
|
653 |
|
| 840 |
def _get_current_modrdn_link(): |
654 |
def _get_current_modrdn_link(): |
| 841 |
return os.path.join(STATE_DIR, 'current_modrdn') |
655 |
return os.path.join(STATE_DIR, 'current_modrdn') |
| 842 |
|
656 |
|
|
Lines 874-880
def _read_dn_from_file(filename):
Link Here
|
| 874 |
def handler(dn, new, listener_old, operation): |
688 |
def handler(dn, new, listener_old, operation): |
| 875 |
global reconnect |
689 |
global reconnect |
| 876 |
global slave |
690 |
global slave |
| 877 |
global flatmode |
|
|
| 878 |
if not slave: |
691 |
if not slave: |
| 879 |
return 1 |
692 |
return 1 |
| 880 |
|
693 |
|
|
Lines 908-916
def handler(dn, new, listener_old, operation):
Link Here
|
| 908 |
else: |
721 |
else: |
| 909 |
connected=1 |
722 |
connected=1 |
| 910 |
|
723 |
|
| 911 |
if flatmode: |
|
|
| 912 |
dn = handlerFlatmode( l, dn, new, listener_old ) |
| 913 |
|
| 914 |
try: |
724 |
try: |
| 915 |
|
725 |
|
| 916 |
if listener.baseConfig.get('ldap/replication/filesystem/check', 'false').lower() in ['true', 'yes']: |
726 |
if listener.baseConfig.get('ldap/replication/filesystem/check', 'false').lower() in ['true', 'yes']: |
|
Lines 1035-1041
def handler(dn, new, listener_old, operation):
Link Here
|
| 1035 |
_delete_dn_recursive(l, old_dn) |
845 |
_delete_dn_recursive(l, old_dn) |
| 1036 |
else: |
846 |
else: |
| 1037 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication: no old dn has been found') |
847 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication: no old dn has been found') |
| 1038 |
|
848 |
|
| 1039 |
if not old: |
849 |
if not old: |
| 1040 |
_add_object_from_new(l, dn, new) |
850 |
_add_object_from_new(l, dn, new) |
| 1041 |
elif old: |
851 |
elif old: |
|
Lines 1214-1234
def init_slapd(arg):
Link Here
|
| 1214 |
listener.run('/etc/init.d/slapd', ['slapd', arg], uid=0) |
1024 |
listener.run('/etc/init.d/slapd', ['slapd', arg], uid=0) |
| 1215 |
time.sleep(1) |
1025 |
time.sleep(1) |
| 1216 |
|
1026 |
|
| 1217 |
def setdata(key, value): |
|
|
| 1218 |
if key == 'bindpw': |
| 1219 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'replication: listener passed key="%s" value="<HIDDEN>"' % key) |
| 1220 |
else: |
| 1221 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'replication: listener passed key="%s" value="%s"' % (key, value)) |
| 1222 |
|
| 1223 |
if key in [ 'ldapserver', 'basedn', 'binddn', 'bindpw' ]: |
| 1224 |
flatmode_ldap[ key ] = value |
| 1225 |
else: |
| 1226 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, 'replication: listener passed unknown data (key="%s" value="%s")' % (key, value)) |
| 1227 |
|
| 1228 |
if key == 'ldapserver': |
| 1229 |
univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, 'replication: ldap server changed to %s' % value) |
| 1230 |
if flatmode: |
| 1231 |
flatmode_reconnect() |
| 1232 |
|
1027 |
|
| 1233 |
if __name__ == '__main__': |
1028 |
if __name__ == '__main__': |
| 1234 |
handler('foo', {'foo': 'bar'}, {'foo': 'baz'}) |
1029 |
handler('foo', {'foo': 'bar'}, {'foo': 'baz'}) |