pvl/hosts/host.py
changeset 738 3104fdf7ea26
parent 734 5770ed34c1f0
child 739 5149c39f3dfc
equal deleted inserted replaced
737:6ba76ac0bc72 738:3104fdf7ea26
   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