diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2010-03-29 16:08:11 +0200 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2010-03-29 18:05:29 +0200 |
commit | 4bbc3ff037026c72f3249f59c1b5af69a6ad6d69 (patch) | |
tree | 125857a1edbf3246579e51b10f6e62ec875062bc /lib/dnspython/dns/update.py | |
parent | 89aa3b766b926d19dac4805a7e72433e497ce872 (diff) | |
download | samba-4bbc3ff037026c72f3249f59c1b5af69a6ad6d69.tar.gz samba-4bbc3ff037026c72f3249f59c1b5af69a6ad6d69.tar.bz2 samba-4bbc3ff037026c72f3249f59c1b5af69a6ad6d69.zip |
s4-python: Move dnspython to lib/, like the other Python modules
This also avoids it from being installed if it's already present on the
system.
Diffstat (limited to 'lib/dnspython/dns/update.py')
-rw-r--r-- | lib/dnspython/dns/update.py | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/lib/dnspython/dns/update.py b/lib/dnspython/dns/update.py new file mode 100644 index 0000000000..7d42636891 --- /dev/null +++ b/lib/dnspython/dns/update.py @@ -0,0 +1,241 @@ +# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""DNS Dynamic Update Support""" + +import dns.message +import dns.name +import dns.opcode +import dns.rdata +import dns.rdataclass +import dns.rdataset + +class Update(dns.message.Message): + def __init__(self, zone, rdclass=dns.rdataclass.IN, keyring=None, + keyname=None, keyalgorithm=dns.tsig.default_algorithm): + """Initialize a new DNS Update object. + + @param zone: The zone which is being updated. + @type zone: A dns.name.Name or string + @param rdclass: The class of the zone; defaults to dns.rdataclass.IN. + @type rdclass: An int designating the class, or a string whose value + is the name of a class. + @param keyring: The TSIG keyring to use; defaults to None. + @type keyring: dict + @param keyname: The name of the TSIG key to use; defaults to None. + The key must be defined in the keyring. If a keyring is specified + but a keyname is not, then the key used will be the first key in the + keyring. Note that the order of keys in a dictionary is not defined, + so applications should supply a keyname when a keyring is used, unless + they know the keyring contains only one key. + @type keyname: dns.name.Name or string + @param keyalgorithm: The TSIG algorithm to use; defaults to + dns.tsig.default_algorithm + @type keyalgorithm: string + """ + super(Update, self).__init__() + self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE) + if isinstance(zone, (str, unicode)): + zone = dns.name.from_text(zone) + self.origin = zone + if isinstance(rdclass, str): + rdclass = dns.rdataclass.from_text(rdclass) + self.zone_rdclass = rdclass + self.find_rrset(self.question, self.origin, rdclass, dns.rdatatype.SOA, + create=True, force_unique=True) + if not keyring is None: + self.use_tsig(keyring, keyname, keyalgorithm) + + def _add_rr(self, name, ttl, rd, deleting=None, section=None): + """Add a single RR to the update section.""" + + if section is None: + section = self.authority + covers = rd.covers() + rrset = self.find_rrset(section, name, self.zone_rdclass, rd.rdtype, + covers, deleting, True, True) + rrset.add(rd, ttl) + + def _add(self, replace, section, name, *args): + """Add records. The first argument is the replace mode. If + false, RRs are added to an existing RRset; if true, the RRset + is replaced with the specified contents. The second + argument is the section to add to. The third argument + is always a name. The other arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string...""" + + if isinstance(name, (str, unicode)): + name = dns.name.from_text(name, None) + if isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + if replace: + self.delete(name, rds.rdtype) + for rd in rds: + self._add_rr(name, rds.ttl, rd, section=section) + else: + args = list(args) + ttl = int(args.pop(0)) + if isinstance(args[0], dns.rdata.Rdata): + if replace: + self.delete(name, args[0].rdtype) + for rd in args: + self._add_rr(name, ttl, rd, section=section) + else: + rdtype = args.pop(0) + if isinstance(rdtype, str): + rdtype = dns.rdatatype.from_text(rdtype) + if replace: + self.delete(name, rdtype) + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, ttl, rd, section=section) + + def add(self, name, *args): + """Add records. The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string...""" + self._add(False, self.authority, name, *args) + + def delete(self, name, *args): + """Delete records. The first argument is always a name. The other + arguments can be: + + - I{nothing} + + - rdataset... + + - rdata... + + - rdtype, [string...]""" + + if isinstance(name, (str, unicode)): + name = dns.name.from_text(name, None) + if len(args) == 0: + rrset = self.find_rrset(self.authority, name, dns.rdataclass.ANY, + dns.rdatatype.ANY, dns.rdatatype.NONE, + dns.rdatatype.ANY, True, True) + elif isinstance(args[0], dns.rdataset.Rdataset): + for rds in args: + for rd in rds: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + args = list(args) + if isinstance(args[0], dns.rdata.Rdata): + for rd in args: + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + else: + rdtype = args.pop(0) + if isinstance(rdtype, str): + rdtype = dns.rdatatype.from_text(rdtype) + if len(args) == 0: + rrset = self.find_rrset(self.authority, name, + self.zone_rdclass, rdtype, + dns.rdatatype.NONE, + dns.rdataclass.ANY, + True, True) + else: + for s in args: + rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, + self.origin) + self._add_rr(name, 0, rd, dns.rdataclass.NONE) + + def replace(self, name, *args): + """Replace records. The first argument is always a name. The other + arguments can be: + + - rdataset... + + - ttl, rdata... + + - ttl, rdtype, string... + + Note that if you want to replace the entire node, you should do + a delete of the name followed by one or more calls to add.""" + + self._add(True, self.authority, name, *args) + + def present(self, name, *args): + """Require that an owner name (and optionally an rdata type, + or specific rdataset) exists as a prerequisite to the + execution of the update. The first argument is always a name. + The other arguments can be: + + - rdataset... + + - rdata... + + - rdtype, string...""" + + if isinstance(name, (str, unicode)): + name = dns.name.from_text(name, None) + if len(args) == 0: + rrset = self.find_rrset(self.answer, name, + dns.rdataclass.ANY, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + elif isinstance(args[0], dns.rdataset.Rdataset) or \ + isinstance(args[0], dns.rdata.Rdata) or \ + len(args) > 1: + if not isinstance(args[0], dns.rdataset.Rdataset): + # Add a 0 TTL + args = list(args) + args.insert(0, 0) + self._add(False, self.answer, name, *args) + else: + rdtype = args[0] + if isinstance(rdtype, str): + rdtype = dns.rdatatype.from_text(rdtype) + rrset = self.find_rrset(self.answer, name, + dns.rdataclass.ANY, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def absent(self, name, rdtype=None): + """Require that an owner name (and optionally an rdata type) does + not exist as a prerequisite to the execution of the update.""" + + if isinstance(name, (str, unicode)): + name = dns.name.from_text(name, None) + if rdtype is None: + rrset = self.find_rrset(self.answer, name, + dns.rdataclass.NONE, dns.rdatatype.ANY, + dns.rdatatype.NONE, None, + True, True) + else: + if isinstance(rdtype, str): + rdtype = dns.rdatatype.from_text(rdtype) + rrset = self.find_rrset(self.answer, name, + dns.rdataclass.NONE, rdtype, + dns.rdatatype.NONE, None, + True, True) + + def to_wire(self, origin=None, max_size=65535): + """Return a string containing the update in DNS compressed wire + format. + @rtype: string""" + if origin is None: + origin = self.origin + return super(Update, self).to_wire(origin, max_size) |