1 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
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.
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.
16 """DNS nodes. A node is a set of rdatasets."""
27 A node is a set of rdatasets
29 @ivar rdatasets: the node's rdatasets
30 @type rdatasets: list of dns.rdataset.Rdataset objects"""
32 __slots__
= ['rdatasets']
35 """Initialize a DNS node.
40 def to_text(self
, name
, **kw
):
41 """Convert a node to text format.
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
50 s
= StringIO
.StringIO()
51 for rds
in self
.rdatasets
:
52 print >> s
, rds
.to_text(name
, **kw
)
53 return s
.getvalue()[:-1]
56 return '<DNS node ' + str(id(self
)) + '>'
58 def __eq__(self
, other
):
59 """Two nodes are equal if they have the same rdatasets.
64 # This is inefficient. Good thing we don't need to do it much.
66 for rd
in self
.rdatasets
:
67 if rd
not in other
.rdatasets
:
69 for rd
in other
.rdatasets
:
70 if rd
not in self
.rdatasets
:
74 def __ne__(self
, other
):
75 return not self
.__eq
__(other
)
78 return len(self
.rdatasets
)
81 return iter(self
.rdatasets
)
83 def find_rdataset(self
, rdclass
, rdtype
, covers
=dns
.rdatatype
.NONE
,
85 """Find an rdataset matching the specified properties in the
88 @param rdclass: The class of the rdataset
90 @param rdtype: The type of the rdataset
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.
101 @param create: If True, create the rdataset if it is not found.
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
108 for rds
in self
.rdatasets
:
109 if rds
.match(rdclass
, rdtype
, covers
):
113 rds
= dns
.rdataset
.Rdataset(rdclass
, rdtype
)
114 self
.rdatasets
.append(rds
)
117 def get_rdataset(self
, rdclass
, rdtype
, covers
=dns
.rdatatype
.NONE
,
119 """Get an rdataset matching the specified properties in the
122 None is returned if an rdataset of the specified type and
123 class does not exist and I{create} is not True.
125 @param rdclass: The class of the rdataset
127 @param rdtype: The type of the rdataset
129 @param covers: The covered type.
131 @param create: If True, create the rdataset if it is not found.
133 @rtype: dns.rdataset.Rdataset object or None
137 rds
= self
.find_rdataset(rdclass
, rdtype
, covers
, create
)
142 def delete_rdataset(self
, rdclass
, rdtype
, covers
=dns
.rdatatype
.NONE
):
143 """Delete the rdataset matching the specified properties in the
146 If a matching rdataset does not exist, it is not an error.
148 @param rdclass: The class of the rdataset
150 @param rdtype: The type of the rdataset
152 @param covers: The covered type.
156 rds
= self
.get_rdataset(rdclass
, rdtype
, covers
)
158 self
.rdatasets
.remove(rds
)
160 def replace_rdataset(self
, replacement
):
161 """Replace an rdataset.
163 It is not an error if there is no rdataset matching I{replacement}.
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.
170 self
.delete_rdataset(replacement
.rdclass
, replacement
.rdtype
,
172 self
.rdatasets
.append(replacement
)