...add missing pvl.hosts, with dynamic hosts support
authorTero Marttila <terom@paivola.fi>
Mon, 16 Dec 2013 20:21:09 +0200
changeset 277 5f0b67ba454f
parent 276 8db56588cefc
child 278 2db1a5323f92
...add missing pvl.hosts, with dynamic hosts support
pvl/hosts.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pvl/hosts.py	Mon Dec 16 20:21:09 2013 +0200
@@ -0,0 +1,150 @@
+"""
+    Host definitions.
+"""
+
+import pvl.args
+import pvl.dns.zone
+
+import configobj
+import ipaddr
+import optparse
+
+def optparser (parser) :
+    hosts = optparse.OptionGroup(parser, "Hosts input")
+    hosts.add_option('--hosts-charset',         metavar='CHARSET',  default='utf-8', 
+            help="Encoding used for host files")
+
+    hosts.add_option('--hosts-domain',          metavar='DOMAIN',
+            help="Default domain for hosts")
+    
+    return hosts
+
+class Host (object) :
+    @classmethod
+    def expand (cls, options, host, range, ip, **opts) :
+        host = pvl.dns.zone.parse_generate_field(host)
+        ip = pvl.dns.zone.parse_generate_field(ip)
+
+        for i in range :
+            yield cls.build(options, host(i),
+                    ip  = ip(i),
+                    **opts
+            )
+
+    @classmethod
+    def config (cls, options, host, ip=None, **extra) :
+        """
+            Yield Hosts from a config section's scalars.
+        """
+
+        if '{' in host :
+            pre, host = host.split('{', 1)
+            range, post = host.rsplit('}', 1)
+            
+            range = pvl.dns.zone.parse_generate_range(range)
+            host = pre + "$" + post
+
+            for host in cls.expand(options, host, range, ip, **extra) :
+                yield host
+        else :
+            yield cls.build(options, host, ip=ip, **extra)
+    
+    @classmethod
+    def build (cls, options, host, domain=None, ip=None, owner=None, **extra) :
+        """
+            Return a Host from a config section's scalars.
+        """
+
+        ethernet = []
+        alias = []
+
+        for attr, value in extra.iteritems() :
+            if attr.startswith('ethernet') :
+                ethernet.append(value)
+            elif attr.startswith('alias') :
+                alias.append(value)
+            else :
+                raise ValueError("Unknown host attr: %s=%s" % (attr, value))
+        
+        if domain is None :
+            domain = options.hosts_domain
+        
+        return cls(host,
+                domain      = domain,
+                ip          = ipaddr.IPAddress(ip) if ip else None,
+                ethernet    = ethernet,
+                alias       = alias,
+                owner       = owner,
+        )
+
+    def __init__ (self, host, domain=None, ip=None, ethernet=(), alias=(), owner=None) :
+        """
+            host        - str
+            domain      - str
+            ip          - ipaddr.IPAddress
+            ethernet    - list
+            alias       - list
+            owner       - str: LDAP uid
+        """
+        self.host = host
+        self.domain = domain
+        self.ip = ip
+        self.ethernet = ethernet
+        self.alias = alias
+        self.owner = owner
+
+    def __str__ (self) :
+        return str(self.host)
+
+def apply_hosts_file (options, file) :
+    """
+        Load Hosts from a file.
+    """
+    config = configobj.ConfigObj(file,
+            encoding    = options.hosts_charset,
+    )
+
+    for name in config.sections :
+        for host in Host.config(options, name, **config[name]) :
+            yield host
+
+def apply_hosts (options, files) :
+    """
+        Load Hosts from files.
+    """
+
+    for file in files :
+        for host in apply_hosts_file(options, file) :
+            yield host
+
+def sort_hosts (options, hosts) :
+    """
+        Yields hosts with a sorting key.
+    """
+
+    for host in hosts :
+        if host.ip :
+            sort = host.ip
+        else :
+            # sorts first
+            sort = ipaddr.IPAddress(0)
+
+        yield sort, host
+
+def apply (options, args) :
+    """
+        Load Hosts from arguments.
+    """
+    
+    # without unicode
+    files = pvl.args.apply_files(args, 'r')
+
+    # load configs
+    hosts = apply_hosts(options, files)
+
+    # sort
+    hosts = list(sort_hosts(options, hosts))
+    hosts.sort()
+    hosts = [host for sort, host in hosts]
+    
+    return hosts