From ae71d1294df70c7f61f79023c4678c9e240d06d3 Mon Sep 17 00:00:00 2001 From: geos_one Date: Sat, 4 Jul 2009 05:31:11 +0000 Subject: [PATCH] app-admin/mmc-agent: update the powerdns patch git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/mds@1320 6952d904-891a-0410-993b-d76249ca496b --- app-admin/mmc-agent/ChangeLog | 6 + app-admin/mmc-agent/Manifest | 4 +- .../files/mmc-agent-2.3.2-powerdns-2.patch | 787 ++++++++++++++++++ app-admin/mmc-agent/mmc-agent-2.3.2-r3.ebuild | 53 ++ 4 files changed, 849 insertions(+), 1 deletion(-) create mode 100644 app-admin/mmc-agent/files/mmc-agent-2.3.2-powerdns-2.patch create mode 100644 app-admin/mmc-agent/mmc-agent-2.3.2-r3.ebuild diff --git a/app-admin/mmc-agent/ChangeLog b/app-admin/mmc-agent/ChangeLog index e3d5437..f465f19 100644 --- a/app-admin/mmc-agent/ChangeLog +++ b/app-admin/mmc-agent/ChangeLog @@ -2,6 +2,12 @@ # Copyright 1999-2009 Gentoo Foundation; Distributed under the GPL v2 # $Header: $ +*mmc-agent-2.3.2-r3 (04 Jul 2009) + + 04 Jul 2009; Mario Fetka + +mmc-agent-2.3.2-r3.ebuild, +files/mmc-agent-2.3.2-powerdns-2.patch: + update the powerdns patch + * mmc-agent-2.3.2-r2 (17 Apr 2009) 17 Apr 2009; Mario Fetka mmc-agent-2.3.2-r2: diff --git a/app-admin/mmc-agent/Manifest b/app-admin/mmc-agent/Manifest index f43333e..367140c 100644 --- a/app-admin/mmc-agent/Manifest +++ b/app-admin/mmc-agent/Manifest @@ -1,9 +1,11 @@ AUX mmc-agent-2.3.1-kerberos-1.patch 16835 RMD160 c7bc79766967ed988a6b9d85be73a5f4cdf90f2b SHA1 fa43b2173e716b207cc6fbc10e739efef188e048 SHA256 69d7c88f5b3a35910c8650f69fdd9f9ee877248a41c03e7e99fa0a1a3b109c1c AUX mmc-agent-2.3.2-powerdns-1.patch 37711 RMD160 dfade7296129ea3a302fad701845d057e9050bd4 SHA1 711c0dd404ce59470e3b1418a9f83726a10e0aac SHA256 6c0f6df0dccca0b42d0860c289333e3d670fa1ef416885bdf561124aec45d258 +AUX mmc-agent-2.3.2-powerdns-2.patch 38803 RMD160 ecde3d096a278446fbe0f866d6165f5940d53fb2 SHA1 d4518fc05dd57aadb4f05689e9675aa6b96d451b SHA256 33f4d1bd8e6509833bae5eec194c67371cb471c2c25d6978979057af2d67464a AUX mmc-agent-2.3.2-printing-1.patch 33371 RMD160 f7064ec4dfc2e923c522f01190ca5d4f7d493d43 SHA1 ca9219b982e210bd92c85db8f982e1a3c6b9d48b SHA256 97dc50bb286361286e5451d2e85ea9b9d8609a2f92c3f3ca3836e9bcbcd1c931 AUX mmc-agent.initd 438 RMD160 d7dc64366782ab0d6fe4347d6a169b88a4e03a49 SHA1 e4ae8808678161237703bbb63b144899c9a544c9 SHA256 922d0bacad3eda749f8807e3ae5c183f636fa93e0d41d7079e570c58ebccb879 DIST mmc-agent-2.3.2.tar.gz 120949 RMD160 871b3b7766d69019de392e42ebf25a216d217c71 SHA1 1e7c634243c00c6b214f24c3467315d31a444215 SHA256 0ac8ff97818c58008cadb3c6b08dba39e42b078fea9d392fda649e036eabaea2 EBUILD mmc-agent-2.3.2-r1.ebuild 1635 RMD160 774f66ecfc207a8c86dadc010f8d9d04b50d0dbf SHA1 1175dc65b8f3e5fadd3cedfd73249b91e8a24987 SHA256 f17934a3cd9623de2c1dd29d88857a16d392feb8c51db0cc69e5320ff5d3e17e EBUILD mmc-agent-2.3.2-r2.ebuild 1557 RMD160 fd12dd7afc50f7d37dd4d9e0291ec2509cc057ba SHA1 cfa7d9721d4b45a52499c481c99e1449844eeb3b SHA256 1ed12652595fc95f9f98be38721899ae6d811746fd7854687911243dd1d59d6d -MISC ChangeLog 1397 RMD160 bebc14d8ccda75f9eb2f83aa4b6e38d1c5c1223e SHA1 ead7bf4650473188b88a1ffa2b3ff9de3fdec0e9 SHA256 ea79debe754971307e18cde0aa862a1ec6c9f9214e1bc2ab173fd056e8a1276b +EBUILD mmc-agent-2.3.2-r3.ebuild 1557 RMD160 2a6e73ba6a2981f4e010fbb05af6439d39e096ad SHA1 35a64b2ec82aef8c5907c11861e7c53cefa0bf76 SHA256 d62618c640f6cf9c531c2a12780046fe1a53ea59712cd8964225a1c436ef4e25 +MISC ChangeLog 1583 RMD160 f25bebf673d9ca95ea6e1d977c7456d93f4d45d8 SHA1 cd9a56d9a08f570ba3b2a72a70f08b7b85201afa SHA256 c78ec491e011f29dfa917fe23f968ed8d6758d301d9833ad1dc4c32420d51e04 MISC metadata.xml 170 RMD160 645927a396fdc21cdeb089fe42c5397332420ea6 SHA1 ac7f48a14fec325926f9ce1be8fbf1f311b4f2e4 SHA256 d797a2ec6f9dc516c9f9c1a758ee87ad3e8c43101b5dc76c2f872d5bd4639b42 diff --git a/app-admin/mmc-agent/files/mmc-agent-2.3.2-powerdns-2.patch b/app-admin/mmc-agent/files/mmc-agent-2.3.2-powerdns-2.patch new file mode 100644 index 0000000..8caba0a --- /dev/null +++ b/app-admin/mmc-agent/files/mmc-agent-2.3.2-powerdns-2.patch @@ -0,0 +1,787 @@ +Submitted By: Mario Fetka (mario dot fetka at gmail dot com) +Date: 2009-07-04 +Initial Package Version: 2.3.2 +Origin: http://mds.mandriva.org/ticket/244 +Upstream Status: accepted +Description: add PowerDNS support to mmc (patch update to version 2) + +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-07-04 05:27:02.904709479 +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-07-04 05:26:28.518150676 +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-07-04 05:26:28.518150676 +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): +@@ -717,7 +872,12 @@ + self.logfile = config.dnsLogFile + self.maxElt= 200 + self.file = open(self.logfile, 'r') +- self.pattern = { +- "named-syslog" : "^(?P[A-z]{3}) *(?P[0-9]+) (?P[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2}) .* named\[[0-9]+\]: (?P.*)$", +- "named-syslog1" : "^(?P[A-z]{3}) *(?P[0-9]+) (?P[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2}) .* named-sdb\[[0-9]+\]: (?P.*)$", ++ if config.dnsType == "pdns": ++ self.pattern = { ++ "named-syslog" : "^(?P[A-z]{3}) *(?P[0-9]+) (?P[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2}) .* pdns\[[0-9]+\]: (?P.*)$", ++ } ++ else: ++ self.pattern = { ++ "named-syslog" : "^(?P[A-z]{3}) *(?P[0-9]+) (?P[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2}) .* named\[[0-9]+\]: (?P.*)$", ++ "named-syslog1" : "^(?P[A-z]{3}) *(?P[0-9]+) (?P[0-9]{2}):(?P[0-9]{2}):(?P[0-9]{2}) .* named-sdb\[[0-9]+\]: (?P.*)$", + } diff --git a/app-admin/mmc-agent/mmc-agent-2.3.2-r3.ebuild b/app-admin/mmc-agent/mmc-agent-2.3.2-r3.ebuild new file mode 100644 index 0000000..de65846 --- /dev/null +++ b/app-admin/mmc-agent/mmc-agent-2.3.2-r3.ebuild @@ -0,0 +1,53 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="2" + +inherit distutils + +DESCRIPTION="The MMC Agent and its Python plugins." +HOMEPAGE="http://mds.mandriva.org/" +SRC_URI="http://mds.mandriva.org/pub/mds/sources/${PV}/${P}.tar.gz" + +LICENSE="GPL-2" +KEYWORDS="~alpha ~amd64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd" +IUSE="" + +SLOT="0" + +RDEPEND=">=dev-python/twisted-web-0.7.0 + >=dev-python/python-ldap-2.2.1 + >=dev-python/psycopg-2.0.2" + +DEPEND=">=dev-python/setuptools-0.6_rc1" + +src_prepare() { + epatch "${FILESDIR}"/${PN}-2.3.1-kerberos-1.patch + epatch "${FILESDIR}"/${PN}-2.3.2-printing-1.patch + epatch "${FILESDIR}"/${PN}-2.3.2-powerdns-2.patch +} + +# from marienz's setuptools.eclass: +src_install() { + "${python}" setup.py install --root="${D}" --no-compile "$@" || die "install failed" + dosbin bin/* || die "bin install failed" + insinto etc/mmc/agent/keys + doins -r conf/agent/keys/* || die "key install failed" + insinto etc/mmc/agent + doins -r conf/agent/*.ini || die "agent ini install failed" + insinto etc/mmc/plugins + doins -r conf/plugins/*.ini || die "plugins ini install failed" + insinto usr/share/doc/${P} + doins -r contrib || die "ldap schemas install failed" + dodoc Changelog || die "doc install failed" + + newinitd "${FILESDIR}"/mmc-agent.initd mmc-agent +} + +pkg_postinst() { + elog "To disable some plugin in your mmc environments, you have to set" + elog "disable to 1 in /etc/mmc/plugins/*.ini" + elog "(one config file per service)" + elog "You can't disable the base plugin." +}