# -*- coding: utf-8 -*- from __future__ import absolute_import from hostinfo import prefix from hostinfo import utils 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) 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 _print_ip(address): return '%s/%s' % (address['address'], address['netmask']) display_check = self._is_group_displayed(full_key, filter_key) return utils.group_by(value, 'interface', None, display_check, _print_ip) def cb_print_ports(self, value, full_key, 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']) display_check = self._is_group_displayed(full_key, filter_key) return (utils.group_by(value, 'process', 'UNKNOWN', 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, force=False): try: value = value.strip().splitlines() except AttributeError: pass if isinstance(value, dict): self._print_dict(value, printer, filter_key, sort, force) elif isinstance(value, list): self._print_list(value, printer, filter_key) elif value is None: if self.flags.verbose: printer.pprint('') else: self._print_value(value, printer, filter_key) 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_value(self, value, printer, filter_key): full_key = _get_full_key(printer.full_key, value) if self._should_display(full_key, filter_key) and \ filter_key is None or full_key == filter_key: printer.pprint(value) def _print_list(self, values, printer, filter_key): for value in values: if isinstance(value, basestring): self._print_value(value, printer, filter_key) else: self._print(value, printer, filter_key) def _print_dict(self, value, printer, filter_key, sort, force): 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) if len(keys) == 0: return maxlength = max([len(self._get_label(key, full_key)) \ for (key, full_key) in keys]) _space(filter_key, printer.full_key, printer, True) found = False 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 found = True 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) if force and not found: printer.pprint('') def _get_label(self, key, full_key): if full_key in self.labels: return self.labels[full_key] return key def info(self, key, label=None, maxlength=0, force=False): printer = prefix.Printer() if label is not None: printer.set_label(label, maxlength) self._print(self.data, printer, filter_key=key, force=force, sort=['hostname', 'arch', 'os', 'addresses', 'ports'])