Package dns :: Module node |
[hide private]
[frames] | no frames]

# Source Code for Module dns.node

      1  # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
      2  #
      3  # Permission to use, copy, modify, and distribute this software and its
      4  # documentation for any purpose with or without fee is hereby granted,
      5  # provided that the above copyright notice and this permission notice
      6  # appear in all copies.
      7  #
      8  # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
      9  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
     11  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     14  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15
     16  """DNS nodes.  A node is a set of rdatasets."""
     17
     18  import StringIO
     19
     20  import dns.rdataset
     21  import dns.rdatatype
     22  import dns.renderer
     23
     24 -class Node(object):
     25      """A DNS node.
     26
     27      A node is a set of rdatasets
     28
     29      @ivar rdatasets: the node's rdatasets
     30      @type rdatasets: list of dns.rdataset.Rdataset objects"""
     31
     32      __slots__ = ['rdatasets']
     33
     34 -    def __init__(self):
     35          """Initialize a DNS node.
     36          """
     37
     38          self.rdatasets = [];
     39
     40 -    def to_text(self, name, **kw):
     41          """Convert a node to text format.
     42
     43          Each rdataset at the node is printed.  Any keyword arguments
     44          to this method are passed on to the rdataset's to_text() method.
     45          @param name: the owner name of the rdatasets
     46          @type name: dns.name.Name object
     47          @rtype: string
     48          """
     49
     50          s = StringIO.StringIO()
     51          for rds in self.rdatasets:
     52              print >> s, rds.to_text(name, **kw)
     53          return s.getvalue()[:-1]
     54
     55 -    def __repr__(self):
     56          return '<DNS node ' + str(id(self)) + '>'
     57
     58 -    def __eq__(self, other):
     59          """Two nodes are equal if they have the same rdatasets.
     60
     61          @rtype: bool
     62          """
     63          #
     64          # This is inefficient.  Good thing we don't need to do it much.
     65          #
     66          for rd in self.rdatasets:
     67              if rd not in other.rdatasets:
     68                  return False
     69          for rd in other.rdatasets:
     70              if rd not in self.rdatasets:
     71                  return False
     72          return True
     73
     74 -    def __ne__(self, other):
     75          return not self.__eq__(other)
     76
     77 -    def __len__(self):
     78          return len(self.rdatasets)
     79
     80 -    def __iter__(self):
     81          return iter(self.rdatasets)
     82
     83 -    def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
     84                        create=False):
     85          """Find an rdataset matching the specified properties in the
     86          current node.
     87
     88          @param rdclass: The class of the rdataset
     89          @type rdclass: int
     90          @param rdtype: The type of the rdataset
     91          @type rdtype: int
     92          @param covers: The covered type.  Usually this value is
     93          dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
     94          dns.rdatatype.RRSIG, then the covers value will be the rdata
     95          type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
     96          types as if they were a family of
     97          types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
     98          easier to work with than if RRSIGs covering different rdata
     99          types were aggregated into a single RRSIG rdataset.
    100          @type covers: int
    101          @param create: If True, create the rdataset if it is not found.
    102          @type create: bool
    103          @raises KeyError: An rdataset of the desired type and class does
    104          not exist and I{create} is not True.
    105          @rtype: dns.rdataset.Rdataset object
    106          """
    107
    108          for rds in self.rdatasets:
    109              if rds.match(rdclass, rdtype, covers):
    110                  return rds
    111          if not create:
    112              raise KeyError
    113          rds = dns.rdataset.Rdataset(rdclass, rdtype)
    114          self.rdatasets.append(rds)
    115          return rds
    116
    117 -    def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
    118                       create=False):
    119          """Get an rdataset matching the specified properties in the
    120          current node.
    121
    122          None is returned if an rdataset of the specified type and
    123          class does not exist and I{create} is not True.
    124
    125          @param rdclass: The class of the rdataset
    126          @type rdclass: int
    127          @param rdtype: The type of the rdataset
    128          @type rdtype: int
    129          @param covers: The covered type.
    130          @type covers: int
    131          @param create: If True, create the rdataset if it is not found.
    132          @type create: bool
    133          @rtype: dns.rdataset.Rdataset object or None
    134          """
    135
    136          try:
    137              rds = self.find_rdataset(rdclass, rdtype, covers, create)
    138          except KeyError:
    139              rds = None
    140          return rds
    141
    142 -    def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
    143          """Delete the rdataset matching the specified properties in the
    144          current node.
    145
    146          If a matching rdataset does not exist, it is not an error.
    147
    148          @param rdclass: The class of the rdataset
    149          @type rdclass: int
    150          @param rdtype: The type of the rdataset
    151          @type rdtype: int
    152          @param covers: The covered type.
    153          @type covers: int
    154          """
    155
    156          rds = self.get_rdataset(rdclass, rdtype, covers)
    157          if not rds is None:
    158              self.rdatasets.remove(rds)
    159
    160 -    def replace_rdataset(self, replacement):
    161          """Replace an rdataset.
    162
    163          It is not an error if there is no rdataset matching I{replacement}.
    164
    165          Ownership of the I{replacement} object is transferred to the node;
    166          in other words, this method does not store a copy of I{replacement}
    167          at the node, it stores I{replacement} itself.
    168          """
    169
    170          self.delete_rdataset(replacement.rdclass, replacement.rdtype,
    171                               replacement.covers)
    172          self.rdatasets.append(replacement)
    173