@@ -, +, @@ --- .../modules/univention/s4connector/s4/__init__.py | 1 + .../modules/univention/s4connector/s4/dns.py | 31 +++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) --- a/services/univention-s4-connector/modules/univention/s4connector/s4/__init__.py +++ a/services/univention-s4-connector/modules/univention/s4connector/s4/__init__.py @@ -2418,6 +2418,7 @@ class s4(univention.s4connector.ucs): if hasattr(self.property[property_type], 'dn_mapping_function'): tmp_object = copy.deepcopy(object) tmp_object['dn'] = old_dn + del tmp_object['olddn'] for function in self.property[property_type].dn_mapping_function: tmp_object = function(self, tmp_object, [], isUCSobject=True) old_dn = tmp_object['dn'] --- a/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py +++ a/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py @@ -167,18 +167,24 @@ def dns_dn_mapping(s4connector, given_object, dn_mapping_stored, isUCSobject): exploded_dn = ldap.dn.str2dn(unicode_to_utf8(dn)) (fst_rdn_attribute_utf8, fst_rdn_value_utf8, _flags) = exploded_dn[0][0] + attributes_from_dn = {attr: value for rdn in exploded_dn + for (attr, value, _flags) in rdn} + if isUCSobject: ud.debug(ud.LDAP, ud.INFO, "dns_dn_mapping: got an UCS-Object") # lookup the relativeDomainName as DC/dnsNode in S4 to get corresponding DN, if not found create new try: - relativeDomainName = obj['attributes'][ol_RR_attr][0] - except (KeyError, IndexError): - # Safety fallback for the unexpected case, where relativeDomainName would not be set - if 'zoneName' == fst_rdn_attribute_utf8: - relativeDomainName = '@' - else: - raise # can't determine relativeDomainName + relativeDomainName = attributes_from_dn[ol_RR_attr] + except KeyError: + try: + relativeDomainName = obj['attributes'][ol_RR_attr][0] + except (KeyError, IndexError): + # Safety fallback for the unexpected case, where relativeDomainName would not be set + if 'zoneName' == fst_rdn_attribute_utf8: + relativeDomainName = '@' + else: + raise # can't determine relativeDomainName if s4connector.property[propertyname].mapping_table and propertyattrib in s4connector.property[propertyname].mapping_table.keys(): for ucsval, conval in s4connector.property[propertyname].mapping_table[propertyattrib]: @@ -191,15 +197,10 @@ def dns_dn_mapping(s4connector, given_object, dn_mapping_stored, isUCSobject): pass # values are not the same codec try: + ol_zone_name = attributes_from_dn['zoneName'] + except KeyError: + # let exceptions pass through, we have no other fallback ol_zone_name = obj['attributes']['zoneName'][0] - except (KeyError, IndexError): - # Safety fallback for the unexpected case, where zoneName would not be set - if ol_RR_attr == fst_rdn_attribute_utf8: - (snd_rdn_attribute_utf8, snd_rdn_value_utf8, _flags) = exploded_dn[1][0] - if 'zoneName' == snd_rdn_attribute_utf8: - ol_zone_name = snd_rdn_value_utf8 - else: - raise # can't determine zoneName for this relativeDomainName target_RR_val = relativeDomainName target_zone_name = ol_zone_name -- --- test/ucs-test/tests/52_s4connector/175sync_create_dns_a_record | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_aaaa_record | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_alias | 2 ++ .../tests/52_s4connector/175sync_create_dns_msdcs_record_con2ucs | 2 ++ .../tests/52_s4connector/175sync_create_dns_msdcs_record_ucs2con | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_pointer_record | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_serial | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_service_record | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_ttl | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_txt | 2 ++ test/ucs-test/tests/52_s4connector/175sync_create_dns_wildcard_host | 2 ++ 11 files changed, 22 insertions(+) --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_a_record +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_a_record @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.udm as udm_test from univention.testing.utils import fail, wait_for_replication_and_postrun --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_aaaa_record +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_aaaa_record @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.udm as udm_test from univention.testing.utils import fail, wait_for_replication_and_postrun --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_alias +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_alias @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.strings as uts import univention.testing.udm as udm_test --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_msdcs_record_con2ucs +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_msdcs_record_con2ucs @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.strings as uts import univention.testing.udm as udm_test --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_msdcs_record_ucs2con +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_msdcs_record_ucs2con @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.strings as uts import univention.testing.utils as utils --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_pointer_record +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_pointer_record @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.udm as udm_test import univention.testing.utils as utils --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_serial +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_serial @@ -8,6 +8,8 @@ ## - dnsutils ## bugs: ## - 32156 +## tags: +## - s4c_dns import univention.testing.udm as udm_test import univention.testing.utils as utils --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_service_record +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_service_record @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.udm as udm_test import univention.testing.utils as utils --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_ttl +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_ttl @@ -10,6 +10,8 @@ ## - 23732 ## versions: ## 3.2-0: skip +## tags: +## - s4c_dns import univention.testing.udm as udm_test --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_txt +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_txt @@ -8,6 +8,8 @@ ## - dnsutils ## versions: ## 3.2-0: skip +## tags: +## - s4c_dns import univention.testing.udm as udm_test import univention.testing.utils as utils --- a/test/ucs-test/tests/52_s4connector/175sync_create_dns_wildcard_host +++ a/test/ucs-test/tests/52_s4connector/175sync_create_dns_wildcard_host @@ -6,6 +6,8 @@ ## - univention-directory-manager-tools ## - univention-s4-connector ## - dnsutils +## tags: +## - s4c_dns import univention.testing.udm as udm_test import dnstests -- --- .../tests/52_s4connector/503_test_dns_rename.py | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100755 test/ucs-test/tests/52_s4connector/503_test_dns_rename.py --- a/test/ucs-test/tests/52_s4connector/503_test_dns_rename.py +++ a/test/ucs-test/tests/52_s4connector/503_test_dns_rename.py @@ -0,0 +1,70 @@ +#!/usr/share/ucs-test/runner /usr/bin/py.test -s +# coding: utf-8 +## desc: "Test the UCS<->AD sync in {read,write,sync} mode for dns objects." +## exposure: dangerous +## packages: +## - univention-s4-connector +## bugs: +## - 39060 +## tags: +## - s4c_dns + +import ldap +import pytest + +from univention.testing.udm import UCSTestUDM +import univention.testing.connector_common as tcommon +import univention.testing.strings as tstring + +import s4connector +from s4connector import (connector_running_on_this_host, connector_setup) +import dnstests + + +def build_s4_host_dn(host, zone, domain): + first = [ + [("DC", host, ldap.AVA_STRING)], + [("DC", zone, ldap.AVA_STRING)], + [("CN", "MicrosoftDNS", ldap.AVA_STRING)], + [("DC", "DomainDnsZones", ldap.AVA_STRING)], + ] + return ldap.dn.dn2str(first + ldap.dn.str2dn(domain)) + + +@pytest.mark.parametrize("sync_mode", ["write", "sync"]) +@pytest.mark.skipif(not connector_running_on_this_host(), + reason="Univention S4 Connector not configured.") +def test_attribute_sync_from_udm_to_s4(sync_mode): + with connector_setup(sync_mode) as s4, UCSTestUDM() as udm: + base = dnstests.ucr.get('ldap/base') + ip = dnstests.make_random_ip() + random_zone = dnstests.random_zone() + random_host_a = tstring.random_name() + random_host_b = tstring.random_name() + nameserver = dnstests.get_hostname_of_ldap_master() + + print 'Creating objects..\n' + zone_dn = udm.create_object('dns/forward_zone', zone=random_zone, nameserver=nameserver) + host_dn = udm.create_object('dns/host_record', name=random_host_a, a=ip, superordinate=zone_dn) + s4connector.wait_for_sync() + s4_host_dn = build_s4_host_dn(random_host_a, random_zone, base) + s4.verify_object(s4_host_dn, {"name": random_host_a, "dc": random_host_a}) + tcommon.verify_udm_object("dns/host_record", host_dn, {"name": random_host_a, "a": ip}) + + print 'Modifying host record..\n' + new_host_dn = udm.modify_object('dns/host_record', dn=host_dn, name=random_host_b) + + s4connector.wait_for_sync() + s4_new_host_dn = build_s4_host_dn(random_host_b, random_zone, base) + s4.verify_object(s4_host_dn, None) + tcommon.verify_udm_object("dns/host_record", host_dn, None) + s4.verify_object(s4_new_host_dn, {"name": random_host_b, "dc": random_host_b}) + tcommon.verify_udm_object("dns/host_record", new_host_dn, {"name": random_host_b, "a": ip}) + + print 'Cleaning up..\n' + udm.remove_object('dns/host_record', dn=new_host_dn) + udm.remove_object('dns/forward_zone', dn=zone_dn) + + s4connector.wait_for_sync() + s4.verify_object(s4_new_host_dn, None) + tcommon.verify_udm_object("dns/host_record", new_host_dn, None) -- 503_test_dns_rename.py --- test/ucs-test/tests/52_s4connector/503_test_dns_rename.py | 8 ++++++++ 1 file changed, 8 insertions(+) --- a/test/ucs-test/tests/52_s4connector/503_test_dns_rename.py +++ a/test/ucs-test/tests/52_s4connector/503_test_dns_rename.py @@ -53,6 +53,14 @@ def test_attribute_sync_from_udm_to_s4(sync_mode): print 'Modifying host record..\n' new_host_dn = udm.modify_object('dns/host_record', dn=host_dn, name=random_host_b) + # XXX after a modify, the old DN is _wrongly_ returned: see bug #41694 + if new_host_dn == host_dn: + new_host_dn = ldap.dn.dn2str([[("relativeDomainName", random_host_b, ldap.AVA_STRING)]] + + ldap.dn.str2dn(host_dn)[1:]) + if host_dn in udm._cleanup.get('dns/host_record', []): + udm._cleanup.setdefault('dns/host_record', []).append(new_host_dn) + udm._cleanup['dns/host_record'].remove(host_dn) + # XXX end of workarround for bug #41694 s4connector.wait_for_sync() s4_new_host_dn = build_s4_host_dn(random_host_b, random_zone, base) --