# -*- coding: utf-8 -*- from __future__ import print_function class Prefix: def __init__(self, prefix, output, oneline): self.prefix = prefix self.output = output self.empty = oneline def pprint(self, data): self.output("%s%s" % (self.prefix, data)) if not self.empty: self.prefix = ' ' * len(self.prefix) self.empty = True class Printer: labels = { 'hostname': 'Hostname', 'arch': 'Architecture', 'os': 'Operating System', 'addresses': 'IPs', 'ports': 'Ports', 'vserver': 'VServer', 'services': 'Services', 'maintainers': 'Maintainers', 'description': 'Description' } ignore = ['vserver-host', 'groups'] def __init__(self, data, oneline, verbose): self.data = data self.oneline = oneline self.verbose = verbose def _sort_with_list(self, list, sort): def helper(value): if sort is None: return value (key, full_key) = value if key in sort: return sort.index(key) return "%d %s" % (len(sort), key) return sorted(list, key=helper) def print_addresses(self, value, pprint, prefix, filter_key): self._print_group_by(value, pprint, prefix, filter_key, lambda ip: 'vserver' not in ip and ip['interface'] or None, lambda ip: '%s/%s' % (ip['address'], ip['netmask'])) def print_vserver(self, value, pprint, prefix, filter_key): if value == 'guest': pprint('guest running on %s' % self.data['vserver-host']) else: pprint(value) def print_ports(self, value, pprint, prefix, filter_key): def _print_port(port): if port['proto'] in ['tcp6', 'udp6']: return '(%s) [%s]:%s' % (port['proto'].replace('6', ''), port['ip'], port['port']) return '(%s) %s:%s' % (port['proto'], port['ip'], port['port']) self._print_group_by(value, pprint, prefix, filter_key, lambda port: 'process' in port and port['process'] or 'UNKNOWN', _print_port, sort=['sshd', 'nrpe', 'munin-node']) def _print(self, value, pprint, prefix='', filter_key=None, sort=None): try: value = value.strip().splitlines() except: pass if isinstance(value, dict): self._print_dict(value, pprint, prefix, filter_key, sort) elif isinstance(value, list): for v in value: pprint(v) elif value is None: if self.verbose: pprint('') else: pprint(value) def _print_dict(self, value, pprint, prefix, filter_key, sort): keys = self._sort_with_list( [(key, full_key) for key in value.keys() for full_key in [self._get_full_key(prefix, key)] if full_key not in self.ignore or filter_key is not None and filter_key.startswith(full_key)], sort) maxlength = max(map(len, map(lambda (key, full_key): self._get_label(key, full_key), keys))) for (key, full_key) in keys: if filter_key is None or filter_key.startswith(full_key): new_filter_key = filter_key if full_key == filter_key: new_filter_key = None new_pprint = pprint if filter_key is None: label = "%s: " % self._get_label(key, full_key) if prefix == '': label = label.rjust(maxlength+4) else: label = label.ljust(maxlength+2) p = Prefix(label, pprint, self.oneline) new_pprint = p.pprint try: method = getattr(self, 'print_%s' % full_key.replace('.', '_')) method(value[key], new_pprint, full_key, new_filter_key) except AttributeError: self._print(value[key], new_pprint, full_key, new_filter_key) def _print_group_by(self, value, pprint, prefix, filter_key, group, format, sort=None): d = {} for e in value: key = group(e) if key is not None: d.setdefault(key, []).append(format(e)) self._print(d, pprint, prefix, filter_key, sort) def _get_full_key(self, prefix, key): if prefix == '': return key return "%s.%s" % (prefix, key) def _get_label(self, key, full_key): if full_key in self.labels: return self.labels[full_key] return key def info(self, key): self._print(self.data, print, filter_key=key, sort=['hostname', 'arch', 'os', 'addresses', 'ports'])