source: contributed/trunk/graphviz/dcachegraph.py @ 7307

Revision 24, 11.1 KB checked in by gcowan, 12 years ago (diff)

Initial import.

  • Property svn:keywords set to Id
Line 
1#! /usr/bin/env python
2# $Id$
3
4'''graphviz representation of dCache PoolManager.conf'''
5
6__author__ = 'Greig A Cowan'
7__date__   = '25 February 2008'
8__version__ = '0.1'
9
10import re
11from optparse import OptionParser
12from pydot import Dot, Edge, Node, Cluster
13
14def main():
15    '''Parse command line options, call methods'''
16    parser = OptionParser(
17        usage = 'usage: %prog [options] <PoolManager file> <graph filename>')
18    parser.add_option('-d', '--debug', dest='debug', action='store_true',
19                     help='Use debug flag only for testing.')
20    parser.add_option('-c', dest='graphConf', default='graphPool.conf',
21                      help='Configuration file for graphing.')
22    parser.add_option('-f', '--format', dest='format', default='dot',
23                      choices=(Dot.formats + ['raw']),
24                      help='output format supported by GraphViz (default: dot)')
25    parser.add_option('-p', '--prog', dest='prog', default='dot',
26                      choices=('dot', 'twopi', 'neato', 'circo', 'fdp'),
27                      help='GraphViz program to create output with (default: dot)')
28
29    # Parse commane-line input
30    (options, args) = parser.parse_args()
31    try:
32        input_filename, output_filename = args
33    except ValueError:
34        parser.print_help()
35        parser.exit()
36
37    if len(args) > 3:
38        parser.error('incorrect number of arguments')
39    if options.debug:
40        print 'reading %s...' % input_filename
41
42    (poolList, unitList, linkMap, pgroupMap,
43     ugroupMap, linkGroupMap) = parsePoolManager( input_filename)
44
45    if options.debug:
46       print poolList
47       print unitList
48       print linkMap
49       print pgroupMap
50       print ugroupMap
51       print linkGroupMap
52
53    dot = generate_dot( poolList, pgroupMap, unitList,
54                        ugroupMap, linkMap, linkGroupMap)
55    write_file(dot, output_filename, options.prog, options.format)
56
57def parsePoolManager( poolManager):
58    pool = re.compile('psu create pool (?P<pool>[\w\d\_\-]+)')
59    pgroup = re.compile('psu create pgroup (?P<pgroup>[\w\d\_\-]+)')
60    pgroupAdd = re.compile('psu addto pgroup (?P<pgroup>[\w\d\_\-]+) (?P<pool>[\w\d\_\-]+)')
61
62    unit = re.compile('psu create unit -[\w]+\s+(?P<unit>[\w\d\_\-\@\:\/\.]+)+')
63    ugroup = re.compile('psu create ugroup (?P<ugroup>[\w\d\_\-]+)')
64    ugroupAdd = re.compile('psu addto ugroup (?P<ugroup>[\w\d\_\-]+) (?P<unit>[\w\d\_\-\@\:\/\.]+)')
65
66    link = re.compile('psu create link (?P<link>[\w\d\_\-]+)\s+(?P<units>[\w\d\_\-\s]*)')
67    linkAdd = re.compile('psu add link (?P<link>[\w\d\_\-]+) (?P<pgroup>[\w\d\_\-]+)')
68    linkGroup = re.compile('psu create linkGroup (?P<linkGroup>[\w\d\_\-]+)')
69    linkGroupAdd = re.compile('psu addto linkGroup (?P<linkGroup>[\w\d\_\-]+) (?P<link>[\w\d\_\-]+)')
70
71    poolList = []
72    pgroupMap = {}
73
74    unitList = []
75    ugroupMap = {}
76
77    linkMap = {}
78    linkGroupList = []
79    linkGroupMap = {}
80   
81    f = open( poolManager, 'r')
82    lines = f.readlines()
83    lines.sort()
84
85    for line in lines:
86        p = pool.match( line)
87        if p != None:
88            poolList.append( p.group('pool'))
89        pg = pgroup.match( line)
90        if pg != None:
91            if pgroupMap.has_key( pg.group('pgroup')):
92                continue
93            else:
94                pgroupMap[ pg.group('pgroup')] = []
95
96        u = unit.match( line)
97        if u != None:
98            unitList.append( u.group('unit'))
99        ug = ugroup.match( line)
100        if ug != None:
101            if ugroupMap.has_key( ug.group('ugroup')):
102                continue
103            else:
104                ugroupMap[ ug.group('ugroup')] = []
105
106
107        lAdd = linkAdd.match( line)
108        if lAdd != None:
109            if linkMap.has_key( lAdd.group('link')):
110                linkMap[ lAdd.group('link') ][1].append( lAdd.group('pgroup'))
111            else:
112                linkMap[ lAdd.group('link') ] = [[],[ lAdd.group('pgroup')]]
113
114        l = link.match( line)
115        if l != None:
116            if linkMap.has_key( l.group('link')):
117                linkMap[ l.group('link') ][0] = l.group('units').split()
118            else:
119                linkMap[ l.group('link') ] = [[],[]]
120                           
121        lg = linkGroup.match( line)
122        if lg != None:
123            if linkGroupMap.has_key( lg.group('linkGroup')):
124                continue
125            else:
126                linkGroupMap[ lg.group('linkGroup')] = []
127
128        pgAdd = pgroupAdd.match( line)
129        if pgAdd != None:
130            if pgroupMap.has_key( pgAdd.group('pgroup')):
131                pgroupMap[ pgAdd.group('pgroup') ].append( pgAdd.group('pool'))
132            else:
133                pgroupMap[ pgAdd.group('pgroup') ] = [ pgAdd.group('pool')]
134
135        ugAdd = ugroupAdd.match( line)
136        if ugAdd != None:
137            if ugroupMap.has_key( ugAdd.group('ugroup')):
138                ugroupMap[ ugAdd.group('ugroup') ].append( ugAdd.group('unit'))
139            else:
140                ugroupMap[ ugAdd.group('ugroup') ] = [ ugAdd.group('unit')]
141
142        lgAdd = linkGroupAdd.match( line)
143        if lgAdd != None:
144            if linkGroupMap.has_key( lgAdd.group('linkGroup')):
145                linkGroupMap[ lgAdd.group('linkGroup') ].append( lgAdd.group('link'))
146            else:
147                linkGroupMap[ lgAdd.group('linkGroup') ] = [ lgAdd.group('link')]
148           
149
150    f.close()
151    return poolList, unitList, linkMap, pgroupMap, ugroupMap, linkGroupMap
152
153def generate_dot( poolList, poolgroupMap,
154                  unitList, unitgroupMap,
155                  linkMap, linkGroupMap,
156                  directed=True):
157    """Create dot graph representations."""
158
159    dot = Dot('PoolManager',size='90,80', rankdir='LR',
160              ranksep='3', ratio='auto', suppress_disconnected=True)
161
162    if directed:
163        dot.set_type('digraph')
164    else:
165        dot.set_type('graph')
166
167    cols = ['darkolivegreen3','darkolivegreen1',
168            'darkseagreen2','darkseagreen4',
169            'pink','pink3',
170            'red4','red',
171            'gold3','gold',
172            'orange3','orange',
173            'white']
174
175    # Create nodes.
176    # Pools
177    poolCluster = Cluster(graph_name='0', label='Pools', color=cols[12])   
178    for pool in poolList:
179        poolCluster.add_node(Node(pool+'_p', label=pool, style='filled',
180                          color=cols[8], fillcolor=cols[9]))
181
182    # Pool Groups
183    poolGroupCluster = Cluster(graph_name='1', label='Pool Groups',
184                               color=cols[12], suppress_disconnected=False)   
185    maxNumPools = 1   
186    for poolgroup, pools in poolgroupMap.iteritems():
187        poolGroupCluster.add_node(Node(poolgroup+'_pg', label=poolgroup,
188                                       style='filled',
189                                       color=cols[10], fillcolor=cols[11]))
190        if len(pools) > maxNumPools : maxNumPools = len(pools)
191
192    # Edges for Pool Groups -> Pools
193    # Loop again since we had to calculate the weighting above
194    for poolgroup, pools in poolgroupMap.iteritems():
195        color = str( float( len(pools))/maxNumPools )
196        for pool in pools:
197            dot.add_edge(Edge(poolgroup+'_pg', pool+'_p',
198                              color='%s %s %s' % (color, color, color)))
199
200    # Units
201    unitCluster = Cluster(graph_name='2', label='Unit',
202                          color=cols[12], suppress_disconnected=False)   
203    maxNumUnits = 1
204    unitCluster = Cluster(graph_name='2', label='Units', color=cols[12])   
205    for unit in unitList:
206        unitCluster.add_node(Node(unit+'_u', label=unit, style='filled',
207                          color=cols[0], fillcolor=cols[1]))
208
209    # Unit Groups
210    unitGroupCluster = Cluster(graph_name='3', label='Unit Groups',
211                               color=cols[12], suppress_disconnected=False)   
212    for unitgroup, units in unitgroupMap.iteritems():
213        unitGroupCluster.add_node(Node(unitgroup+'_ug', label=unitgroup,
214                                       style='filled',
215                                       color=cols[3], fillcolor=cols[2]))
216        if len(units) > maxNumUnits : maxNumUnits = len(units)
217       
218    # Edges for Units -> Unit Groups
219    # Loop again since we had to calculate the weighting above
220    for unitgroup, units in unitgroupMap.iteritems():
221        color = str( float( len(units))/maxNumUnits )
222        for unit in units:
223            dot.add_edge(Edge(unit+'_u', unitgroup+'_ug',
224                              color='%s %s %s' % (color, color, color)))
225
226    # Links
227    linkCluster = Cluster(graph_name='4', label='Link',
228                          color=cols[12], suppress_disconnected=False)   
229
230    # Build dictionary that maps ugroups to links
231    unitgroupLinkMap = {}
232    for unitgroup in unitgroupMap:
233        for link, [unitgroups,poolgroups] in linkMap.iteritems():
234            if unitgroup in unitgroups:
235                if unitgroupLinkMap.has_key( unitgroup):
236                    unitgroupLinkMap[ unitgroup].append( link)
237                else:
238                    unitgroupLinkMap[ unitgroup] = []
239
240    # Getting weighting for colour
241    maxNumLinks2PoolGroups = 0
242    for link, [unitgroups, poolgroups] in linkMap.iteritems():
243        linkCluster.add_node(Node(link+'_l', label=link, style='filled',
244                                  color=cols[5], fillcolor=cols[4]))
245        if len(poolgroups)> maxNumLinks2PoolGroups:
246            maxNumLinks2PoolGroups = len(poolgroups)
247
248
249    # Getting weighting for colour
250    maxNumUnitGroups2Links = 0
251    for unitgroup, links in unitgroupLinkMap.iteritems():
252        if len(links) > maxNumUnitGroups2Links :
253            maxNumUnitGroups2Links = len(links)
254
255    # Tie it all together. Unit Groups -> Links -> Pool Groups
256    for link, [unitgroups,poolgroups] in linkMap.iteritems():
257        for unitgroup in unitgroups:
258            color=str( float( len(unitgroupLinkMap[unitgroup]))/maxNumUnitGroups2Links)
259            dot.add_edge(Edge(unitgroup+'_ug', link+'_l',
260                              color='%s %s %s' % (color, color, color)))
261        for poolgroup in poolgroups:
262            color = str( float( len( poolgroups))/maxNumLinks2PoolGroups)
263            dot.add_edge(Edge(link+'_l', poolgroup+'_pg',
264                              color='%s %s %s' % (color, color, color)))
265           
266    # Link Groups
267    linkGroupCluster = Cluster(graph_name='5', label='Link Groups',
268                               color=cols[12])   
269    for linkgroup in linkGroupMap.keys():
270        linkGroupCluster.add_node(Node(linkgroup+'_lg', label=linkgroup,
271                                       color=cols[7], fillcolor=cols[6]))
272
273    # Edges for Link Groups -> Links
274    for linkgroup, links in linkGroupMap.iteritems():
275        for link in links:
276            dot.add_edge(Edge(linkgroup+'_lg', link+'_l', color='grey'))
277
278
279    dot.add_subgraph( poolCluster)
280    dot.add_subgraph( poolGroupCluster)
281
282    dot.add_subgraph( unitCluster)
283    dot.add_subgraph( unitGroupCluster)
284
285    dot.add_subgraph( linkCluster)
286    dot.add_subgraph( linkGroupCluster)
287
288    return dot
289
290
291def write_file(dot, name, prog, format):
292    '''Create a graphics file from the DOT file.'''
293    filename = '%s.%s.%s' % (name, prog, format)
294    dot.write(filename, prog, format)
295    print "Wrote %s output to '%s' using %s." % (format, filename, prog)
296
297
298if __name__=='__main__':
299    main()
Note: See TracBrowser for help on using the repository browser.