Index: fedd/fedd_client.py
===================================================================
--- fedd/fedd_client.py	(revision 63f374626fb62134c95b058a1b959462708a3c0d)
+++ fedd/fedd_client.py	(revision cc58813b7e5b89a8a2c884152488f6b872366038)
@@ -6,4 +6,6 @@
 import tempfile
 import subprocess
+import re
+import xml.parsers.expat
 
 from federation import fedid, service_error
@@ -118,4 +120,7 @@
 		default=False,
 		help="get output suitable for federation kit install")
+	self.add_option('-G','--gatewaykit', action='store_true',
+		dest='gatewaykit', default=False,
+		help="get output suitable for federation gateway kit install")
 
 
@@ -152,5 +157,20 @@
 		help="output image file")
 	self.add_option("-F", "--format", dest="format", type="choice", 
-		choices=("jpg", "png", "dot"),
+		choices=("jpg", "png", "dot", "svg"),
+		help="Output file format override")
+	self.add_option("-P", "--program", dest="neato", default=None,
+		type="string",
+		help="Program compatible with dot (from graphviz) used to " + \
+			"render image")
+
+class fedd_ns_image_opts(fedd_split_opts):
+    def __init__(self, access_keys, add_key_callback=None, 
+	    add_cert_callback=None):
+	fedd_split_opts.__init__(self, access_keys, add_key_callback, 
+		add_cert_callback)
+	self.add_option("-o", "--output", dest="outfile", type="string",
+		help="output image file")
+	self.add_option("-Q", "--format", dest="format", type="choice", 
+		choices=("jpg", "png", "dot", "svg"),
 		help="Output file format override")
 	self.add_option("-P", "--program", dest="neato", default=None,
@@ -394,13 +414,11 @@
 
 
-# Querying experiment data follows the same control flow regardless of the
-# specific data retrieved.  This class encapsulates that control flow.
 class image(fedd_rpc):
-    def __init__(self): 
+    def __init__(self, op): 
 	"""
 	Null constructor
 	"""
 
-	fedd_rpc.__init__(self, "Vtopo")
+	fedd_rpc.__init__(self, op)
 
     def gen_image(self, d, file, fmt, neato):
@@ -430,7 +448,14 @@
 	cmd.append(dotname)
 
+	nodes = d.get('node',[])
+
+	if len(nodes) < 10: size = 5
+	elif len(nodes) < 50: size = 10
+	else: size = 18
+
 	print >>dotfile, "graph G {"
+	print >>dotfile, '\tgraph [size="%i,%i", ratio=fill];' % (size, size)
 	print >>dotfile, '\tnode [fontname=arial,fontsize=9,label="\N"];'
-	print >>dotfile, '\tedge [fontname=arial,fontsize=9,label="\N"];\n'
+	print >>dotfile, '\tedge [fontname=arial,fontsize=9];\n'
 
 	for n in d.get('node', []):
@@ -446,15 +471,16 @@
 	    v = n['vname']
 	    m = n['member']
+	    i = n['ip']
 	    if m.find(':') != -1:
 		m = m[0:m.find(':')]
 	    if lans.has_key(v):
-		lans[v].append(m)
+		lans[v].append((m, i))
 	    elif links.has_key(v):
-		links[v].append(m)
+		links[v].append((m, i))
 		if len(links[v]) > 2:
 		    lans[v] = links[v]
 		    del links[v]
 	    else:
-		links[v] = [m]
+		links[v] = [(m, i)]
 
 	# Encode the lans and the links
@@ -463,9 +489,12 @@
 	    print >>dotfile,'\t\tcolor=black,fillcolor="#80c0f8",regular=1]'
 	    for n in lans[l]:
-		print >>dotfile, '\t%s -- %s' % (l, n)
+		print >>dotfile, '\t%s -- %s [headlabel="%s"]' % (l, n[0], n[1])
 
 	for k, l in links.items():
 	    if len(l) == 2:
-		print >>dotfile, '\t%s -- %s [label="%s"]' % (l[0], l[1], k)
+		print >>dotfile, \
+			('\t%s -- %s [label="%s",taillabel="%s",' + \
+			'headlabel="%s"]') % \
+			(l[0][0], l[1][0], k, l[0][1], l[1][1])
 
 	print >>dotfile, "}"
@@ -524,5 +553,5 @@
 	elif not opts.format and opts.outfile:
 	    fmt = opts.outfile[-3:]
-	    if fmt not in ("png", "jpg", "dot"):
+	    if fmt not in ("png", "jpg", "dot", "svg"):
 		sys.exit("Unexpected file type and no format specified")
 	    file = opts.outfile
@@ -552,4 +581,162 @@
 	if resp_dict.has_key('vtopo'):
 	    self.gen_image(resp_dict['vtopo'], file, fmt, opts.neato)
+	else:
+	    sys.exit("Bad response. %s" % e.message)
+
+class ns_image(image):
+    def __init__(self, op): 
+	"""
+	Null constructor
+	"""
+
+	image.__init__(self, op)
+
+    def generate_topo_dict(self, splitout):
+	class topo_parse:
+	    """
+	    Parse the topology XML and create the dats structure.  This class
+	    is copied from federation.experiment_control.
+	    """
+	    def __init__(self):
+		# Typing of the subelements for data conversion
+		self.str_subelements = ('vname', 'vnode', 'ips', 'ip', 'member')
+		self.int_subelements = ( 'bandwidth',)
+		self.float_subelements = ( 'delay',)
+		# The final data structure
+		self.nodes = [ ]
+		self.lans =  [ ]
+		self.topo = { \
+			'node': self.nodes,\
+			'lan' : self.lans,\
+		    }
+		self.element = { }  # Current element being created
+		self.chars = ""	    # Last text seen
+
+	    def end_element(self, name):
+		# After each sub element the contents is added to the current
+		# element or to the appropriate list.
+		if name == 'node':
+		    self.nodes.append(self.element)
+		    self.element = { }
+		elif name == 'lan':
+		    self.lans.append(self.element)
+		    self.element = { }
+		elif name in self.str_subelements:
+		    self.element[name] = self.chars
+		    self.chars = ""
+		elif name in self.int_subelements:
+		    self.element[name] = int(self.chars)
+		    self.chars = ""
+		elif name in self.float_subelements:
+		    self.element[name] = float(self.chars)
+		    self.chars = ""
+
+	    def found_chars(self, data):
+		self.chars += data.rstrip()
+
+
+	tp = topo_parse();
+	parser = xml.parsers.expat.ParserCreate()
+	parser.EndElementHandler = tp.end_element
+	parser.CharacterDataHandler = tp.found_chars
+
+	m = re.search('^#\s+Begin\s+Vtopo\s*$(.*)^#\s+End\s+Vtopo', splitout, 
+		re.MULTILINE | re.DOTALL)
+	if m:
+	    str = m.group(1)
+	else:
+	    sys.exit("Badly formatted split")
+
+	parser.Parse(str)
+
+	return tp.topo
+
+    def __call__(self):
+	"""
+	The control flow.  Compose the request and print the response.
+	"""
+	access_keys = []
+	# Process the options using the customized option parser defined above
+	parser = fedd_ns_image_opts(access_keys, self.add_ssh_key,
+		self.add_x509_cert)
+
+	(opts, args) = parser.parse_args()
+
+	if opts.trusted:
+	    if ( not os.access(opts.trusted, os.R_OK) ) :
+		sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
+
+	if opts.debug > 0: opts.tracefile=sys.stderr
+
+	(user, cert) = self.get_user_info([])
+
+	if opts.cert != None: cert = opts.cert
+
+	if cert == None:
+	    sys.exit("No certificate given (--cert) or found")
+
+	if os.access(cert, os.R_OK):
+	    fid = fedid(file=cert)
+	else:
+	    sys.exit("Cannot read certificate (%s)" % cert)
+
+	if opts.file:
+	    exp_desc = ""
+	    try:
+		f = open(opts.file, 'r')
+		for line in f:
+		    exp_desc += line
+		f.close()
+	    except IOError:
+		sys.exit("Cannot read description file (%s)" %opts.file)
+	else:
+	    sys.exit("Must specify an experiment description (--file)")
+
+	if not opts.master:
+	    opts.master="dummy"
+
+
+	req = {
+		'description': { 'ns2description': exp_desc },
+		'master': opts.master,
+		'include_fedkit': opts.fedkit,
+		'include_gatewaykit': opts.gatewaykit,
+		}
+
+
+	if opts.format and opts.outfile:
+	    fmt = opts.format
+	    file = opts.outfile
+	elif not opts.format and opts.outfile:
+	    fmt = opts.outfile[-3:]
+	    if fmt not in ("png", "jpg", "dot", "svg"):
+		sys.exit("Unexpected file type and no format specified")
+	    file = opts.outfile
+	elif opts.format and not opts.outfile:
+	    fmt = opts.format
+	    file = None
+	else:
+	    fmt="dot"
+	    file = None
+
+
+	try:
+	    resp_dict = self.do_rpc(req,
+		    opts.url, opts.transport, cert, opts.trusted, 
+		    serialize_only=opts.serialize_only,
+		    tracefile=opts.tracefile)
+	except self.RPCException, e:
+	    exit_with_fault(\
+		    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
+	except RuntimeError, e:
+	    print e
+	    sys.exit("Error processing RPC: %s" % e)
+
+
+	if resp_dict.has_key('output'):
+	    if len(resp_dict['output']) < 1:
+		sys.exit("Bad response: could not split")
+	    topo = self.generate_topo_dict(resp_dict['output'])
+	    self.gen_image(topo, file, fmt, opts.neato)
 	else:
 	    sys.exit("Bad response. %s" % e.message)
@@ -738,6 +925,7 @@
 	if opts.debug > 0: opts.tracefile=sys.stderr
 
+	(user, cert) = self.get_user_info(access_keys)
+
 	if opts.cert != None: cert = opts.cert
-	else: cert = None
 
 	if cert == None:
@@ -772,4 +960,5 @@
 		'master': opts.master,
 		'include_fedkit': opts.fedkit,
+		'include_gatewaykit': opts.gatewaykit,
 		}
 
@@ -911,5 +1100,6 @@
 	'vtopo': exp_data('Vtopo'),\
 	'vis': exp_data('Vis'),\
-	'image': image(),\
+	'image': image('Vtopo'),\
+	'ns_image': ns_image('Ns2Split'),\
 	'info': exp_data('Info'),\
 	'terminate': terminate(),\
