Graphviz

From Noah.org
Jump to: navigation, search

Graphviz is a collection of tools for creating pictures from descriptions of graphs. It is not a GUI drawing tool. Instead, you write a description of a graph and Graphviz will draw it for you.

The main tool is `dot`. Without any options it doesn't do much. Usually you want to tell it to create a PNG.

dot -T png -o example.png example.dot

A dot script file is pretty simple. You pretty much just list nodes and denote connections between them with a '--' operator. You can repeat node names on different lines or you can list multiple connections on one line. Some special characters need quoting (note how I quote www.noah.org).

# This is simple, undirected graph of nodes. This just lists nodes. The edges have no labels.
graph example
{
    user -- internet
    internet -- "www.noah.org"
    database -- "www.noah.org"
    "Noah's home" -- "staging server" -- "www.noah.org"
}

You can also label the edges. Note how I broke the last two edges into two lines ("Noah's home" -- "staging server" -- "www.noah.org") so I could label each edge separately.

# This is simple, undirected graph of nodes. This adds labels to the edges.
graph example
{
    user -- internet [label="ISP"]
    internet -- "www.noah.org" [label="port 80"]
    database -- "www.noah.org" [label="port 3306"]
    "Noah's home" -- "staging server" [label="local"]
    "staging server" -- "www.noah.org" [label="port 22"]
}

You can create directed graphs using digraph instead of graph. Note that edges always point left->right. If you want an edge to point both directions then add "dir=both" to the properties (database -> "www.noah.org" [dir=both, label = "port 3306"]).

# This creates a directed graph.
digraph example
{
    user -> internet [label="ISP"]
    internet -> "www.noah.org" [label="port 80"]
    database  -> "www.noah.org" [dir=both, label="port 3306"]
    "Noah's home" -> "staging server" [label="local"]
    "staging server" -> "www.noah.org" [label="port 22"]
}

More advanced work

digraph finite_state_machine {
    graph[rankdir=LR size="8.5,11" dpi=300 ratio=fill center=1]
    //graph[rankdir=LR dpi=300 ratio=fill center=1]
    rankdir=LR
//    graph[rankdir=LR size="18,10"]
//    node [shape=box style=rounded color=black fontcolor=black fontsize=12];
    node [shape=box style=rounded fontsize=12];
//node [shape=box style=rounded weight=bold fontsize=18 color=black fontcolor=black]
    edge [color=black fontcolor=black fontsize=12]
    
    { rank=same
        off_lm1970 [label = "power=OFF\nLastMount=1970"];
        off_lm2011 [label = "power=OFF\nLastMount=2011"];
    }
    { rank = same
        lm2011_now2011 [style=bold,label = "System Running\nApp starts\nLastMount=2011\nnow=2011"];
        lm1970_now1970 [style=bold,label = "System Running Crippled\nApp does not start\nStuck on white screen\nLastMount=1970\nnow=1970"];
        lm2011_now1970 [style=bold,label = "System Crashing\nLastMount=2011\nnow=1970"];
        lm1970_now2011 [style=bold,label = "System Running Unsteady\nApp starts\nLastMount=1970\nnow=2011"];
    }
    { rank=same
        halt_lm2011_now2011 [label = ":Halt kernel\nLastMount=2011\nnow=2011"];
        halt_lm1970_now1970 [label = ":Halt kernel\nLastMount=1970\nnow=1970"];
    }
    { rank=same
        lm1970_now1970_boot_fsck [label = "boot: filesystem check\n:fsck rootfs\nLastMount=1970\nnow=1970"];
    }
    { rank=same
        lm1970_now1970_boot_ntp [label = "boot: start NTP update daemon\n:mount root filesystem\n:NTPD start"];
    }
    { rank=same
        lm2011_rtc_query_i2c [label=":query RTC via I2C bus"]
        lm1970_rtc_query_i2c [label=":query RTC via I2C bus"]
    }
    { rank=same
        panic_unrelated [shape = doublecircle, label = "ERROR\nUnrelated\n:Halt kernel"];
        panic_fs_error [shape = doublecircle, label = "ERROR\nFileSystem\nStuck on white screen\n:Halt kernel"];
    }

    // Transitions.
    lm2011_now2011 -> halt_lm2011_now2011 [label="clean shutdown"];
    lm2011_now2011 -> off_lm2011 [label="power off"];
    lm2011_now1970 -> panic_fs_error [weight=bold fontsize=32 label="λ: fsck BAD"];
    lm1970_now1970_boot_fsck -> lm1970_now1970_boot_ntp [label="fsck OK"]; 
    lm1970_now1970_boot_fsck -> panic_unrelated [label="fsck BAD"]; 
    lm1970_now2011 -> off_lm1970 [label="power off"];
    lm1970_now2011 -> halt_lm2011_now2011 [label="clean shutdown"];
    lm1970_now1970_boot_ntp -> lm1970_now1970 [label="NTP BAD"];
    lm1970_now1970_boot_ntp -> lm1970_now2011 [label="NTP GOOD"];
    halt_lm2011_now2011 -> off_lm2011 [label="power off"];
    off_lm2011 -> lm2011_rtc_query_i2c [label="power on"] //lm2011_now1970 [label="power on,\nbad RTC"];
    lm2011_rtc_query_i2c -> lm2011_now2011 [label="RTC OK"] //lm2011_now1970 [label="power on,\nbad RTC"];
    lm2011_rtc_query_i2c -> lm2011_now1970 [label="RTC BAD"] //lm2011_now1970 [label="power on,\nbad RTC"];
    //off_lm1970 -> lm1970_now1970_boot_fsck [label="power on,\nbad RTC"];
    off_lm1970 -> lm1970_rtc_query_i2c [label="power on"];
    lm1970_rtc_query_i2c -> lm1970_now1970_boot_fsck [label="RTC BAD"];
    lm1970_rtc_query_i2c -> lm1970_now2011 [label="RTC GOOD"];
    //lm1970_now1970_boot_fsck -> lm1970_now1970 [label="power on,\nbad RTC"];//->lm1970_now1970_boot_ntp
    off_lm2011 -> lm2011_now2011 [label="power on,\ngood RTC"];
    halt_lm1970_now1970 -> off_lm1970 [label="power off"];
    lm1970_now1970 -> halt_lm1970_now1970 [label="clean shutdown\n(Unlikely exept by developers.)"];
}

// Makefile: 
// all:
//      @ dot -T png rtc.dot | display - 2>&1 >/dev/null &
//  :map <F5> <CR>:silent !make<CR><CR>:redraw!<CR>