1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """DNS nodes. A node is a set of rdatasets."""
19
20 from io import StringIO
21
22 import dns.rdataset
23 import dns.rdatatype
24 import dns.renderer
25
26
28
29 """A Node is a set of rdatasets."""
30
31 __slots__ = ['rdatasets']
32
36
37 - def to_text(self, name, **kw):
38 """Convert a node to text format.
39
40 Each rdataset at the node is printed. Any keyword arguments
41 to this method are passed on to the rdataset's to_text() method.
42
43 *name*, a ``dns.name.Name`` or ``text``, the owner name of the rdatasets.
44
45 Returns a ``text``.
46 """
47
48 s = StringIO()
49 for rds in self.rdatasets:
50 if len(rds) > 0:
51 s.write(rds.to_text(name, **kw))
52 s.write(u'\n')
53 return s.getvalue()[:-1]
54
56 return '<DNS node ' + str(id(self)) + '>'
57
69
71 return not self.__eq__(other)
72
75
78
81 """Find an rdataset matching the specified properties in the
82 current node.
83
84 *rdclass*, an ``int``, the class of the rdataset.
85
86 *rdtype*, an ``int``, the type of the rdataset.
87
88 *covers*, an ``int``, the covered type. Usually this value is
89 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
90 dns.rdatatype.RRSIG, then the covers value will be the rdata
91 type the SIG/RRSIG covers. The library treats the SIG and RRSIG
92 types as if they were a family of
93 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
94 easier to work with than if RRSIGs covering different rdata
95 types were aggregated into a single RRSIG rdataset.
96
97 *create*, a ``bool``. If True, create the rdataset if it is not found.
98
99 Raises ``KeyError`` if an rdataset of the desired type and class does
100 not exist and *create* is not ``True``.
101
102 Returns a ``dns.rdataset.Rdataset``.
103 """
104
105 for rds in self.rdatasets:
106 if rds.match(rdclass, rdtype, covers):
107 return rds
108 if not create:
109 raise KeyError
110 rds = dns.rdataset.Rdataset(rdclass, rdtype)
111 self.rdatasets.append(rds)
112 return rds
113
116 """Get an rdataset matching the specified properties in the
117 current node.
118
119 None is returned if an rdataset of the specified type and
120 class does not exist and *create* is not ``True``.
121
122 *rdclass*, an ``int``, the class of the rdataset.
123
124 *rdtype*, an ``int``, the type of the rdataset.
125
126 *covers*, an ``int``, the covered type. Usually this value is
127 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
128 dns.rdatatype.RRSIG, then the covers value will be the rdata
129 type the SIG/RRSIG covers. The library treats the SIG and RRSIG
130 types as if they were a family of
131 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
132 easier to work with than if RRSIGs covering different rdata
133 types were aggregated into a single RRSIG rdataset.
134
135 *create*, a ``bool``. If True, create the rdataset if it is not found.
136
137 Returns a ``dns.rdataset.Rdataset`` or ``None``.
138 """
139
140 try:
141 rds = self.find_rdataset(rdclass, rdtype, covers, create)
142 except KeyError:
143 rds = None
144 return rds
145
147 """Delete the rdataset matching the specified properties in the
148 current node.
149
150 If a matching rdataset does not exist, it is not an error.
151
152 *rdclass*, an ``int``, the class of the rdataset.
153
154 *rdtype*, an ``int``, the type of the rdataset.
155
156 *covers*, an ``int``, the covered type.
157 """
158
159 rds = self.get_rdataset(rdclass, rdtype, covers)
160 if rds is not None:
161 self.rdatasets.remove(rds)
162
164 """Replace an rdataset.
165
166 It is not an error if there is no rdataset matching *replacement*.
167
168 Ownership of the *replacement* object is transferred to the node;
169 in other words, this method does not store a copy of *replacement*
170 at the node, it stores *replacement* itself.
171
172 *replacement*, a ``dns.rdataset.Rdataset``.
173
174 Raises ``ValueError`` if *replacement* is not a
175 ``dns.rdataset.Rdataset``.
176 """
177
178 if not isinstance(replacement, dns.rdataset.Rdataset):
179 raise ValueError('replacement is not an rdataset')
180 self.delete_rdataset(replacement.rdclass, replacement.rdtype,
181 replacement.covers)
182 self.rdatasets.append(replacement)
183