equal
deleted
inserted
replaced
136 |
136 |
137 else: |
137 else: |
138 # empty value |
138 # empty value |
139 return False |
139 return False |
140 |
140 |
141 def parse_dict(value, parse): |
141 def parse_dict(value, parse, **opts): |
142 if not value: |
142 if not value: |
143 return { } |
143 return { } |
144 |
144 |
145 if isinstance(value, dict): |
145 if isinstance(value, dict): |
146 values = value |
146 values = value |
147 else: |
147 else: |
148 values = {None: value} |
148 values = {None: value} |
149 |
149 |
150 return { instance: parse(value) for instance, value in values.iteritems() } |
150 return {instance: parse(value, **opts) for instance, value in values.iteritems()} |
151 |
151 |
152 class Host (object) : |
152 class Host (object) : |
153 """ |
153 """ |
154 A host is a network node that can have multiple ethernet interfaces, and multiple IP addresses in different domains. |
154 A host is a network node that can have multiple ethernet interfaces, and multiple IP addresses in different domains. |
155 """ |
155 """ |
182 Return a Host initialized from data attributes. |
182 Return a Host initialized from data attributes. |
183 |
183 |
184 This handles all string parsing to our data types. |
184 This handles all string parsing to our data types. |
185 """ |
185 """ |
186 |
186 |
187 ip4 = parse_dict(ip, ipaddr.IPv4Address) |
|
188 ip6 = parse_dict(ip6, ipaddr.IPv6Address) |
|
189 |
|
190 ip = {label: (ip4.get(label), ip6.get(label)) for label in set(ip4) | set(ip6)} |
|
191 |
|
192 |
|
193 return cls(name, |
187 return cls(name, |
194 domain = domain, |
188 domain = domain, |
195 ip4 = ip4.get(None), |
189 ip4 = parse_ip(ip, ipaddr.IPv4Address), |
196 ip6 = ip6.get(None), |
190 ip6 = parse_ip(ip6, ipaddr.IPv6Address), |
197 ip = ip, |
|
198 ethernet = parse_dict(ethernet, parse_ethernet), |
191 ethernet = parse_dict(ethernet, parse_ethernet), |
199 owner = owner, |
192 owner = owner, |
200 location = parse_location(location, domain), |
193 location = parse_location(location, domain), |
201 alias = parse_list(alias), |
194 alias = parse_list(alias), |
202 alias4 = parse_list(alias4), |
195 alias4 = parse_list(alias4), |
208 extensions = dict(cls.build_extensions(extensions)), |
201 extensions = dict(cls.build_extensions(extensions)), |
209 ) |
202 ) |
210 |
203 |
211 def __init__ (self, name, domain, |
204 def __init__ (self, name, domain, |
212 ip4=None, ip6=None, |
205 ip4=None, ip6=None, |
213 ip={}, |
|
214 ethernet={ }, |
206 ethernet={ }, |
215 owner=None, |
207 owner=None, |
216 location=None, |
208 location=None, |
217 alias=(), alias4=(), alias6=(), |
209 alias=(), alias4=(), alias6=(), |
218 forward=None, reverse=None, |
210 forward=None, reverse=None, |
223 """ |
215 """ |
224 name - str |
216 name - str |
225 domain - str |
217 domain - str |
226 ip4 - primary ipaddr.IPv4Address |
218 ip4 - primary ipaddr.IPv4Address |
227 ip6 - primary ipaddr.IPv6Address |
219 ip6 - primary ipaddr.IPv6Address |
228 ip - secondary { index: (ip4, ip6) } interface addresses |
|
229 ethernet - { index: ethernet } |
220 ethernet - { index: ethernet } |
230 alias - [ str ]: generate CNAMEs for given relative names |
221 alias - [ str ]: generate CNAMEs for given relative names |
231 owner - str: LDAP uid |
222 owner - str: LDAP uid |
232 location - None or (name, domain) |
223 location - None or (name, domain) |
233 alias4 - [ str ]: generate additional A records for given relative names |
224 alias4 - [ str ]: generate additional A records for given relative names |
243 |
234 |
244 self.name = name |
235 self.name = name |
245 self.domain = domain |
236 self.domain = domain |
246 self.ip4 = ip4 |
237 self.ip4 = ip4 |
247 self.ip6 = ip6 |
238 self.ip6 = ip6 |
248 self.ip = ip |
|
249 self.ethernet = ethernet |
239 self.ethernet = ethernet |
250 self.alias = alias |
240 self.alias = alias |
251 self.alias4 = alias4 |
241 self.alias4 = alias4 |
252 self.alias6 = alias6 |
242 self.alias6 = alias6 |
253 self.owner = owner |
243 self.owner = owner |
261 def sort_key (self): |
251 def sort_key (self): |
262 """ |
252 """ |
263 Stable sort ordering |
253 Stable sort ordering |
264 """ |
254 """ |
265 |
255 |
266 if self.ip: |
256 if self.ip4: |
267 return self.ip |
257 return self.ip4 |
268 else: |
258 else: |
269 # sorts first |
259 # sorts first |
270 return ipaddr.IPAddress(0) |
260 return ipaddr.IPAddress(0) |
271 |
261 |
272 def addresses (self): |
262 def addresses (self): |
273 """ |
263 """ |
274 Yield (sublabel, ipaddr) records. |
264 Yield (sublabel, ipaddr) records. |
275 """ |
265 """ |
276 |
266 |
277 for sublabel, (ip4, ip6) in self.ip.iteritems(): |
267 if self.ip4: |
278 |
268 yield None, self.ip4 |
279 if ip4: |
269 |
280 yield sublabel, ip4 |
270 if self.ip6: |
281 |
271 yield None, self.ip6 |
282 if ip6: |
|
283 yield sublabel, ip6 |
|
284 |
272 |
285 for extension in self.extensions.itervalues(): |
273 for extension in self.extensions.itervalues(): |
286 for sublabel, ip in extension.addresses(): |
274 for sublabel, ip in extension.addresses(): |
287 yield sublabel, ip |
275 yield sublabel, ip |
288 |
276 |
289 def fqdn (self): |
277 def fqdn (self): |
|
278 """ |
|
279 Return DNS FQDN for this host in its domain. |
|
280 """ |
|
281 |
290 if self.domain: |
282 if self.domain: |
291 return pvl.dns.fqdn(self.name, self.domain) |
283 return pvl.dns.fqdn(self.name, self.domain) |
292 else: |
284 else: |
293 return pvl.dns.fqdn(self.name) |
285 return pvl.dns.fqdn(self.name) |
294 |
286 |
297 domain = self.domain or '', |
289 domain = self.domain or '', |
298 ) |
290 ) |
299 |
291 |
300 class HostExtension (object): |
292 class HostExtension (object): |
301 """ |
293 """ |
302 Extension hooks |
294 Base class for Host.EXTENSIONS |
|
295 |
|
296 Provides default no-op behaviours for extension hooks. |
303 """ |
297 """ |
304 |
298 |
305 def addresses (self): |
299 def addresses (self): |
|
300 """ |
|
301 Yield additional (sublabel, ipaddr) records. |
|
302 """ |
|
303 |
306 return () |
304 return () |
307 |
305 |
308 def extension (cls): |
306 def extension (cls): |
309 """ |
307 """ |
310 Register an extension class |
308 Register an extension class |