Example #1
0
def status(arguments):
    """
    Main dispatcher for status commands. Calls the corresponding helper
    function.

    :param arguments: A dictionary of arguments already processed through
    this file's docstring with docopt
    :return: None
    """
    calico_node_info = filter(lambda container: "/calico-node" in
                              container["Names"],
                              docker_client.containers())
    if len(calico_node_info) == 0:
        print "calico-node container not running"
    else:
        print "calico-node container is running. Status: %s" % \
              calico_node_info[0]["Status"]

        apt_cmd = docker_client.exec_create("calico-node", ["/bin/bash", "-c",
                                           "apt-cache policy calico-felix"])
        result = re.search(r"Installed: (.*?)\s", docker_client.exec_start(apt_cmd))
        if result is not None:
            print "Running felix version %s" % result.group(1)

        print "\nIPv4 BGP status"
        pprint_bird_protocols(4)
        print "IPv6 BGP status"
        pprint_bird_protocols(6)
Example #2
0
def pprint_bird_protocols(version):
    """
    Pretty print the output from the BIRD "show protocols".  This parses the
    existing output and lays it out in pretty printed table.

    :param version:
    :return: None.
    """
    # Based on the IP version, run the appropriate BIRD command, and select
    # the appropriate separator char for an IP address.
    if version == 4:
        bird_cmd = docker_client.exec_create("calico-node",
                                    ["/bin/bash", "-c",
                                     "echo show protocols | "
                                     "birdc -s /etc/service/bird/bird.ctl"])
        results = docker_client.exec_start(bird_cmd)
        ip_sep = "."
    else:
        bird6_cmd = docker_client.exec_create("calico-node",
                                    ["/bin/bash", "-c",
                                     "echo show protocols | "
                                     "birdc6 -s "
                                     "/etc/service/bird6/bird6.ctl"])
        results = docker_client.exec_start(bird6_cmd)
        ip_sep = ":"

    # Parse the output from BIRD to extract the values in the protocol status
    # table.  We'll further parse the name since that includes details about
    # the type of peer and the peer IP address.
    x = PrettyTable(["Peer address", "Peer type", "State",
                     "Since", "Info"])
    lines = results.split("\n")
    found_table = False
    for line in lines:
        # When BIRD displays its protocol table, it prints the bird> prompt and
        # then shifts the cursor to print back over the prompt.  However, this
        # means that we get rogue prompts when parsing the output.  For this
        # processing just remove the prompt if it is present.
        if line.startswith("bird>"):
            line = line[5:]

        # Skip blank lines.
        line = line.strip()
        if not line:
            continue

        # Split the line into columns based on whitespace separators.  We split
        # a maximum of 5 times because the 6th "info" column may contain a
        # string that itself includes whitespace that should be maintained.
        columns = re.split("\s+", line.strip(), 5)

        # Loop until we find the table heading.
        if columns == ["name", "proto", "table", "state", "since", "info"]:
            found_table = True
            continue
        elif not found_table:
            continue

        # We expect either 5 or 6 columns depending on whether there was a
        # value in the info column.  Anything else is not handled, so revert
        # to displaying the raw BIRD output.
        if not (5 <= len(columns) <= 6):
            found_table = False
            break

        # Parse the name, we name our BGP peers as "Mesh", "Node" or "Global"
        # followed by the IP address.  Extract the info so we can pretty
        # print it.
        combined = columns[0]
        if combined.startswith("Mesh_"):
            name = combined[5:].replace("_", ip_sep)
            ptype = "node-to-node mesh"
        elif combined.startswith("Node_"):
            name = combined[5:].replace("_", ip_sep)
            ptype = "node specific"
        elif combined.startswith("Global_"):
            name = combined[7:].replace("_", ip_sep)
            ptype = "global"
        else:
            # This is not a BGP Peer, so do not include in the output.
            continue

        x.add_row([name, ptype, columns[3], columns[4],
                   columns[5] if len(columns) == 6 else ""])

    # If we parsed the table then pretty print the table, otherwise just output
    # the BIRD output directly.  The first line of the BIRD output provides an
    # overall BIRD status.
    if found_table:
        print str(x) + "\n"
    else:
        print results + "\n"