예제 #1
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_collector(key, _data):
     if _data["state"] == "running":
         state = colorize(_data["state"], color.GREEN)
     else:
         state = colorize(_data["state"], color.RED)
     line = [
         " " + colorize(key, color.BOLD),
         state,
         "",
         fmt_tid(_data, stats_data),
         fmt_thr_tasks(key, stats_data),
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         speaker = data["monitor"].get("nodes", {}).get(nodename,
                                                        {}).get("speaker")
         if speaker:
             status = "up"
             status = colorize_status(status, lpad=0).replace(
                 status, unicons[status])
         else:
             status = ""
         line.append(status)
     out.append(line)
예제 #2
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_node_compat():
     if "monitor" not in data:
         return
     if data["monitor"].get("compat") is True:
         # no need to clutter if the situation is normal
         return
     line = [
         colorize(" compat", color.BOLD),
         colorize("warn", color.BROWN),
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         compat = data["monitor"]["nodes"].get(nodename,
                                               {}).get("compat", "")
         line.append(str(compat))
     out.append(line)
예제 #3
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_node_version():
     if "monitor" not in data:
         return
     line = [
         colorize(" version", color.BOLD),
         colorize("warn", color.BROWN),
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     versions = []
     for nodename in nodenames:
         agent = data["monitor"]["nodes"].get(nodename, {}).get("agent", "")
         line.append(str(agent))
         if agent != "":
             versions.append(str(agent))
     if len(set(versions)) > 1:
         out.append(line)
예제 #4
0
def print_table_default(data):
    try:
        data = validate_format(data)
    except Exception as e:
        return

    labels = data[0]
    max_label_len = reduce(lambda x,y: max(x,len(y)), labels, 0)+1
    data = data[1:]
    subsequent_indent = ""
    for i in range(max_label_len+3):
        subsequent_indent += " "
    fmt = " %-"+str(max_label_len)+"s "
    for j, d in enumerate(data):
        print("-")
        for i, label in enumerate(labels):
            val = '\n'.join(wrap(convert(d[i]),
                       initial_indent = "",
                       subsequent_indent = subsequent_indent,
                       width=78
                  ))
            try:
                print(colorize(fmt % (label+":"), color.LIGHTBLUE), val)
            except UnicodeEncodeError:
                print(colorize(fmt % (label+":"), color.LIGHTBLUE), val.encode("utf-8"))
예제 #5
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_daemon():
     key = "daemon"
     state = colorize("running", color.GREEN)
     line = [
         " " + colorize(key, color.BOLD),
         "%s" % state,
         "",
         str(data.get("pid", "")) if stats_data else "",
         "",
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         fmt_thr_mem_total(key, stats_data),
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         speaker = data["monitor"].get("nodes", {}).get(nodename,
                                                        {}).get("speaker")
         if speaker:
             status = "up"
             status = colorize_status(status, lpad=0).replace(
                 status, unicons[status])
         else:
             status = ""
         line.append(status)
     out.append(line)
예제 #6
0
    def format(self, record):
        record.message = record.getMessage()
        record.context = ""
        for xattr, key in self.attrs:
            if xattr == "sid" and not self.sid:
                continue
            try:
                val = getattr(record, xattr)
                if val:
                    record.context += "%s:%s " % (key, getattr(record, xattr))
            except AttributeError:
                pass
        record.context = record.context.rstrip()
        for pattern in extconfig.SECRETS:
            record.message = record.message.replace(pattern, "xxxx")

        if not self.human:
            return logging.Formatter.format(self, record)

        # Factorize context information, trim the level and colorize.
        buff = ""
        if self.last_context != record.context:
            buff += colorize("@ " + record.context, color.LIGHTBLUE) + "\n"
            self.last_context = record.context
        if record.levelname == "INFO":
            buff += "  " + record.message
        elif record.levelname == "ERROR":
            buff += colorize("E " + record.message, color.RED)
        elif record.levelname == "WARNING":
            buff += colorize("W " + record.message, color.BROWN)
        elif record.levelname == "DEBUG":
            buff += colorize("D " + record.message, color.LIGHTBLUE)
        return buff
예제 #7
0
파일: rcStatus.py 프로젝트: sghf/opensvc
def colorize_status(status, lpad=10, agg_status=None):
    """
    Return the colorized human readable status string.
    """
    if isinstance(status, Status):
        status = str(status)
    elif isinstance(status, int):
        status = str(Status(status))

    fmt = "%-" + str(lpad) + "s"
    if status is None:
        return colorize(fmt % "undef", color.LIGHTBLUE)
    elif status == "warn":
        return colorize(fmt % status, color.BROWN)
    elif status == "down" or status in ("err", "error"):
        if agg_status == "up":
            return colorize(fmt % status, color.LIGHTBLUE)
        else:
            return colorize(fmt % status, color.RED)
    elif status == "up" or status == "ok":
        return colorize(fmt % status, color.GREEN)
    elif status == "stdby up":
        if agg_status == "up":
            return colorize(fmt % status, color.LIGHTBLUE)
        else:
            return colorize(fmt % status, color.RED)
    elif status == "stdby down":
        return colorize(fmt % status, color.RED)
    elif status == "n/a":
        return colorize(fmt % status, color.LIGHTBLUE)
    else:
        return colorize(fmt % status, color.LIGHTBLUE)
예제 #8
0
def instance_notice(overall=None, frozen=None, node_frozen=None, constraints=None,
                    provisioned=None, monitor=None):
    notice = []
    if overall == "warn":
        notice.append(colorize(overall, STATUS_COLOR[overall]))
    if frozen:
        notice.append(colorize("frozen", color.BLUE))
    if node_frozen:
        notice.append(colorize("node frozen", color.BLUE))
    if not constraints:
        notice.append("constraints violation")
    if provisioned is False:
        notice.append(colorize("not provisioned", color.RED))
    if monitor == {}:
        # encap monitor
        pass
    elif monitor:
        mon_status = monitor.get("status", "unknown")
        if monitor["status"] == "idle":
            notice.append(colorize(mon_status, color.LIGHTBLUE))
        else:
            notice.append(colorize(mon_status, color.RED))
        if monitor.get("local_expect") not in ("", None):
            notice.append(colorize(monitor.get("local_expect", ""), color.LIGHTBLUE))
        if monitor.get("global_expect") not in ("", None):
            notice.append(colorize(">"+monitor.get("global_expect", ""), color.LIGHTBLUE))
    else:
        notice.append(colorize("daemon down", color.RED))
    return ", ".join(notice)
예제 #9
0
 def print_rcode(self, r):
     buff = "STATUS:   "
     if r == 1:
         buff += colorize("nok", color.RED)
     elif r == 0:
         buff += colorize("ok", color.GREEN)
     elif r == 2:
         buff += "n/a"
     else:
         buff += "%d" % r
     print(buff)
예제 #10
0
def get_svc_notice(data):
    svc_notice = []
    if "cluster" in data:
        overall = data["cluster"].get("overall", "n/a")
        if overall == "warn":
            svc_notice.append(colorize(overall, STATUS_COLOR[overall]))
        placement = data["cluster"].get("placement", "n/a")
        if placement not in ("optimal", "n/a"):
            svc_notice.append(colorize(placement + " placement", color.RED))
        compat = data["cluster"].get("compat", True)
        if not compat:
            svc_notice.append(colorize("incompatible versions", color.RED))
    return ", ".join(svc_notice)
예제 #11
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_hb(key, _data):
     state = _data.get("state", "")
     if state == "running":
         state = colorize(state, color.GREEN)
     else:
         state = colorize(state, color.RED)
     if _data.get("alerts"):
         state += colorize("!", color.BROWN)
     cf = _data.get("config", {})
     addr = cf.get("addr", "")
     port = cf.get("port", "")
     dev = cf.get("dev", "")
     relay = cf.get("relay", "")
     if addr and port:
         config = addr + ":" + str(port)
     elif dev:
         config = os.path.basename(dev)
     elif relay:
         config = relay
     else:
         config = ""
     line = [
         " " + colorize(key, color.BOLD),
         state,
         config,
         fmt_tid(_data, stats_data),
         fmt_thr_tasks(key, stats_data),
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     peers = _data.get("peers", {})
     for nodename in nodenames:
         beating = peers.get(nodename, {}).get("beating")
         if beating is None:
             status = "n/a"
         elif beating:
             status = "up"
         else:
             status = "down"
         status = colorize_status(status,
                                  lpad=0).replace(status, unicons[status])
         line.append(status)
     out.append(line)
예제 #12
0
 def highlighter(line):
     """
     Colorize interesting parts to help readability
     """
     line = line.rstrip("\n")
     if re.match(r'\[.+\]', line):
         return colorize(line, color.BROWN)
     line = re.sub(r"({[\.\w\-_#{}\[\]()\$\+]+})",
                   colorize(r"\1", color.GREEN), line)
     line = re.sub(r"^(\s*\w+\s*)=",
                   colorize(r"\1", color.LIGHTBLUE) + "=", line)
     line = re.sub(
         r"^(\s*\w+)(@[\w\.]+\s*)=",
         colorize(r"\1", color.LIGHTBLUE) + colorize(r"\2", color.RED) +
         "=", line)
     return line
예제 #13
0
    def format_action(self, section, action, options=True):
        """
        Format an candidate action for the help message.
        The action message may or may include the possible options,
        dependendin on the value of the options parameter.
        """
        fancya = self.prog + " " + action.replace('_', ' ')
        if self.colorize:
            desc = "  " + rcColor.colorize(fancya, rcColor.color.BOLD)
        else:
            desc = "  " + fancya
        desc += '\n\n'
        if self.async_actions.get(action, {}).get("local"):
            preamble = "Asynchronous orchestrated action, unless --local or --node <node> is specified.\n\n"
        else:
            preamble = ""
        wrapper = textwrap.TextWrapper(width=self.width - self.indent,
                                       replace_whitespace=False)
        text = preamble + self.actions[section][action]["msg"]
        text = text.replace("``", "`")
        for phrase in text.splitlines():
            for line in wrapper.wrap(phrase):
                for _line in line.splitlines():
                    desc += self.subsequent_indent + _line
            desc += '\n'

        if options:
            desc += self.format_options(section, action)

        desc = wipe_rest_markup(desc)
        desc += '\n'
        return desc
예제 #14
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_generic_thread(key, _data):
     if _data["state"] == "running":
         state = colorize(_data["state"], color.GREEN)
     else:
         state = colorize(_data["state"], color.RED)
     out.append((
         " " + colorize(key, color.BOLD),
         state,
         "",
         fmt_tid(_data, stats_data),
         fmt_thr_tasks(key, stats_data),
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         "",
         "",
         "",
     ))
예제 #15
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_listener(key, _data):
     if _data["state"] == "running":
         state = colorize(_data["state"], color.GREEN)
     else:
         state = colorize(_data["state"], color.RED)
     out.append((
         " " + colorize(key, color.BOLD),
         state,
         _data["config"]["addr"] + ":" + str(_data["config"]["port"]),
         fmt_tid(_data, stats_data),
         fmt_thr_tasks(key, stats_data),
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         "",
         "",
         "",
         "",
         "",
     ))
예제 #16
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_free_total(key):
     if "monitor" not in data:
         return
     line = [
         colorize("  " + key, color.BOLD),
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         total = data["monitor"]["nodes"].get(nodename, {}).get(
             "stats", {}).get(key + "_total")
         avail = data["monitor"]["nodes"].get(nodename, {}).get(
             "stats", {}).get(key + "_avail")
         limit = 100 - data["monitor"]["nodes"].get(nodename, {}).get(
             "min_avail_" + key, 0)
         if avail is None or total in (0, None):
             line.append("-")
             continue
         usage = 100 - avail
         total = print_size(total, unit="MB", compact=True)
         if limit:
             cell = "%d/%d%%:%s" % (usage, limit, total)
         else:
             cell = "%d%%:%s" % (usage, total)
         if usage > limit:
             cell = colorize(cell, color.RED)
         line.append(cell)
     out.append(line)
예제 #17
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_node_state():
     if "monitor" not in data:
         return
     line = [
         colorize(" state", color.BOLD),
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         nmon_state = data["monitor"]["nodes"].get(nodename, {}).get(
             "monitor", {}).get("status", "")
         if nmon_state == "idle":
             nmon_state = ""
         if data["monitor"]["nodes"].get(nodename, {}).get("frozen", ""):
             frozen = frozen_icon = colorize(unicons["frozen"], color.BLUE)
         else:
             frozen = ""
         global_expect = data["monitor"]["nodes"].get(nodename, {}).get(
             "monitor", {}).get("global_expect")
         if global_expect:
             global_expect = colorize(" >" + str(global_expect),
                                      color.LIGHTBLUE)
         else:
             global_expect = ""
         line.append(str(nmon_state) + frozen + global_expect)
     out.append(line)
예제 #18
0
파일: forest.py 프로젝트: sghf/opensvc
 def format_cell(text, width, textcolor, separator, align):
     """
     Format the table cell, happending the separator, coloring the text and
     applying the cell padding for alignment.
     """
     if text in ("", None):
         return " " * width + separator
     if align == "right":
         fmt = "%" + str(width) + "s"
     else:
         fmt = "%-" + str(width) + "s"
     cell = fmt % text
     if textcolor:
         cell = colorize(cell, textcolor)
     return cell + separator
예제 #19
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_monitor(key, _data):
     if _data["state"] == "running":
         state = colorize(_data["state"], color.GREEN)
     else:
         state = colorize(_data["state"], color.RED)
     transitions = _data.get("transitions", 0)
     if transitions:
         status = "%d transition" % transitions
     else:
         status = ""
     out.append((
         " " + colorize(key, color.BOLD),
         state,
         status,
         fmt_tid(_data, stats_data),
         fmt_thr_tasks(key, stats_data),
         fmt_thr_cpu_usage(key, prev_stats_data, stats_data),
         fmt_thr_cpu_time(key, stats_data),
         "",
         "",
         "",
         "",
         "",
     ))
예제 #20
0
 def status_logs_str(self, color=False):
     """
     Returns the formatted resource status log buffer entries.
     """
     status_str = ""
     for level, text in self.status_logs:
         if len(text) == 0:
             continue
         entry = level + ": " + text + "\n"
         if color:
             if level == "warn":
                 color = rcColor.color.BROWN
             elif level == "error":
                 color = rcColor.color.RED
             else:
                 color = rcColor.color.LIGHTBLUE
             status_str += rcColor.colorize(entry, color)
         else:
             status_str += entry
     return status_str
예제 #21
0
def colorize_json(s):
    import re
    from rcStatus import colorize_status
    s = re.sub(
        r'(")(error|ok|err|up|down|warn|n/a|stdby up|stdby down)(")', lambda m:
        m.group(1) + colorize_status(m.group(2), lpad=0) + m.group(3), s)
    s = re.sub(r'((?!"DEFAULT":)("[\w: ,@-]+":))',
               colorize(r'\1', color.LIGHTBLUE), s)
    s = re.sub(r'("DEFAULT":)( {)', colorize(r'\1', color.BROWN) + r'\2', s)
    s = re.sub(r'("[\w:-]+#[\w\.:-]+":)( {)',
               colorize(r'\1', color.BROWN) + r'\2', s)
    s = re.sub(r'(@[\w-]+)(":)',
               colorize(r'\1', color.RED) + colorize(r'\2', color.LIGHTBLUE),
               s)
    s = re.sub(r'({.+})', colorize(r'\1', color.GREEN), s)
    return s
예제 #22
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_header(title=""):
     if isinstance(title, list):
         line = title
     else:
         line = [
             title,
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
         ]
     for nodename in show_nodenames:
         line.append(colorize(nodename, color.BOLD))
     out.append(line)
예제 #23
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_arbitrators():
     if "arbitrators" not in sections:
         return
     arbitrators = []
     arbitrators_name = {}
     for nodename, ndata in data["monitor"]["nodes"].items():
         for aid, adata in ndata.get("arbitrators", {}).items():
             if aid not in arbitrators:
                 arbitrators.append(aid)
                 arbitrators_name[aid] = adata["name"]
     if len(arbitrators) == 0:
         return
     load_header("Arbitrators")
     for aid in arbitrators:
         line = [
             colorize(" " + arbitrators_name[aid], color.BOLD),
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "",
             "|" if nodenames else "",
         ]
         for nodename in nodenames:
             status = data["monitor"]["nodes"].get(nodename, {}).get(
                 "arbitrators", {}).get(aid, {}).get("status", "undef")
             if status != "up":
                 line[1] = colorize_status("warn", lpad=0)
             status = colorize_status(status, lpad=0).replace(
                 status, unicons[status])
             line.append(status)
         out.append(line)
     out.append([])
예제 #24
0
def print_table_tabulate(data, width=20):
    try:
        data = validate_format(data)
    except Exception as e:
        return

    from tabulate import tabulate
    import rcColor

    try:
        table = tabulate(data, headers="firstrow", tablefmt="plain").splitlines()
    except UnicodeEncodeError:
        table = tabulate(data, headers="firstrow", tablefmt="plain").encode("utf-8").splitlines()

    colors = [
        rcColor.color.BGWHITE+rcColor.color.BLACK,
        rcColor.color.E_BGODD+rcColor.color.BLACK,
    ]
    idx = 0
    tw = term_width()

    for line_idx, line in enumerate(table):
        if line.startswith("+-"):
            idx = (idx + 1) % 2
            continue
        if line_idx == 0:
            color = rcColor.color.BOLD
        else:
            color = colors[idx]
        if line.endswith("|"):
            cont = False
        else:
            cont = True
        length = len(line)
        if length > tw or cont:
            rpad = tw - (length % tw)
            line += " " * rpad
        print(rcColor.colorize(line, color))
예제 #25
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
 def load_loadavg():
     if "monitor" not in data:
         return
     line = [
         colorize("  load 15m", color.BOLD),
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "",
         "|" if nodenames else "",
     ]
     for nodename in nodenames:
         line.append(
             str(data["monitor"]["nodes"].get(nodename, {}).get(
                 "stats", {}).get("load_15m", "")))
     out.append(line)
예제 #26
0
def colorize_log_line(line, last=None, auto=None):
    """
    Format a log line, colorizing the log level.
    Return the line as a string buffer.
    """
    msg = os.linesep.join(line["m"])
    extra = ""
    for k, v in line["x"].items():
        if k in ("n", "o") and auto:
            try:
                i = auto.index(v)
                v = colorize(v, AUTO_COLORS[i % AUTO_COLORS_LEN])
            except (ValueError, IndexError):
                pass
        extra += "%s:%s " % (k, v)
    extra = extra.rstrip()
    lvl = line["l"]
    t = datetime.datetime.fromtimestamp(
        line["t"]).strftime("%Y-%m-%d %H:%M:%S,%f")

    if lvl == "INFO":
        lvl = colorize("INFO   ", color.LIGHTBLUE)
    elif lvl == "WARNING":
        lvl = colorize("WARNING", color.BROWN)
    elif lvl == "ERROR":
        lvl = colorize("ERROR  ", color.RED)
    elif lvl == "DEBUG":
        lvl = "DEBUG  "

    if msg.startswith("do "):
        msg = colorize(msg, color.BOLD)

    if auto:
        for i, word in enumerate(auto):
            msg = re.sub(
                "([\s,:@'\"]+)%s([\s,:@'\"]+)" % word,
                lambda m: m.group(1) + colorize(
                    word, AUTO_COLORS[i % AUTO_COLORS_LEN]) + m.group(2), msg)
    line = " ".join((t, lvl, extra, "|", msg))
    return line
예제 #27
0
 def print_bold(self, s):
     print(colorize(s, color.BOLD))
예제 #28
0
파일: fmt_cluster.py 프로젝트: sghf/opensvc
    def load_svc(path, prefix=""):
        if path not in services:
            return
        data = services[path]
        if path in slave_parents and prefix == "":
            return
        try:
            topology = services[path].topology
        except KeyError:
            topology = ""
        if services[path].get("drp", False):
            topology = "drp " + topology

        # status
        status = colorize_status(data["avail"], lpad=0)
        if data["overall"] == "warn":
            status += colorize("!", color.BROWN)
        if data["placement"] == "non-optimal":
            status += colorize("^", color.RED)

        # info
        info = {
            "topology": data.get("topology", ""),
            "orchestrate": data.get("orchestrate", "-"),
            "status": "%d/1" % data["n_up"] if data["n_up"] is not None else 0,
        }
        if data.get("scale") is not None:
            info["status"] = "%d/%d" % (data["n_up"], data.get("scale"))
        elif data.get("wrapper"):
            info = {
                "topology": "",
                "orchestrate": "",
                "status": "",
            }
        elif topology == "flex":
            info["status"] = "%d/%d" % (data["n_up"], data["flex_target"])
        if data["avail"] == "n/a":
            info["status"] = ""
        info = "%(orchestrate)-5s %(status)-5s" % info
        line = [
            " " + colorize(
                prefix + strip_path(path, os.environ.get("OSVC_NAMESPACE")),
                color.BOLD),
            status,
            info,
            fmt_svc_uptime(path, stats_data),
            fmt_svc_tasks(path, prev_stats_data),
            fmt_svc_cpu_usage(path, prev_stats_data, stats_data),
            fmt_svc_cpu_time(path, stats_data),
            fmt_svc_mem_total(path, stats_data),
            fmt_svc_blk_rb(path, stats_data),
            fmt_svc_blk_wb(path, stats_data),
            fmt_svc_blk_rbps(path, prev_stats_data, stats_data),
            fmt_svc_blk_wbps(path, prev_stats_data, stats_data),
            "|" if nodenames else "",
        ]
        for nodename in nodenames:
            if nodename not in data["nodes"]:
                line.append("")
            elif data["nodes"][nodename] is None:
                line.append(colorize("?", color.RED))
            elif data["nodes"][nodename] is not None:
                val = []
                # frozen unicon
                if data["nodes"][nodename]["frozen"]:
                    frozen_icon = colorize(unicons["frozen"], color.BLUE)
                else:
                    frozen_icon = ""
                # avail status unicon
                if data["wrapper"]:
                    avail_icon = ""
                else:
                    avail = data["nodes"][nodename]["avail"]
                    if avail == "unknown":
                        avail_icon = colorize("?", color.RED)
                    else:
                        avail_icon = colorize_status(
                            avail, lpad=0, agg_status=data["avail"]).replace(
                                avail, unicons[avail])
                # overall status unicon
                if data["wrapper"]:
                    overall_icon = ""
                else:
                    overall = data["nodes"][nodename]["overall"]
                    if overall == "warn":
                        overall_icon = colorize_status(
                            overall, lpad=0).replace(overall, unicons[overall])
                    else:
                        overall_icon = ""
                # mon status
                smon = data["nodes"][nodename]["mon"]
                if smon == "idle":
                    # don't display 'idle', as its to normal status and thus repeated as nauseam
                    smon = ""
                else:
                    smon = " " + smon
                # global expect
                if smon == "":
                    global_expect = data["nodes"][nodename]["global_expect"]
                    if global_expect:
                        global_expect = colorize(" >" + str(global_expect),
                                                 color.LIGHTBLUE)
                    else:
                        global_expect = ""
                else:
                    global_expect = ""
                # leader
                if data["wrapper"]:
                    leader = ""
                else:
                    if data["nodes"][nodename]["placement"] == "leader":
                        leader = colorize("^", color.LIGHTBLUE)
                    else:
                        leader = ""
                # provisioned
                if data["nodes"][nodename].get("provisioned") is False:
                    provisioned = colorize("P", color.RED)
                else:
                    provisioned = ""

                val.append(avail_icon)
                val.append(overall_icon)
                val.append(leader)
                val.append(frozen_icon)
                val.append(provisioned)
                val.append(smon)
                val.append(global_expect)
                line.append("".join(val))
        out.append(line)

        for child in sorted(list(data.get("slaves", []))):
            load_svc(child, prefix=prefix + " ")