Changeset cc58813 for fedd


Ignore:
Timestamp:
Jun 18, 2009 9:57:59 AM (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:
c7910ac
Parents:
63f3746
Message:

Allow image generation when not swapped in, using a fedd to do the split. Also added dynamic image sizing and ip addresses to links.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_client.py

    r63f3746 rcc58813  
    66import tempfile
    77import subprocess
     8import re
     9import xml.parsers.expat
    810
    911from federation import fedid, service_error
     
    118120                default=False,
    119121                help="get output suitable for federation kit install")
     122        self.add_option('-G','--gatewaykit', action='store_true',
     123                dest='gatewaykit', default=False,
     124                help="get output suitable for federation gateway kit install")
    120125
    121126
     
    152157                help="output image file")
    153158        self.add_option("-F", "--format", dest="format", type="choice",
    154                 choices=("jpg", "png", "dot"),
     159                choices=("jpg", "png", "dot", "svg"),
     160                help="Output file format override")
     161        self.add_option("-P", "--program", dest="neato", default=None,
     162                type="string",
     163                help="Program compatible with dot (from graphviz) used to " + \
     164                        "render image")
     165
     166class fedd_ns_image_opts(fedd_split_opts):
     167    def __init__(self, access_keys, add_key_callback=None,
     168            add_cert_callback=None):
     169        fedd_split_opts.__init__(self, access_keys, add_key_callback,
     170                add_cert_callback)
     171        self.add_option("-o", "--output", dest="outfile", type="string",
     172                help="output image file")
     173        self.add_option("-Q", "--format", dest="format", type="choice",
     174                choices=("jpg", "png", "dot", "svg"),
    155175                help="Output file format override")
    156176        self.add_option("-P", "--program", dest="neato", default=None,
     
    394414
    395415
    396 # Querying experiment data follows the same control flow regardless of the
    397 # specific data retrieved.  This class encapsulates that control flow.
    398416class image(fedd_rpc):
    399     def __init__(self):
     417    def __init__(self, op):
    400418        """
    401419        Null constructor
    402420        """
    403421
    404         fedd_rpc.__init__(self, "Vtopo")
     422        fedd_rpc.__init__(self, op)
    405423
    406424    def gen_image(self, d, file, fmt, neato):
     
    430448        cmd.append(dotname)
    431449
     450        nodes = d.get('node',[])
     451
     452        if len(nodes) < 10: size = 5
     453        elif len(nodes) < 50: size = 10
     454        else: size = 18
     455
    432456        print >>dotfile, "graph G {"
     457        print >>dotfile, '\tgraph [size="%i,%i", ratio=fill];' % (size, size)
    433458        print >>dotfile, '\tnode [fontname=arial,fontsize=9,label="\N"];'
    434         print >>dotfile, '\tedge [fontname=arial,fontsize=9,label="\N"];\n'
     459        print >>dotfile, '\tedge [fontname=arial,fontsize=9];\n'
    435460
    436461        for n in d.get('node', []):
     
    446471            v = n['vname']
    447472            m = n['member']
     473            i = n['ip']
    448474            if m.find(':') != -1:
    449475                m = m[0:m.find(':')]
    450476            if lans.has_key(v):
    451                 lans[v].append(m)
     477                lans[v].append((m, i))
    452478            elif links.has_key(v):
    453                 links[v].append(m)
     479                links[v].append((m, i))
    454480                if len(links[v]) > 2:
    455481                    lans[v] = links[v]
    456482                    del links[v]
    457483            else:
    458                 links[v] = [m]
     484                links[v] = [(m, i)]
    459485
    460486        # Encode the lans and the links
     
    463489            print >>dotfile,'\t\tcolor=black,fillcolor="#80c0f8",regular=1]'
    464490            for n in lans[l]:
    465                 print >>dotfile, '\t%s -- %s' % (l, n)
     491                print >>dotfile, '\t%s -- %s [headlabel="%s"]' % (l, n[0], n[1])
    466492
    467493        for k, l in links.items():
    468494            if len(l) == 2:
    469                 print >>dotfile, '\t%s -- %s [label="%s"]' % (l[0], l[1], k)
     495                print >>dotfile, \
     496                        ('\t%s -- %s [label="%s",taillabel="%s",' + \
     497                        'headlabel="%s"]') % \
     498                        (l[0][0], l[1][0], k, l[0][1], l[1][1])
    470499
    471500        print >>dotfile, "}"
     
    524553        elif not opts.format and opts.outfile:
    525554            fmt = opts.outfile[-3:]
    526             if fmt not in ("png", "jpg", "dot"):
     555            if fmt not in ("png", "jpg", "dot", "svg"):
    527556                sys.exit("Unexpected file type and no format specified")
    528557            file = opts.outfile
     
    552581        if resp_dict.has_key('vtopo'):
    553582            self.gen_image(resp_dict['vtopo'], file, fmt, opts.neato)
     583        else:
     584            sys.exit("Bad response. %s" % e.message)
     585
     586class ns_image(image):
     587    def __init__(self, op):
     588        """
     589        Null constructor
     590        """
     591
     592        image.__init__(self, op)
     593
     594    def generate_topo_dict(self, splitout):
     595        class topo_parse:
     596            """
     597            Parse the topology XML and create the dats structure.  This class
     598            is copied from federation.experiment_control.
     599            """
     600            def __init__(self):
     601                # Typing of the subelements for data conversion
     602                self.str_subelements = ('vname', 'vnode', 'ips', 'ip', 'member')
     603                self.int_subelements = ( 'bandwidth',)
     604                self.float_subelements = ( 'delay',)
     605                # The final data structure
     606                self.nodes = [ ]
     607                self.lans =  [ ]
     608                self.topo = { \
     609                        'node': self.nodes,\
     610                        'lan' : self.lans,\
     611                    }
     612                self.element = { }  # Current element being created
     613                self.chars = ""     # Last text seen
     614
     615            def end_element(self, name):
     616                # After each sub element the contents is added to the current
     617                # element or to the appropriate list.
     618                if name == 'node':
     619                    self.nodes.append(self.element)
     620                    self.element = { }
     621                elif name == 'lan':
     622                    self.lans.append(self.element)
     623                    self.element = { }
     624                elif name in self.str_subelements:
     625                    self.element[name] = self.chars
     626                    self.chars = ""
     627                elif name in self.int_subelements:
     628                    self.element[name] = int(self.chars)
     629                    self.chars = ""
     630                elif name in self.float_subelements:
     631                    self.element[name] = float(self.chars)
     632                    self.chars = ""
     633
     634            def found_chars(self, data):
     635                self.chars += data.rstrip()
     636
     637
     638        tp = topo_parse();
     639        parser = xml.parsers.expat.ParserCreate()
     640        parser.EndElementHandler = tp.end_element
     641        parser.CharacterDataHandler = tp.found_chars
     642
     643        m = re.search('^#\s+Begin\s+Vtopo\s*$(.*)^#\s+End\s+Vtopo', splitout,
     644                re.MULTILINE | re.DOTALL)
     645        if m:
     646            str = m.group(1)
     647        else:
     648            sys.exit("Badly formatted split")
     649
     650        parser.Parse(str)
     651
     652        return tp.topo
     653
     654    def __call__(self):
     655        """
     656        The control flow.  Compose the request and print the response.
     657        """
     658        access_keys = []
     659        # Process the options using the customized option parser defined above
     660        parser = fedd_ns_image_opts(access_keys, self.add_ssh_key,
     661                self.add_x509_cert)
     662
     663        (opts, args) = parser.parse_args()
     664
     665        if opts.trusted:
     666            if ( not os.access(opts.trusted, os.R_OK) ) :
     667                sys.exit("Cannot read trusted certificates (%s)" % opts.trusted)
     668
     669        if opts.debug > 0: opts.tracefile=sys.stderr
     670
     671        (user, cert) = self.get_user_info([])
     672
     673        if opts.cert != None: cert = opts.cert
     674
     675        if cert == None:
     676            sys.exit("No certificate given (--cert) or found")
     677
     678        if os.access(cert, os.R_OK):
     679            fid = fedid(file=cert)
     680        else:
     681            sys.exit("Cannot read certificate (%s)" % cert)
     682
     683        if opts.file:
     684            exp_desc = ""
     685            try:
     686                f = open(opts.file, 'r')
     687                for line in f:
     688                    exp_desc += line
     689                f.close()
     690            except IOError:
     691                sys.exit("Cannot read description file (%s)" %opts.file)
     692        else:
     693            sys.exit("Must specify an experiment description (--file)")
     694
     695        if not opts.master:
     696            opts.master="dummy"
     697
     698
     699        req = {
     700                'description': { 'ns2description': exp_desc },
     701                'master': opts.master,
     702                'include_fedkit': opts.fedkit,
     703                'include_gatewaykit': opts.gatewaykit,
     704                }
     705
     706
     707        if opts.format and opts.outfile:
     708            fmt = opts.format
     709            file = opts.outfile
     710        elif not opts.format and opts.outfile:
     711            fmt = opts.outfile[-3:]
     712            if fmt not in ("png", "jpg", "dot", "svg"):
     713                sys.exit("Unexpected file type and no format specified")
     714            file = opts.outfile
     715        elif opts.format and not opts.outfile:
     716            fmt = opts.format
     717            file = None
     718        else:
     719            fmt="dot"
     720            file = None
     721
     722
     723        try:
     724            resp_dict = self.do_rpc(req,
     725                    opts.url, opts.transport, cert, opts.trusted,
     726                    serialize_only=opts.serialize_only,
     727                    tracefile=opts.tracefile)
     728        except self.RPCException, e:
     729            exit_with_fault(\
     730                    {'desc': e.desc, 'errstr': e.errstr, 'code': e.code})
     731        except RuntimeError, e:
     732            print e
     733            sys.exit("Error processing RPC: %s" % e)
     734
     735
     736        if resp_dict.has_key('output'):
     737            if len(resp_dict['output']) < 1:
     738                sys.exit("Bad response: could not split")
     739            topo = self.generate_topo_dict(resp_dict['output'])
     740            self.gen_image(topo, file, fmt, opts.neato)
    554741        else:
    555742            sys.exit("Bad response. %s" % e.message)
     
    738925        if opts.debug > 0: opts.tracefile=sys.stderr
    739926
     927        (user, cert) = self.get_user_info(access_keys)
     928
    740929        if opts.cert != None: cert = opts.cert
    741         else: cert = None
    742930
    743931        if cert == None:
     
    772960                'master': opts.master,
    773961                'include_fedkit': opts.fedkit,
     962                'include_gatewaykit': opts.gatewaykit,
    774963                }
    775964
     
    9111100        'vtopo': exp_data('Vtopo'),\
    9121101        'vis': exp_data('Vis'),\
    913         'image': image(),\
     1102        'image': image('Vtopo'),\
     1103        'ns_image': ns_image('Ns2Split'),\
    9141104        'info': exp_data('Info'),\
    9151105        'terminate': terminate(),\
Note: See TracChangeset for help on using the changeset viewer.