Commit c87af26f authored by Greg Rutz's avatar Greg Rutz

More complex example working

parent 1c58e287
......@@ -2,7 +2,7 @@ digraph G {
rankdir = BT
serverDate [shape=box,lciuri="lci:/date",program="/bin/date"]
n2 [type=serverNode]
serverLS [shape=box,lciuri="lci:/ls",program="/bin/ls"]
serverLS [shape=box,lciuri="lci:/ls",program="/bin/ls -a"]
n3 [type=serverNode]
client [shape=triangle,type=client]
n1 [type=clientNode]
......
digraph G {
rankdir = BT
srv_lsl [shape=box,lciuri="lci:/grutz/bin/ls/l",program="/bin/ls -l"]
srv_lsa [shape=box,lciuri="lci:/grutz/bin/ls/a",program="/bin/ls -a"]
srv_ls [shape=box,lciuri="lci:/grutz/bin/ls",program="/bin/ls"]
srv_pse [shape=box,lciuri="lci:/grutz/bin/ps/e",program="/bin/ps -e"]
srv_psd [shape=box,lciuri="lci:/grutz/bin/ps/d",program="/bin/ps -d"]
srv_ps [shape=box,lciuri="lci:/grutz/bin/ps/e",program="/bin/ps"]
srv_dateR [shape=box,lciuri="lci:/grutz/bin/date/R",program="/bin/date -R"]
srv_dateu [shape=box,lciuri="lci:/grutz/bin/date/u",program="/bin/date -u"]
srv_date [shape=box,lciuri="lci:/grutz/bin/date",program="/bin/date"]
ls [type=serverNode]
ls -> srv_lsl
ls -> srv_lsa
ls -> srv_ls
ps [type=serverNode]
ps -> srv_pse
ps -> srv_psd
ps -> srv_ps
date [type=serverNode]
date -> srv_dateR
date -> srv_dateu
date -> srv_date
co1 [type=anode]
co1 -> date [label="lci:/grutz/bin/date"]
co1 -> ls [label="lci:/grutz/bin/ls"]
co1 -> ps [label="lci:/grutz/bin/ps"]
e1 [type=anode]
e1 -> co1 [label="lci:/grutz/bin"]
e2 [type=anode]
e2 -> co1 [label="lci:/grutz/bin"]
c1 [shape=triangle,type=client]
c1n [type=clientNode]
c1n -> e1 [label="lci:/grutz"]
c1 -> c1n
c2 [shape=triangle,type=client]
c2n [type=clientNode]
c2n -> e1 [label="lci:/grutz"]
c2 -> c2n
c3 [shape=triangle,type=client]
c3n [type=clientNode]
c3n -> e1 [label="lci:/grutz"]
c3 -> c3n
c4 [shape=triangle,type=client]
c4n [type=clientNode]
c4n -> e2 [label="lci:/grutz"]
c4 -> c4n
c5 [shape=triangle,type=client]
c5n [type=clientNode]
c5n -> e2 [label="lci:/grutz"]
c5 -> c5n
c6 [shape=triangle,type=client]
c6n [type=clientNode]
c6n -> e2 [label="lci:/grutz"]
c6 -> c6n
}
import argparse
from pydotplus.graphviz import graph_from_dot_file
from subprocess import check_output
from subprocess import CalledProcessError
......@@ -5,15 +6,18 @@ from subprocess import STDOUT
from sys import argv
from os import getcwd
if len(argv) != 2:
print('Must specify dotfile name!')
raise SystemExit
dotfile = argv[1]
container = 'grutz/ccnx-ubuntu'
# Build argument parser (and help)
argparser = argparse.ArgumentParser(description='Build a linked set of docker CCNx nodes according to a dotfile graph description.')
argparser.add_argument('--test', action='store_true',
help='Test. Do not actually run any containers.')
argparser.add_argument('--container', metavar='CONT', default='grutz/ccnx-ubuntu',
help='The container to run.')
argparser.add_argument('dotfile', metavar='DOTFILE',
help='The DOT file containing the graph/network description')
args = argparser.parse_args()
print('Parsing dot file (' + dotfile + ')...')
graph = graph_from_dot_file(dotfile)
print('Parsing dot file (' + args.dotfile + ')...')
graph = graph_from_dot_file(args.dotfile)
docker_volumes = {
'node' : getcwd() + '/runnode.sh:/runnode.sh:ro',
......@@ -79,7 +83,7 @@ for sn in server_nodes:
remove_quotes(server.get('program'))]
# Build docker command
docker_cmd = build_docker_run(container,
docker_cmd = build_docker_run(args.container,
volumes=[docker_volumes['node']],
name=node_name,
command=run_scripts['node'],
......@@ -87,37 +91,42 @@ for sn in server_nodes:
print('(' + node_name + ') Server cmd: ' + " ".join(docker_cmd))
try:
print('(' + node_name + ') Server container: ' + \
check_output(docker_cmd, stderr=STDOUT).decode("utf-8"))
if not args.test:
print('(' + node_name + ') Server container: ' + \
check_output(docker_cmd, stderr=STDOUT).decode("utf-8"))
except CalledProcessError as exc:
print("DOCKER COMMAND FAILED! Code={} \n{}\n".format(exc.returncode,
exc.output.decode("utf-8")))
global running_node_names
running_node_names += [node_name]
# Breadth-first recursion of our network tree to start all nodes
# that have the given nodes as targets
def start_nodes(target_nodes):
global running_node_names
next_nodes = []
nodes_to_start = {}
for target in target_nodes:
target_name = target.get_name()
print('Checking target node: ' + target_name)
# Find all edges that are directed at target
edges = find_edges(dst=target_name)
new_nodes = []
nodes_to_start = {}
for edge in edges:
source_node = find_node(edge.get_source())
source_name = source_node.get_name()
print('Checking edge: ' + target_name + ' -> ' + source_name)
# A node is only started if it is not already running, it is
# not a client and all of its link targets are running
if source_node.get('type') == 'client' or source_name in running_node_names:
print('Ignoring source node because it is a client or already running')
continue
target_edges = find_edges(src=source_name)
if len([t for t in target_edges if t.get_destination() not in running_node_names]) != 0:
print('Ignoring because not all of the source node\'s target nodes are running')
continue
# Build links args for docker and link routes for our metis script
......@@ -141,46 +150,50 @@ def start_nodes(target_nodes):
[str("-r " + alias + "=" + route) for alias in all_routes \
for route in all_routes[alias]]
nodes_to_start[source_name] = {'node':source_node,
'links':links,
'routes':routes}
if source_name not in nodes_to_start:
print('Adding ' + source_name + ' to "nodes_to_start" list')
nodes_to_start[source_name] = {'node':source_node,
'links':links,
'routes':routes}
for node_name in nodes_to_start:
# Run the container and metis forwarder and establish
# all required links
node = nodes_to_start[node_name]
docker_cmd = build_docker_run(args.container,
volumes=[docker_volumes['node']],
name=node_name,
links=node['links'],
command=run_scripts['node'],
command_args=node['routes'])
is_client = (node['node'].get('type') == 'clientNode')
# Run node container
print('(' + node_name + ') Node cmd: ' + " ".join(docker_cmd))
try:
if not args.test:
node_id = check_output(docker_cmd).decode("utf-8").strip()
print('(' + node_name + ') Node container: ' + node_id)
except CalledProcessError as exc:
print("DOCKER COMMAND FAILED! Code={} \n{}\n".format(exc.returncode,
exc.output.decode("utf-8")))
# Add this node to our list of newly run nodes and to our
# global list of running nodes
next_nodes += [find_node(node_name)]
running_node_names += [node_name]
for node_name in nodes_to_start:
# Run the container and metis forwarder and establish
# all required links
node = nodes_to_start[node_name]
docker_cmd = build_docker_run(container,
volumes=[docker_volumes['node']],
name=node_name,
links=node['links'],
command=run_scripts['node'],
command_args=node['routes'])
is_client = (node['node'].get('type') == 'clientNode')
# Run node container
try:
print('(' + source_name + ') Node cmd: ' + " ".join(docker_cmd))
except CalledProcessError as exc:
print("DOCKER COMMAND FAILED! Code={} \n{}\n".format(exc.returncode,
exc.output.decode("utf-8")))
node_id = check_output(docker_cmd).decode("utf-8").strip()
print('(' + source_name + ') Node container: ' + node_id)
# Add this node to our list of newly run nodes and to our
# global list of running nodes
new_nodes += [find_node(source_name)]
running_node_names += [source_name]
# Show instructions for how to enter client node
if is_client:
print('CLIENT NODE! Run this command to enter the ' \
'container and perform client actions:')
print('\tdocker exec -i -t ' + node_id + ' /bin/bash')
# Show instructions for how to enter client node
if not args.test and is_client:
print('CLIENT NODE! Run this command to enter the ' \
'container and perform client actions:')
print('\tdocker exec -i -t ' + node_name + ' /bin/bash')
# Recurse to start the next level of nodes
if len(new_nodes) != 0:
start_nodes(new_nodes)
# Recurse to start the next level of nodes
if len(next_nodes) != 0:
print('Starting next level nodes (' + str([x.get_name() for x in next_nodes]) + ')')
start_nodes(next_nodes)
print("Starting all other nodes...")
start_nodes(server_nodes)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment