# -*- coding: utf-8 -*- from __future__ import absolute_import from hostinfo import prefix def _get_full_key(prev_key, key): if prev_key == '': return key return "%s.%s" % (prev_key, key) def _sort_with_list(iterable, sort): def helper(value): if sort is None: return value (key, _) = value if key in sort: return sort.index(key) return "%d %s" % (len(sort), key) return sorted(iterable, key=helper) def _space(filter_key, full_key, printer, force=False): if filter_key is None and full_key == '': printer.space(force) def _group_by(value, group, display_check, print_value): groups = {} for elem in value: key = group(elem) if key is not None and display_check(key): groups.setdefault(key, []).append(print_value(elem)) return groups 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, flags): self.data = data self.flags = flags prefix.Printer.flags = flags def cb_print_addresses(self, value, full_key, filter_key): def _group_ip(address): if 'vserver' not in address: return address['interface'] else: return None def _print_ip(address): return '%s/%s' % (address['address'], address['netmask']) display_check = self._is_group_displayed(full_key, filter_key) return _group_by(value, _group_ip, display_check, _print_ip) def cb_print_ports(self, value, full_key, filter_key): def _group_port(port): if 'process' in port: return port['process'] else: return 'UNKNOWN' 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']) display_check = self._is_group_displayed(full_key, filter_key) return (_group_by(value, _group_port, display_check, _print_port), ['sshd', 'nrpe', 'munin-node']) def cb_print_vserver(self, value, full_key, filter_key): if value == 'guest' and 'vserver-host' in self.data and \ self.data['vserver-host'] is not None: return 'guest running on %s' % self.data['vserver-host'] else: return value def _should_display(self, full_key, filter_key=None): if full_key not in self.ignore: return True if filter_key is not None and filter_key.startswith(full_key): return True return False def _is_group_displayed(self, prev_key, filter_key): return (lambda key: self._should_display(_get_full_key(prev_key, key), filter_key)) def _print(self, value, printer, filter_key=None, sort=None): try: value = value.strip().splitlines() except AttributeError: pass if isinstance(value, dict): self._print_dict(value, printer, filter_key, sort) elif isinstance(value, list): for values in value: printer.pprint(values) elif value is None: if 'verbose' in self.flags: printer.pprint('') else: printer.pprint(value) def _print_key(self, key, value, printer, filter_key): sort = None try: method = getattr(self, 'cb_print_%s' % key.replace('.', '_')) result = method(value, printer.full_key, filter_key) if isinstance(result, tuple): value, sort = result else: value = result except AttributeError: pass self._print(value, printer, filter_key, sort) def _print_dict(self, value, printer, filter_key, sort): keys = _sort_with_list( [(key, full_key) for key in value.keys() for full_key in [_get_full_key(printer.full_key, key)] if self._should_display(full_key, filter_key)], sort) maxlength = max([len(self._get_label(key, full_key)) \ for (key, full_key) in keys]) _space(filter_key, printer.full_key, printer, True) for (key, full_key) in keys: new_filter_key = None if filter_key is not None: if filter_key.startswith(full_key + '.'): new_filter_key = filter_key elif full_key != filter_key: continue new_printer = prefix.Printer(full_key, printer) if filter_key is None: new_printer.set_label(self._get_label(key, full_key), maxlength) self._print_key(full_key, value[key], new_printer, new_filter_key) _space(filter_key, printer.full_key, new_printer) 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, prefix.Printer(), filter_key=key, sort=['hostname', 'arch', 'os', 'addresses', 'ports'])