Submitted By: Mario Fetka (mario dot fetka at gmail dot com) Date: 2009-03-30 Initial Package Version: 2.3.2 Origin: http://mds.mandriva.org/ticket/244 Upstream Status: accepted Description: add PowerDNS support to mmc diff -Naur mmc-agent-2.3.2.orig/conf/plugins/network.ini mmc-agent-2.3.2/conf/plugins/network.ini --- mmc-agent-2.3.2.orig/conf/plugins/network.ini 2008-05-16 07:39:44.000000000 +0000 +++ mmc-agent-2.3.2/conf/plugins/network.ini 2009-03-30 10:08:24.623244489 +0000 @@ -9,6 +9,10 @@ leases = /var/lib/dhcp3/dhcpd.leases [dns] +# DNS Server Type : (default: bind) +# - bind (ISC Bind) +# - pdns (PowerDNS) +# type = bind dn = ou=DNS,dc=mandriva,dc=com pidfile = /var/run/bind/run/named.pid init = /etc/init.d/bind9 diff -Naur mmc-agent-2.3.2.orig/mmc/plugins/network/__init__.py mmc-agent-2.3.2/mmc/plugins/network/__init__.py --- mmc-agent-2.3.2.orig/mmc/plugins/network/__init__.py 2008-12-15 14:20:35.000000000 +0000 +++ mmc-agent-2.3.2/mmc/plugins/network/__init__.py 2009-03-30 10:09:41.023104866 +0000 @@ -71,13 +71,27 @@ return False # Test if the DNS/LDAP schema is available in the directory - try: - schema = ldapObj.getSchema("dNSZone") - if len(schema) <= 0: - logger.error("DNS zone schema is not included in LDAP directory"); + serverType = config.dnsType + if serverType == "pdns": + try: + schema = ldapObj.getSchema("dNSDomain2") + if len(schema) <= 0: + logger.error("DNS zone schema (dnsdomain2.schema) is not included in LDAP directory"); + return False + except: + logger.exception("invalid DNS schema") + return False + elif serverType == "bind": + try: + schema = ldapObj.getSchema("dNSZone") + if len(schema) <= 0: + logger.error("DNS zone schema (dnszone.schema) is not included in LDAP directory"); + return False + except: + logger.exception("invalid DNS schema") return False - except: - logger.exception("invalid schema") + else: + logger.error("%s : Unknown DNS server."%serverType); return False # Create required OUs @@ -108,26 +122,27 @@ pass # Create DNS config base structure - try: - gidNumber = grp.getgrnam(config.bindGroup) - except KeyError: - logger.error('The group "%s" does not exist.' % config.bindGroup) - return False - gidNumber = gidNumber[2] + if serverType == "bind": + try: + gidNumber = grp.getgrnam(config.bindGroup) + except KeyError: + logger.error('The group "%s" does not exist.' % config.bindGroup) + return False + gidNumber = gidNumber[2] - try: - os.mkdir(config.bindLdapDir) - os.chmod(config.bindLdapDir, 02750) - os.chown(config.bindLdapDir, -1, gidNumber) - except OSError, e: - # errno = 17 is "File exists" - if e.errno != 17: raise - - if not os.path.exists(config.bindLdap): - f = open(config.bindLdap, "w") - f.close() - os.chmod(config.bindLdap, 0640) - os.chown(config.bindLdap, -1, gidNumber) + try: + os.mkdir(config.bindLdapDir) + os.chmod(config.bindLdapDir, 02750) + os.chown(config.bindLdapDir, -1, gidNumber) + except OSError, e: + # errno = 17 is "File exists" + if e.errno != 17: raise + + if not os.path.exists(config.bindLdap): + f = open(config.bindLdap, "w") + f.close() + os.chmod(config.bindLdap, 0640) + os.chown(config.bindLdap, -1, gidNumber) return True @@ -344,6 +359,10 @@ self.dhcpLogFile = self.get("dhcp", "logfile") self.dhcpLeases = self.get("dhcp", "leases") # DNS conf + try: + self.dnsType = self.get("dns", "type") + except NoOptionError: + self.dnsType = "bind" self.dnsDN = self.getdn("dns", "dn") self.dnsPidFile = self.get("dns", "pidfile") self.dnsInit = self.get("dns", "init") diff -Naur mmc-agent-2.3.2.orig/mmc/plugins/network/dns.py mmc-agent-2.3.2/mmc/plugins/network/dns.py --- mmc-agent-2.3.2.orig/mmc/plugins/network/dns.py 2008-12-10 15:18:18.000000000 +0000 +++ mmc-agent-2.3.2/mmc/plugins/network/dns.py 2009-03-30 10:09:41.020789343 +0000 @@ -41,6 +41,15 @@ self.configDns.dnsReader = self.config.get("ldap", "rootName") if not self.configDns.dnsReaderPassword: self.configDns.dnsReaderPassword = self.config.get("ldap", "password") + if self.configDns.dnsType == "pdns": + self.pdns = True + self.zoneNameField = "associatedDomain" + self.relativeDomainNameField = "associatedDomain" + else: + self.pdns = False + self.zoneNameField = "zoneName" + self.relativeDomainNameField = "relativeDomainName" + self.reverseMarkup = "Reverse:" self.reversePrefix = ".in-addr.arpa" self.templateZone = """ @@ -77,7 +86,7 @@ """ ret = [] for result in self.getZones(self.reversePrefix, True): - ret.append(self.translateReverse(result[1]["zoneName"][0])) + ret.append(self.translateReverse(result[1][self.zoneNameField][0])) return ret def getReverseZone(self, name): @@ -85,9 +94,17 @@ Return the name of the reverse zone of a zone """ ret = [] - for result in self.getZones(reverse = True, base = "ou=" + name + "," + self.configDns.dnsDN): - zoneName = result[1]["zoneName"][0] - if zoneName.endswith(self.reversePrefix): ret.append(zoneName) + if self.pdns: + tmpZones = self.getZones(reverse = True, base = self.configDns.dnsDN) + for result in tmpZones: + zoneName = result[1][self.zoneNameField][0] + nsRecord = result[1]["nSRecord"][0] + if zoneName.endswith(self.reversePrefix) and nsRecord.endswith(".%s"%name): ret.append(zoneName) + else: + tmpZones = self.getZones(reverse = True, base = "ou=" + name + "," + self.configDns.dnsDN) + for result in tmpZones: + zoneName = result[1][self.zoneNameField][0] + if zoneName.endswith(self.reversePrefix): ret.append(zoneName) return ret def getZoneObjects(self, name, filt = None): @@ -98,10 +115,13 @@ filt = "*" + filt.strip() + "*" else: filt = "*" - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (name, filt), None) + if self.pdns: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s.%s))" % (filt, name), None) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (name, filt), None) ret = [] for result in search: - relative = result[1]["relativeDomainName"][0] + relative = result[1][self.relativeDomainNameField][0] # Don't count these entries if relative != "@" and relative != name + ".": ret.append(result) @@ -111,17 +131,24 @@ """ Return the number of objects defined in a zone """ - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s))" % (name), ["relativeDomainName"]) count = 0 + if self.pdns: + search = self.l.search_s("dc=" + name + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=*.%s))" % (name), ["associatedDomain"]) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s))" % (name), ["relativeDomainName"]) + for result in search: - relative = result[1]["relativeDomainName"][0] + relative = result[1][self.relativeDomainNameField][0] # Don't count these entries if relative != "@" and relative != name + ".": count = count + 1 return count def getZone(self, zoneName): - return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zoneName, zoneName + "."), None) + if self.pdns: + return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" % (zoneName), None) + else: + return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zoneName, zoneName + "."), None) def getZones(self, filt = "", reverse = False, base = None): """ @@ -131,14 +158,23 @@ if not filt: filt = "*" else: filt = "*" + filt + "*" if not base: base = self.configDns.dnsDN - search = self.l.search_s(base, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (filt, filt), None) ret = [] - for result in search: - if (result[1]["zoneName"][0] + ".") == result[1]["relativeDomainName"][0]: - if self.reversePrefix in result[1]["zoneName"][0]: + if self.configDns.dnsType == "pdns": + search = self.l.search_s(base, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(soarecord=*)(associatedDomain=%s))" %filt, None) + for result in search: + if self.reversePrefix in result[1][self.zoneNameField][0]: # Reverse zone if reverse: ret.append(result) else: ret.append(result) + + else: + search = self.l.search_s(base, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (filt, filt), None) + for result in search: + if (result[1]["zoneName"][0] + ".") == result[1]["relativeDomainName"][0]: + if self.reversePrefix in result[1][self.zoneNameField][0]: + # Reverse zone + if reverse: ret.append(result) + else: ret.append(result) return ret def zoneExists(self, zone): @@ -168,32 +204,34 @@ else: raise "Won't create reverse zone as asked, netmask is not 8, 16 or 24" - f = open(os.path.join(self.configDns.bindLdapDir, name), "w") - d = { - "zone" : name, - "ldapurl" : self.ldapHost + "/" + self.configDns.dnsDN, - "dnsreader": urllib.quote(self.configDns.dnsReader), - "dnsreaderpasswd" : urllib.quote(self.configDns.dnsReaderPassword) - } - f.write(self.templateZone % d) - if reverse: - d["zone"] = self.reverseZone(network) + if not self.pdns: + # Create Bind configuration files + f = open(os.path.join(self.configDns.bindLdapDir, name), "w") + d = { + "zone" : name, + "ldapurl" : self.ldapHost + "/" + self.configDns.dnsDN, + "dnsreader": urllib.quote(self.configDns.dnsReader), + "dnsreaderpasswd" : urllib.quote(self.configDns.dnsReaderPassword) + } f.write(self.templateZone % d) - f.close() - os.chmod(os.path.join(self.configDns.bindLdapDir, name), 0640) + if reverse: + d["zone"] = self.reverseZone(network) + f.write(self.templateZone % d) + f.close() + os.chmod(os.path.join(self.configDns.bindLdapDir, name), 0640) - f = open(self.configDns.bindLdap, "r") - found = False - toadd = 'include "' + os.path.join(self.configDns.bindLdapChrootConfPath, name) + '";\n' - for line in f: - if line == toadd: - found = True - break - f.close() - if not found: - f = open(self.configDns.bindLdap, "a") - f.write(toadd) + f = open(self.configDns.bindLdap, "r") + found = False + toadd = 'include "' + os.path.join(self.configDns.bindLdapChrootConfPath, name) + '";\n' + for line in f: + if line == toadd: + found = True + break f.close() + if not found: + f = open(self.configDns.bindLdap, "a") + f.write(toadd) + f.close() # Create the needed zones object in LDAP if reverse: @@ -205,10 +243,15 @@ # Fill SOA self.addSOA(name) - ns = nameserver + "." + name + "." + if self.pdns: + ns = nameserver + "." + name + mailaddr = "admin." + name + else: + ns = nameserver + "." + name + "." + mailaddr = "admin." + name + "." rec = { "nameserver" : ns, - "emailaddr" : "admin." + name + ".", + "emailaddr" : mailaddr, "serial" : self.computeSerial(), "refresh" : "2D", "retry" : "15M", @@ -234,18 +277,26 @@ @param name: the zone name to delete """ - self.delRecursiveEntry("ou=" + zone + "," + self.configDns.dnsDN) - os.unlink(os.path.join(self.configDns.bindLdapDir, zone)) - newcontent = [] - f = open(self.configDns.bindLdap, "r") - for line in f: - if not "/" + zone + '";' in line: - newcontent.append(line) - f.close() - f = open(self.configDns.bindLdap, "w+") - for line in newcontent: - f.write(line) - f.close() + if self.pdns: + zoneDN = "dc=" + zone + "," + self.configDns.dnsDN + self.delRecursiveEntry(zoneDN) + reverseDN = self.getReverseZone(zone) + if reverseDN[0]: + self.delRecursiveEntry("dc=" + reverseDN[0] + "," + self.configDns.dnsDN) + else: + zoneDN = "ou=" + zone + "," + self.configDns.dnsDN + self.delRecursiveEntry(zoneDN) + os.unlink(os.path.join(self.configDns.bindLdapDir, zone)) + newcontent = [] + f = open(self.configDns.bindLdap, "r") + for line in f: + if not "/" + zone + '";' in line: + newcontent.append(line) + f.close() + f = open(self.configDns.bindLdap, "w+") + for line in newcontent: + f.write(line) + f.close() def addDnsZone(self, zoneName, description = None, container = None): """ @@ -253,40 +304,55 @@ """ if not container: container = zoneName # Create the container of this zone and its reverses if it does not exist - try: - self.addOu(container, self.configDns.dnsDN) - except ldap.ALREADY_EXISTS: - pass - # Create the ou defining this zone and that will contain all records - self.addOu(zoneName, "ou=" + container + "," + self.configDns.dnsDN) - dn = "zoneName=" + zoneName + "," + "ou=" + zoneName + "," + "ou=" + container + "," + self.configDns.dnsDN - entry = { - "zoneName" : zoneName, - "objectClass" : ["top", "dNSZone"], - "relativeDomainName" : zoneName + ".", - } - if description: entry["tXTRecord"] = [description] + if self.pdns: + dn = "dc=" + zoneName + "," + self.configDns.dnsDN + entry = { + "associateddomain" : zoneName, + "objectClass" : ["top", "domainrelatedobject", "dnsdomain2", "dcobject"], + "dc" : zoneName, + } + if description: entry["tXTRecord"] = [description] + else: + try: + self.addOu(container, self.configDns.dnsDN) + except ldap.ALREADY_EXISTS: + pass + # Create the ou defining this zone and that will contain all records + self.addOu(zoneName, "ou=" + container + "," + self.configDns.dnsDN) + dn = "zoneName=" + zoneName + "," + "ou=" + zoneName + "," + "ou=" + container + "," + self.configDns.dnsDN + entry = { + "zoneName" : zoneName, + "objectClass" : ["top", "dNSZone"], + "relativeDomainName" : zoneName + ".", + } + if description: entry["tXTRecord"] = [description] attributes = [ (k,v) for k,v in entry.items() ] self.l.add_s(dn, attributes) def addSOA(self, zoneName, container = None, dnsClass = "IN"): if not container: container = zoneName - dn = "relativeDomainName=@," + "ou=" + zoneName + "," + "ou=" + container + "," + self.configDns.dnsDN - entry = { - "zoneName" : zoneName, - "objectClass" : ["top", "dNSZone"], - "relativeDomainName" : "@", - "dnsClass" : dnsClass - } - attributes=[ (k,v) for k,v in entry.items() ] - self.l.add_s(dn, attributes) + if not self.pdns: + dn = "relativeDomainName=@," + "ou=" + zoneName + "," + "ou=" + container + "," + self.configDns.dnsDN + entry = { + "zoneName" : zoneName, + "objectClass" : ["top", "dNSZone"], + "relativeDomainName" : "@", + "dnsClass" : dnsClass + } + attributes=[ (k,v) for k,v in entry.items() ] + self.l.add_s(dn, attributes) def setSOARecord(self, zoneName, record): - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) - if soa: - soaDN = soa[0][0] + if self.pdns: + zoneDN = "dc=" + zoneName + "," + self.configDns.dnsDN s = "%(nameserver)s %(emailaddr)s %(serial)s %(refresh)s %(retry)s %(expiry)s %(minimum)s" % record - self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "sOARecord", [s])]) + self.l.modify_s(zoneDN, [(ldap.MOD_REPLACE, "soarecord", [s])]) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if soa: + soaDN = soa[0][0] + s = "%(nameserver)s %(emailaddr)s %(serial)s %(refresh)s %(retry)s %(expiry)s %(minimum)s" % record + self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "sOARecord", [s])]) def setSOANSRecord(self, zoneName, nameserver): """ @@ -294,10 +360,14 @@ It updates the SOARecord field and nsRecord field of the @ LDAP entry of this given zone. """ - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) - if soa: - soaDN = soa[0][0] - self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "nSRecord", [nameserver])]) + if self.pdns: + zoneDN = "dc=" + zoneName + "," + self.configDns.dnsDN + self.l.modify_s(zoneDN, [(ldap.MOD_REPLACE, "nsrecord", [nameserver])]) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if soa: + soaDN = soa[0][0] + self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "nSRecord", [nameserver])]) # Also sync SOA record if there is one soaRecord = self.getSOARecord(zoneName) if soaRecord: @@ -311,22 +381,29 @@ The nsRecord corresponding to the name server containted into the SOARecord field won't be deleted. Use the setSOANSRecord to update it. """ - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) - if soa: - soaDN = soa[0][0] - soanameserver = soa[0][1]["sOARecord"][0].split()[0] - # Assert that the name server contained into the SOA record won't - # be deleted - if soanameserver not in nameservers: - nameservers.append(soanameserver) - self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "nSRecord", nameservers)]) - self.updateZoneSerial(zoneName) + if self.pdns: + zoneDN = "dc=" + zoneName + "," + self.configDns.dnsDN + self.l.modify_s(zoneDN, [(ldap.MOD_REPLACE, "nsrecord", nameservers)]) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if soa: + soaDN = soa[0][0] + soanameserver = soa[0][1]["sOARecord"][0].split()[0] + # Assert that the name server contained into the SOA record won't + # be deleted + if soanameserver not in nameservers: + nameservers.append(soanameserver) + self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "nSRecord", nameservers)]) + self.updateZoneSerial(zoneName) def setMXRecords(self, zoneName, mxservers): """ Update the mXRecord fields of the @ LDAP entry of the given zone. """ - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if self.pdns: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s)(soarecord=*))" % zoneName, None) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) if soa: soaDN = soa[0][0] self.l.modify_s(soaDN, [(ldap.MOD_REPLACE, "mXRecord", mxservers)]) @@ -353,7 +430,10 @@ @rtype: dict """ ret = {} - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, ["soaRecord"]) + if self.pdns: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" % zoneName, ["soaRecord"]) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, ["soaRecord"]) if soa: try: ret["nameserver"], ret["emailaddr"], ret["serial"], ret["refresh"], ret["retry"], ret["expiry"], ret["minimum"] = soa[0][1]["sOARecord"][0].split() @@ -366,7 +446,10 @@ Get the name servers of a zone """ ret = [] - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if self.pdns: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associateddomain=%s))" % zoneName, None) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) if soa: soaDN = soa[0][0] ret = soa[0][1]["nSRecord"] @@ -377,7 +460,10 @@ Get the MX servers of a zone """ ret = [] - soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) + if self.pdns: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associateddomain=%s))" % zoneName, None) + else: + soa = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=@))" % zoneName, None) if soa: soaDN = soa[0][0] try: @@ -395,7 +481,11 @@ elements.reverse() while elements: rev = ".".join(elements) + self.reversePrefix - ret = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s))" % rev, None) + if self.pdns: + ret = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associateddomain=*.%s)" % rev, None) + else: + ret = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s))" % rev, None) + if ret: elements.reverse() # Return the reverse zone name and how the IPs are beginning in this zone @@ -434,7 +524,7 @@ ret = [] oldaliases = [] for record in self.getCNAMEs(zone, host): - oldalias = record[1]["relativeDomainName"][0] + oldalias = record[1][self.relativeDomainNameField][0] oldaliases.append(oldalias) if oldalias not in aliases: # Delete alias @@ -470,15 +560,25 @@ raise "%s in not a A record" % cname except IndexError: raise "'%s' A record does not exist in the DNS zone" % cname - # Add the CNAME record - dn = "relativeDomainName=" + alias + "," + "ou=" + zone + "," + "ou=" + zone + "," + self.configDns.dnsDN - entry = { - "relativeDomainName" : alias, - "objectClass" : ["top", "dNSZone"], - "zoneName" : zone, - "dNSClass" : dnsClass, - "CNAMERecord" : cname, - } + + if self.pdns: + dn = "dc=" + alias + "," +"dc=" + zone + "," + self.configDns.dnsDN + entry = { + "associateddomain" : alias + "." + zone, + "objectClass" : ["top", "domainrelatedobject", "dnsdomain2"], + "dc" : alias, + "cnamerecord" : cname + "." + zone, + } + else: + # Add the CNAME record + dn = "relativeDomainName=" + alias + "," + "ou=" + zone + "," + "ou=" + zone + "," + self.configDns.dnsDN + entry = { + "relativeDomainName" : alias, + "objectClass" : ["top", "dNSZone"], + "zoneName" : zone, + "dNSClass" : dnsClass, + "CNAMERecord" : cname, + } attributes=[ (k,v) for k,v in entry.items() ] self.l.add_s(dn, attributes) self.updateZoneSerial(zone) @@ -491,15 +591,24 @@ @rtype: int """ ret = 1 - if not container: container = zone - dn = "relativeDomainName=" + hostname + "," + "ou=" + zone + "," + "ou=" + container + "," + self.configDns.dnsDN - entry = { - "relativeDomainName" : hostname, - "objectClass" : ["top", "dNSZone"], - "zoneName" : zone, - "dNSClass" : dnsClass, - "aRecord" : ip, - } + if self.pdns: + dn = "dc=" + hostname + "," +"dc=" + zone + "," + self.configDns.dnsDN + entry = { + "associateddomain" : hostname + "." + zone, + "objectClass" : ["top", "domainrelatedobject", "dnsdomain2"], + "dc" : hostname, + "aRecord" : ip, + } + else: + if not container: container = zone + dn = "relativeDomainName=" + hostname + "," + "ou=" + zone + "," + "ou=" + container + "," + self.configDns.dnsDN + entry = { + "relativeDomainName" : hostname, + "objectClass" : ["top", "dNSZone"], + "zoneName" : zone, + "dNSClass" : dnsClass, + "aRecord" : ip, + } attributes=[ (k,v) for k,v in entry.items() ] self.l.add_s(dn, attributes) self.updateZoneSerial(zone) @@ -518,14 +627,23 @@ elements.reverse() elements.pop() # Remove the last "." relative = ".".join(elements) - dn = "relativeDomainName=" + relative + "," + "ou=" + revZone + "," + "ou=" + container + "," + self.configDns.dnsDN - entry = { - "relativeDomainName" : relative, - "objectClass" : ["top", "dNSZone"], - "zoneName" : revZone, - "dNSClass" : dnsClass, - "pTRRecord" : hostname + "." + zone + ".", - } + if self.pdns: + dn = "dc=" + relative + "," + "dc=" + revZone + "," + self.configDns.dnsDN + entry = { + "dc" : relative, + "objectClass" : ["top", "domainrelatedobject", "dnsdomain2"], + "associatedDomain" : relative + "." + revZone, + "pTRRecord" : hostname + "." + zone, + } + else: + dn = "relativeDomainName=" + relative + "," + "ou=" + revZone + "," + "ou=" + container + "," + self.configDns.dnsDN + entry = { + "relativeDomainName" : relative, + "objectClass" : ["top", "dNSZone"], + "zoneName" : revZone, + "dNSClass" : dnsClass, + "pTRRecord" : hostname + "." + zone + ".", + } attributes=[ (k,v) for k,v in entry.items() ] self.l.add_s(dn, attributes) self.updateZoneSerial(revZone) @@ -536,7 +654,12 @@ """ Get all CNAME records that points to the given hostname """ - return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(cNAMERecord=%s))" % (zone, hostname), None) + if hostname.endswith("."+zone): fqdn = hostname + else: fqdn = hostname + "." + zone + if self.pdns: + return self.l.search_s("dc=" + zone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(cNAMERecord=%s))" % (fqdn), None) + else: + return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(cNAMERecord=%s))" % (zone, hostname), None) def delCNAMEs(self, zone, hostname): """ @@ -553,7 +676,12 @@ If the RR is a A record where CNAME are linked in, the CNAME records are also removed. """ - host = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) + if hostname.endswith("."+zone): fqdn = hostname + else: fqdn = hostname + "." + zone + if self.pdns: + host = self.l.search_s("dc=" + zone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" %fqdn, None) + else: + host = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) if host: # If the deleted resource is a type A record, the aliases must be # removed if they exist @@ -564,7 +692,10 @@ # Also remove reverse entry revzones = self.getReverseZone(zone) for revzone in revzones: - revhost = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(pTRRecord=%s))" % (revzone, hostname + "." + zone + "."), None) + if self.pdns: + revhost = self.l.search_s("dc=" + revzone + "," +self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(pTRRecord=%s))" %fqdn, None) + else: + revhost = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(pTRRecord=%s))" % (revzone, hostname + "." + zone + "."), None) if revhost: self.l.delete_s(revhost[0][0]) self.updateZoneSerial(revzone) @@ -608,14 +739,22 @@ This method is useful to know if we can record a machine in a zone without duplicate. """ - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) + if hostname.endswith("."+zone): fqdn = hostname + else: fqdn = hostname + "." + zone + if self.pdns: + search = self.l.search_s("dc=" + zone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" % (fqdn), None) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) if search: return True revZone = self.getReverseZone(zone) if revZone: # Search host in the reverse zone revZone = revZone[0] - fqdn = hostname + "." + zone + "." - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(pTRRecord=%s))" % (revZone, fqdn), None) + if self.pdns: + search = self.l.search_s("dc=" + revZone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(dc=%s))" % (fqdn), None) + else: + fqdn = fqdn + "." + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(pTRRecord=%s))" % (revZone, fqdn), None) return len(search) > 0 return False @@ -628,7 +767,10 @@ This method is useful to know if we can record a machine in a zone without duplicate. """ - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(aRecord=%s))" % (zone, ip), None) + if self.pdns: + search = self.l.search_s("dc=" + zone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(aRecord=%s))" %ip, None) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(aRecord=%s))" % (zone, ip), None) if search: return True revZone = self.getReverseZone(zone) if revZone: @@ -640,7 +782,10 @@ elements.reverse() elements.pop() # Remove the last "." relative = ".".join(elements) - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (revZone, relative), None) + if self.pdns: + search = self.l.search_s("dc=" + revZone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" %relative, None) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (revZone, relative), None) return len(search) > 0 return False @@ -652,7 +797,12 @@ @rtype: str """ ret = "" - search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) + if hostname.endswith("."+zone): fqdn = hostname + else: fqdn = hostname + "." + zone + if self.pdns: + search = self.l.search_s("dc=" + zone + "," + self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s))" %fqdn, None) + else: + search = self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, hostname), None) if search: try: ret = search[0][1]["aRecord"][0] @@ -697,7 +847,12 @@ @return: a domain name resource record (RR) @rtype: dict """ - return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, rr), None) + if self.pdns: + if rr.endswith(zone): + rr, tmp = rr.split(".") + return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dnsdomain2)(associatedDomain=%s.%s))" % (rr, zone), None) + else: + return self.l.search_s(self.configDns.dnsDN, ldap.SCOPE_SUBTREE, "(&(objectClass=dNSZone)(zoneName=%s)(relativeDomainName=%s))" % (zone, rr), None) class DnsService(ServiceManager):