terom@277: """ terom@277: Host definitions. terom@277: """ terom@277: terom@277: import pvl.args terom@277: import pvl.dns.zone terom@277: terom@277: import configobj terom@277: import ipaddr terom@277: import optparse terom@277: terom@277: def optparser (parser) : terom@277: hosts = optparse.OptionGroup(parser, "Hosts input") terom@277: hosts.add_option('--hosts-charset', metavar='CHARSET', default='utf-8', terom@277: help="Encoding used for host files") terom@277: terom@277: hosts.add_option('--hosts-domain', metavar='DOMAIN', terom@277: help="Default domain for hosts") terom@277: terom@277: return hosts terom@277: terom@277: class Host (object) : terom@277: @classmethod terom@277: def expand (cls, options, host, range, ip, **opts) : terom@277: host = pvl.dns.zone.parse_generate_field(host) terom@277: ip = pvl.dns.zone.parse_generate_field(ip) terom@277: terom@277: for i in range : terom@277: yield cls.build(options, host(i), terom@277: ip = ip(i), terom@277: **opts terom@277: ) terom@277: terom@277: @classmethod terom@277: def config (cls, options, host, ip=None, **extra) : terom@277: """ terom@277: Yield Hosts from a config section's scalars. terom@277: """ terom@277: terom@277: if '{' in host : terom@277: pre, host = host.split('{', 1) terom@277: range, post = host.rsplit('}', 1) terom@277: terom@277: range = pvl.dns.zone.parse_generate_range(range) terom@277: host = pre + "$" + post terom@277: terom@277: for host in cls.expand(options, host, range, ip, **extra) : terom@277: yield host terom@277: else : terom@277: yield cls.build(options, host, ip=ip, **extra) terom@277: terom@277: @classmethod terom@282: def build (cls, options, host, domain=None, ip=None, ip6=None, owner=None, boot=None, **extra) : terom@277: """ terom@277: Return a Host from a config section's scalars. terom@277: """ terom@277: terom@277: ethernet = [] terom@277: alias = [] terom@277: terom@277: for attr, value in extra.iteritems() : terom@277: if attr.startswith('ethernet') : terom@277: ethernet.append(value) terom@277: elif attr.startswith('alias') : terom@277: alias.append(value) terom@277: else : terom@277: raise ValueError("Unknown host attr: %s=%s" % (attr, value)) terom@277: terom@277: if domain is None : terom@277: domain = options.hosts_domain terom@277: terom@277: return cls(host, terom@277: domain = domain, terom@282: ip = ipaddr.IPv4Address(ip) if ip else None, terom@282: ip6 = ipaddr.IPv6Address(ip6) if ip6 else None, terom@277: ethernet = ethernet, terom@277: alias = alias, terom@277: owner = owner, terom@282: boot = boot, terom@277: ) terom@277: terom@282: def __init__ (self, host, domain=None, ip=None, ip6=None, ethernet=(), alias=(), owner=None, boot=None) : terom@277: """ terom@277: host - str terom@277: domain - str terom@282: ip - ipaddr.IPv4Address terom@282: ip6 - ipaddr.IPv6Address terom@277: ethernet - list terom@277: alias - list terom@277: owner - str: LDAP uid terom@277: """ terom@277: self.host = host terom@277: self.domain = domain terom@277: self.ip = ip terom@282: self.ip6 = ip6 terom@277: self.ethernet = ethernet terom@277: self.alias = alias terom@277: self.owner = owner terom@282: self.boot = boot terom@277: terom@277: def __str__ (self) : terom@277: return str(self.host) terom@277: terom@277: def apply_hosts_file (options, file) : terom@277: """ terom@277: Load Hosts from a file. terom@277: """ terom@277: config = configobj.ConfigObj(file, terom@277: encoding = options.hosts_charset, terom@277: ) terom@277: terom@277: for name in config.sections : terom@277: for host in Host.config(options, name, **config[name]) : terom@277: yield host terom@277: terom@277: def apply_hosts (options, files) : terom@277: """ terom@277: Load Hosts from files. terom@277: """ terom@277: terom@277: for file in files : terom@277: for host in apply_hosts_file(options, file) : terom@277: yield host terom@277: terom@277: def sort_hosts (options, hosts) : terom@277: """ terom@277: Yields hosts with a sorting key. terom@277: """ terom@277: terom@277: for host in hosts : terom@277: if host.ip : terom@277: sort = host.ip terom@277: else : terom@277: # sorts first terom@277: sort = ipaddr.IPAddress(0) terom@277: terom@277: yield sort, host terom@277: terom@277: def apply (options, args) : terom@277: """ terom@277: Load Hosts from arguments. terom@277: """ terom@277: terom@277: # without unicode terom@277: files = pvl.args.apply_files(args, 'r') terom@277: terom@277: # load configs terom@277: hosts = apply_hosts(options, files) terom@277: terom@277: # sort terom@277: hosts = list(sort_hosts(options, hosts)) terom@277: hosts.sort() terom@277: hosts = [host for sort, host in hosts] terom@277: terom@277: return hosts