Changeset 63f3746


Ignore:
Timestamp:
Jun 17, 2009 6:29:41 PM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
Children:
cc58813
Parents:
af542ea
Message:

Add image rendering functionality to fedd_client

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_client.py

    raf542ea r63f3746  
    44import os
    55import pwd
     6import tempfile
     7import subprocess
    68
    79from federation import fedid, service_error
     
    144146                type="string", help="output certificate file")
    145147
     148class fedd_image_opts(fedd_exp_data_opts):
     149    def __init__(self):
     150        fedd_exp_data_opts.__init__(self)
     151        self.add_option("-o", "--output", dest="outfile", type="string",
     152                help="output image file")
     153        self.add_option("-F", "--format", dest="format", type="choice",
     154                choices=("jpg", "png", "dot"),
     155                help="Output file format override")
     156        self.add_option("-P", "--program", dest="neato", default=None,
     157                type="string",
     158                help="Program compatible with dot (from graphviz) used to " + \
     159                        "render image")
     160
    146161def exit_with_fault(dict, out=sys.stderr):
    147162    """ Print an error message and exit.
     
    378393            print resp_dict
    379394
     395
     396# Querying experiment data follows the same control flow regardless of the
     397# specific data retrieved.  This class encapsulates that control flow.
     398class image(fedd_rpc):
     399    def __init__(self):
     400        """
     401        Null constructor
     402        """
     403
     404        fedd_rpc.__init__(self, "Vtopo")
     405
     406    def gen_image(self, d, file, fmt, neato):
     407
     408        # Open up a temporary file for dot to turn into a visualization
     409        try:
     410            df, dotname = tempfile.mkstemp(prefix='fedd_client', suffix=".dot")
     411            dotfile = os.fdopen(df, 'w')
     412        except IOError:
     413            raise service_error(service_error.internal,
     414                    "Failed to open file in genviz")
     415
     416        if not neato:
     417            for f in ['/usr/bin/neato', '/usr/local/bin/neato',
     418                    '/usr/bin/dot', '/usr/local/bin/dot']:
     419                if os.access(f, os.X_OK):
     420                    neato = f
     421                    break
     422            else:
     423                sys.exit("Cannot find graph rendering program")
     424
     425        cmd = [neato, '-Gsplines=true']
     426        if fmt != 'dot': cmd.append('-T%s' % fmt)
     427        if file:
     428            cmd.append('-o')
     429            cmd.append(file)
     430        cmd.append(dotname)
     431
     432        print >>dotfile, "graph G {"
     433        print >>dotfile, '\tnode [fontname=arial,fontsize=9,label="\N"];'
     434        print >>dotfile, '\tedge [fontname=arial,fontsize=9,label="\N"];\n'
     435
     436        for n in d.get('node', []):
     437            print >>dotfile, '\t%s [shape=box,style=filled,\\' % n['vname']
     438            print >>dotfile, '\t\tcolor=black,fillcolor="#60f8c0",regular=1]'
     439
     440
     441        lans = { }
     442        links = { }
     443
     444        # Collect lan members (we have to draw extra stuff for these)
     445        for n in d.get('lan', []):
     446            v = n['vname']
     447            m = n['member']
     448            if m.find(':') != -1:
     449                m = m[0:m.find(':')]
     450            if lans.has_key(v):
     451                lans[v].append(m)
     452            elif links.has_key(v):
     453                links[v].append(m)
     454                if len(links[v]) > 2:
     455                    lans[v] = links[v]
     456                    del links[v]
     457            else:
     458                links[v] = [m]
     459
     460        # Encode the lans and the links
     461        for l in lans.keys():
     462            print >>dotfile, '\t%s [shape=ellipse, style=filled,\\' % l
     463            print >>dotfile,'\t\tcolor=black,fillcolor="#80c0f8",regular=1]'
     464            for n in lans[l]:
     465                print >>dotfile, '\t%s -- %s' % (l, n)
     466
     467        for k, l in links.items():
     468            if len(l) == 2:
     469                print >>dotfile, '\t%s -- %s [label="%s"]' % (l[0], l[1], k)
     470
     471        print >>dotfile, "}"
     472        dotfile.close()
     473
     474        # Redirect the drawing program stderr
     475        dev_null = open("/dev/null", "w")
     476        rv = subprocess.call(cmd, stderr=dev_null)
     477        os.remove(dotname)
     478        dev_null.close()
     479        if rv != 0:
     480            sys.exit("Error creating graph")
     481
     482
     483
     484    def __call__(self):
     485        """
     486        The control flow.  Compose the request and print the response.
     487        """
     488        # Process the options using the customized option parser defined above
     489        parser = fedd_image_opts()
     490
     491        (opts, args) = parser.parse_args()
     492
     493        if opts.trusted:
     494            if ( not os.access(opts.trusted, os.R_OK) ) :
     495                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
     496
     497        if opts.debug > 0: opts.tracefile=sys.stderr
     498
     499        (user, cert) = self.get_user_info([])
     500
     501        if opts.cert != None: cert = opts.cert
     502
     503        if cert == None:
     504            sys.exit("No certificate given (--cert) or found")
     505
     506        if os.access(cert, os.R_OK):
     507            fid = fedid(file=cert)
     508        else:
     509            sys.exit("Cannot read certificate (%s)" % cert)
     510
     511        if opts.exp_name and opts.exp_certfile:
     512            sys.exit("Only one of --experiment_cert and " +\
     513                    "--experiment_name permitted");
     514
     515        if opts.exp_certfile:
     516            exp_id = { 'fedid': fedid(file=opts.exp_certfile) }
     517
     518        if opts.exp_name:
     519            exp_id = { 'localname' : opts.exp_name }
     520
     521        if opts.format and opts.outfile:
     522            fmt = opts.format
     523            file = opts.outfile
     524        elif not opts.format and opts.outfile:
     525            fmt = opts.outfile[-3:]
     526            if fmt not in ("png", "jpg", "dot"):
     527                sys.exit("Unexpected file type and no format specified")
     528            file = opts.outfile
     529        elif opts.format and not opts.outfile:
     530            fmt = opts.format
     531            file = None
     532        else:
     533            fmt="dot"
     534            file = None
     535
     536
     537        req = { 'experiment': exp_id }
     538
     539        try:
     540            resp_dict = self.do_rpc(req,
     541                    opts.url, opts.transport, cert, opts.trusted,
     542                    serialize_only=opts.serialize_only,
     543                    tracefile=opts.tracefile)
     544        except self.RPCException, e:
     545            exit_with_fault(\
     546                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
     547        except RuntimeError, e:
     548            print e
     549            sys.exit("Error processing RPC: %s" % e)
     550
     551
     552        if resp_dict.has_key('vtopo'):
     553            self.gen_image(resp_dict['vtopo'], file, fmt, opts.neato)
     554        else:
     555            sys.exit("Bad response. %s" % e.message)
     556
    380557class terminate(fedd_rpc):
    381558    def __init__(self):
     
    734911        'vtopo': exp_data('Vtopo'),\
    735912        'vis': exp_data('Vis'),\
     913        'image': image(),\
    736914        'info': exp_data('Info'),\
    737915        'terminate': terminate(),\
Note: See TracChangeset for help on using the changeset viewer.