Release of grains plugin to racktables-contribs
[racktables-contribs] / python-graph-topology / draw_topo_24_estable.py
1 # coding=utf-8
2 ##########################################################
3 # Name: draw_topo_02.py
4 # Version: 0.2
5 # Author: Lucas Aimaretto
6 # mail: laimaretto@gmail.com
7 # Date: 14-jun-2015
8 #
9 # - 0.1: first draft
10 # This version will graph any topology based on the tags of the routers.
11 # - 0.2: Reorder of functions; cleaning of code.
12 # - 0.3: Implementing of IP/PORT/Speed information. Change on function
13 # fnc_build_query_connections SQL's query
14 # - 0.4: Included sync-e reference to each port. If not abailable, then N/A is shown.
15 # For this, a sync_dict is created.
16 # - 0.5: Including system IP, sync order, color for not integrated routers.
17 # - 0.6: If no SFP, no speed can be obtained. Then "No SFP" is shown. If CES, ATM or ASAP, then "No ETH" is shown.
18 # - 0.7: fnc_build_query_objetos(.) modify to further filter out objects with tags (and no ipvnet)
19 # fnc_build_query_interfaces(.) to bring IPs and interfaces
20 # fnc_build_query_connections(.) now only brings connections and no IPs
21 # fnc_cross_conn_inter(.) finds out IP for connections
22 # - 0.8: Asked whether to graph LAGs or not
23 # TBD: consider when link label is something else than "LAG", "Hairpin" or "".
24 # - 1.1: Distinction between High, Mid and Low Ran
25 # - 1.2: Reducing font size of link's labels
26 # - 1.3: Including FO and ARSAT as possible labels for links
27 # - 1.7: Different colors for MR and HR
28 # - 1.8: Includes transmission with a list
29 # - 1.9: Ring topology now available
30 # - 2.0: Change Name of file to match Claro's format.
31 # - 2.1: Bug regarding getting the system IP of router: fnc_build_query_attributes(.)
32 # TxType now considered when MIX TX is needed (ie: DWDM+MW)
33 # - 2.2: Option to graph nodes with the names, only.
34 # - 2.3: implementing argv to pass parameters in line
35 # change \n to \n in port an router when mode 1,2,3
36 # - 2.4: full custimoization via argv[]
37 # Different color depending con Ref_Order
38
39 #!/usr/bin/python
40 import MySQLdb
41 import graphviz as gv
42 import time
43 import sys
44 import functools
45 import datetime
46 from operator import itemgetter
47 from itertools import groupby
48
49 ########################################################################
50 # Globals
51 ########################################################################
52
53 ipran_tx = ["LAG_Y","HAIRPIN_Y","SDH","RADIO","DWDM","CDWM","FO",""]
54 version_script="21"
55
56 ########################################################################
57 # Functions
58 ########################################################################
59
60 # Function to try if string is number
61 def fnc_isNumber(text):
62
63 try:
64 int(text)
65 return 1
66 except:
67 return 0
68
69 # Function to distinguish chains from rings
70 def fnc_chains_ring(vector):
71 topoString=""
72 tempList=[]
73 len_vector= len(vector)
74 i=1
75
76 # We can have many topos inside vector
77 for topo in vector:
78
79 topoString = topo
80 charCount = topoString.count("_")
81 nameList=topoString.split("_")
82
83 #print nameList, charCount
84
85 if fnc_isNumber(nameList[0]==0):
86
87 if charCount == 1:
88 name1 = nameList[0]
89 testNumber1 = nameList[1]
90
91 # SF903_002
92 if fnc_isNumber(testNumber1)==1:
93 tempList.append(("Anillo",name1,name1+"_"+testNumber1))
94 else:
95 print "Wrong ring number: " + testNumber1 + " .Quitting..."
96 sys.exit(-1)
97
98 elif charCount == 2:
99 name1 = nameList[0]
100 name2 = nameList[0] + "_" + nameList[1]
101 testNumber1 = nameList[1]
102 testNumber2 = nameList[2]
103
104 # SF903_002_ARSAT
105 if fnc_isNumber(testNumber1):
106 tempList.append(("Anillo_TX",name1,name1+"_"+testNumber1))
107 # CF164_CFR17_001 or c1744_c3983_radial
108 elif fnc_isNumber(testNumber2) or testNumber2=="RADIAL":
109 tempList.append(("Cadena",name2,name2+"_"+testNumber2))
110 else:
111 print "Wrong chain name. Verify either: " + testNumber1 + " or " + testNumber2 + " .Quitting..."
112 sys.exit(-1)
113
114 elif charCount == 3:
115 name1 = nameList[0] + "_" + nameList[1]
116 testNumber1 = nameList[2]
117
118 # CF164_CFR17_001_MW
119 if fnc_isNumber(testNumber1)==1:
120 tempList.append(("Cadena_TX",name1,name1+"_"+testNumber1))
121 else:
122 print "Wrong chain_tx number: " + testNumber1 + " .Quitting..."
123 sys.exit(-1)
124
125 elif charCount == 0:
126 name1 = vector[0]
127 tempList.append(("Other",name1,name1))
128
129 else:
130 print "Wrong topo name. Quitting..."
131 sys.exit(-1)
132
133 return tempList
134
135 # Function that builds the filename
136 def fnc_build_filename(vector):
137 info = fnc_chains_ring(vector)
138 len_vector= len(vector)
139
140 if len_vector==1:
141
142 tipoTopo = info[0][0]
143 agregador = info[0][1]
144 topologia = info[0][2]
145
146 topoName1 = "Topology "
147 topoName2 = tipoTopo
148 topoName3 = " - MR LR - "
149 topoName4 = topologia
150 filename = "pix/topo/" + agregador + "/" + topoName1 + topoName2 + topoName3 + topoName4
151
152 elif len_vector >1:
153
154 tipoTopo = "-".join(list(set([name[0] for name in info])))
155 agregador = "-".join(list(set([name[1] for name in info])))
156 topologia = "-".join(list(set([name[2] for name in info])))
157
158 topoName1 = "Topology "
159 topoName2 = tipoTopo
160 topoName3 = " - MR LR - "
161 topoName4 = topologia
162 filename = "pix/topo/" + agregador + "/" + topoName1 + topoName2 + topoName3 + topoName4
163
164 now = datetime.datetime.now()
165 #filename=filename + "_" + version_script + "_" +now.strftime("%Y-%m-%d")+".dot"
166 return filename
167
168 # Function that builds the SQL query to obtain the object Id based
169 # on topo_name
170 def fnc_build_query_objetos(vector):
171 query1=""
172 query2=""
173 len_vector = len(vector)
174 i=1
175
176 query1=(
177 "select "
178 "OBJ.name, "
179 "TS.entity_id "
180 "from "
181 "TagStorage as TS join Object as OBJ on (TS.entity_id=OBJ.id) "
182 "where entity_realm ='object' and "
183 )
184
185 for row in vector:
186 obj_id=str(row[0])
187 if i < len_vector:
188 query2 = query2 + "tag_id = " + obj_id + " or "
189 else:
190 query2 = query2 + "tag_id = " + obj_id
191 i=i+1
192
193 query = query1 + query2
194
195 return query
196
197 # Function that builds the SQL query to obatin the topo_ID
198 def fnc_build_query_topo_id(vector):
199 query1=""
200 query2=""
201 len_vector = len(vector)
202 i=1
203
204 query1=(
205 "select id from TagTree where "
206 )
207
208 for row in vector:
209 obj_id="'" + row + "'"
210 if i < len_vector:
211 query2 = query2 + "tag = " + obj_id + " or "
212 else:
213 query2 = query2 + "tag = " + obj_id
214 i=i+1
215
216 query = query1 + query2
217
218 return query
219
220 # Function that removes ports from a router if such port connects
221 # to a router that does not have a requested tag.
222 def fnc_remove_routers_wotag(object_vector, connex_vector):
223
224 temp_list=[]
225 for o in object_vector:
226 temp_list.append(o[0])
227
228 final_list=[item for item in connex_vector if item[0] in temp_list and item[5] in temp_list]
229
230 return final_list
231
232
233 # Function that obtains the attributes values per object ID
234 # It also brings the system IP of the router.
235 def fnc_build_query_attributes(vector):
236 query1=""
237 query2=""
238 query3=""
239 query4=""
240 len_vector = len(vector)
241
242 query1=(
243 "select "
244 "ob.name, "
245 "concat(ob.name,\"_\",av.string_value) as node, "
246 "a.name, "
247 "av.string_value, "
248 "d.dict_value "
249 "from Object as ob "
250 "join AttributeValue as av on (ob.id=av.object_id) "
251 "join Attribute as a on (av.attr_id=a.id) "
252 "left join Dictionary as d on (d.dict_key=av.uint_value) "
253 "where (a.name = 'Integrado' or a.name = 'HW type' or a.name = 'HW function' or a.name = 'TxType_CKT_ID' or a.name like '%Ref%') "
254 "and ("
255 )
256 i=1
257 for row in vector:
258 obj_id=str(row[1])
259 if i < len_vector:
260 query2 = query2 + "ob.id = " + obj_id + " or "
261 else:
262 query2 = query2 + "ob.id = " + obj_id
263 i=i+1
264
265 query = query1 + query2 + ")"
266
267 query3=(
268 "SELECT "
269 "ob.name AS obj1, "
270 "'TBD1', "
271 "concat(ob.name,'_',ip4.name) AS int_name1, "
272 "INET_NTOA(ip4.ip) as ip, "
273 "'TBD2' "
274 "FROM Object AS ob "
275 "JOIN IPv4Allocation AS ip4 ON (ip4.object_id=ob.id) "
276 "where ip4.name = 'system' "
277 "and ("
278 )
279 i=1
280 for row in vector:
281 obj_id=str(row[1])
282 if i < len_vector:
283 query4 = query4 + "ob.id = " + obj_id + " or "
284 else:
285 query4 = query4 + "ob.id = " + obj_id
286 i=i+1
287
288 query = query + " UNION " + query3 + query4 + ")"
289
290 return query
291
292 # Function that builds a SQL query to obtain the IP interfaces
293 def fnc_build_query_interfaces(vector):
294 query1=""
295 query2=""
296 len_vector = len(vector)
297 i=1
298
299 query1=(
300 "SELECT "
301 "ro1.name AS obj1, "
302 "ro1.id AS obj1_id, "
303 "concat(ro1.name,'_',ip4.name) AS int_name1, "
304 "INET_NTOA(ip4.ip) as ip "
305 "FROM "
306 "Object AS ro1 "
307 "JOIN IPv4Allocation AS ip4 ON (ip4.object_id=ro1.id) "
308 "WHERE ("
309 )
310 for row in vector:
311 obj_id=str(row[1])
312 if i < len_vector:
313 query2 = query2 + "ro1.id = " + obj_id + " or "
314 else:
315 query2 = query2 + "ro1.id = " + obj_id
316 i=i+1
317
318 query = query1 + query2 + ")"
319
320 return query
321
322
323 # Function that builds a SQL query to obtain the connections
324 # among routers.
325 def fnc_build_query_connections(vector):
326 query1=""
327 query2=""
328 len_vector = len(vector)
329 i=1
330
331 query1=(
332 "SELECT "
333 "ro1.name AS obj1, "
334 "ro1.id as obj1_id, "
335 "concat(ro1.name,'_',p1.label) AS int_name1, "
336 "p1.name AS port1, "
337 "Link.cable, "
338 "p2.name AS port2, "
339 "concat(ro2.name,'_',p2.label) AS int_name2, "
340 "ro2.name AS obj2, "
341 "ro2.id as obj2_id, "
342 "d.dict_value AS obj1type, "
343 "poia.oif_name, "
344 "poib.oif_name "
345 "FROM Object AS ro1 "
346 "JOIN Port AS p1 ON(ro1.id=p1.object_id) "
347 "JOIN Link ON(p1.id=Link.porta) "
348 "JOIN Port AS p2 ON(Link.portb=p2.id) "
349 "JOIN Object AS ro2 ON(p2.object_id=ro2.id) "
350 "JOIN PortOuterInterface AS poia ON(poia.id=p1.type) "
351 "JOIN PortOuterInterface AS poib ON(poib.id=p2.type) "
352 "LEFT JOIN Dictionary AS d ON(ro1.objtype_id=d.dict_key) "
353 "WHERE ("
354 )
355 for row in vector:
356 obj_id=str(row[1])
357 if i < len_vector:
358 query2 = query2 + "ro1.id = " + obj_id + " or ro2.id = " + obj_id + " or "
359 else:
360 query2 = query2 + "ro1.id = " + obj_id + " or ro2.id = " + obj_id
361 i=i+1
362
363 query = query1 + query2 + ")"
364
365 return query
366
367
368 # Funcion que organiza los puertos de cada nodo
369 def fnc_port_list(routers):
370 router_list=[]
371 port_list=[]
372 for router in routers:
373 #print router[0]
374 router_id = router[0][0]
375 for port in router:
376 port_list.append(port[1])
377 router_list.append((router_id,port_list))
378 port_list=[]
379
380 return router_list
381
382 # Function that returns de speed of the port
383 def fnc_port_speed(port_string):
384
385 speed=port_string.split('B')
386 speed=speed[0]
387
388 if speed == "100":
389 return "-100Mb"
390 elif speed == "1000":
391 return "-1Gb"
392 elif speed == "10G":
393 return "-10Gb"
394 elif speed == "empty SFP-1000":
395 return "-n/SFP"
396 elif speed == "virtual port":
397 return ""
398 elif speed == "SFP-CES" or speed == "SFP-ATM" or speed == "SFP-ASAP":
399 return "-n/ETH"
400 else:
401 return "-N/A"
402
403 # Function that returns the SFP type
404 def fnc_port_sfp(port_string):
405
406 if port_string == "virtual port":
407 return "LAG"
408 elif port_string == "SFP-CES" or port_string == "SFP-ATM" or port_string == "SFP-ASAP":
409 return port_string.split('-')[1]
410 else:
411 sfp_type = port_string.split('-')
412 sfp_type = sfp_type[1]
413 return sfp_type
414
415 # Function that creates a dictionary for sync references
416 # The asignment is done on a port basis
417 def fnc_add_atributes_to_dic_ref(attributes):
418
419 dict_ref={}
420
421 for attrib in attributes:
422 node_id=attrib[1]
423 node_ref=attrib[2]
424 if node_ref:
425 dict_ref[node_id]=node_ref
426 else:
427 dict_ref[node_id]="N/A"
428
429 return dict_ref
430
431 # Function that creates a dictionary with global attributes
432 def fnc_add_atributes_to_dic_global(attributes):
433
434 dict_global={}
435
436 for attrib in attributes:
437
438 if "ARSAT" in attrib[0]:
439 pass
440 #print attrib
441
442 router_name = attrib[0]
443 attrib_name = attrib[2]
444 system_ip = attrib[3]
445 attrib_value = attrib[4]
446 ckt_id = attrib[3]
447
448 if "HW function" in attrib_name:
449 hw_function=attrib_value
450 dict_key=router_name + "_function"
451 dict_global[dict_key]=hw_function
452 if "Integrado" in attrib_name:
453 dict_key=router_name + "_Integrado"
454 dict_global[dict_key]=attrib_value
455 if "Ref_Order" in attrib_name:
456 dict_key=router_name + "_Ref_Order"
457 dict_global[dict_key]=attrib_value
458 if "TxType_CKT_ID" in attrib_name:
459 dict_key=router_name + "_ckt_id"
460 dict_global[dict_key]=ckt_id
461 if "system" in attrib_name:
462 dict_key=router_name + "_system"
463 dict_global[dict_key]=system_ip
464
465 return dict_global
466
467
468 # Function that creates a list which holds each router and all its ports.
469 # Input: object_connections
470 # [('Router1', '1/1/1'), ('Router1', '1/1/2')]
471 # Output
472 # ('Router1/1/1', {'label': '1/1/1'})
473 # The output of this function is used as input to graphviz
474 def fnc_node_list(routers,sync_dict, router_mode, graph_hp, graph_lag, graph_cpam):
475
476 temp_list=[]
477
478 for row in routers:
479
480
481 cableID=row[3]
482 if not cableID: cableID=""
483
484 if ("LAG" in cableID.upper() and graph_lag=="n") or ("HAIRPIN" in cableID.upper() and graph_hp=="n") or ("CPAM" in cableID.upper() and graph_cpam=="n"):
485 a=1
486 else:
487
488 routerA=row[0]
489 portA=row[2]
490 portAspeed=fnc_port_speed(row[10])
491 portAtype=fnc_port_sfp(row[10])
492 ipA=row[8]
493 if not ipA: ipA="N/A"
494 nodeA=routerA + "_" + portA
495 ref1a=sync_dict.get(nodeA,"N/A")
496
497 routerB=row[5]
498 portB=row[4]
499 portBspeed=fnc_port_speed(row[11])
500 portBtype=fnc_port_sfp(row[11])
501 ipB=row[9]
502 if not ipB: ipB="N/A"
503 nodeB=routerB + "_" + portB
504 ref1b=sync_dict.get(nodeB,"N/A")
505
506 if router_mode=="0":
507 labelA="<"+ portA + "<BR />" + portAtype + portAspeed + "<BR />" + ipA + "<BR />" + ref1a +">"
508 labelB="<"+ portB + "<BR />" + portBtype + portBspeed + "<BR />" + ipB + "<BR />" + ref1b +">"
509 elif router_mode=="1" or router_mode=="2":
510 labelA= portA + "&#92;n" + portAtype + portAspeed + "&#92;n" + ipA + "&#92;n" + ref1a
511 labelB= portB + "&#92;n" + portBtype + portBspeed + "&#92;n" + ipB + "&#92;n" + ref1b
512 elif router_mode=="3":
513 labelA=""
514 labelB=""
515
516 temp_list.append((routerA,nodeA,{'label':labelA}))
517 temp_list.append((routerB,nodeB,{'label':labelB}))
518
519 # List will be ordered and sorted always by the first field
520 # which is the router name
521 lista_sorted=sorted(temp_list, key=itemgetter(0))
522 lista_grouped = groupby(lista_sorted, key=itemgetter(0))
523
524 a = []
525 for i,rou in enumerate(lista_grouped):
526 a.append(list(rou[1]))
527
528 return a
529
530 # Function that crosses the connections and interfaces to come out
531 # with a proper list
532 #
533 # Output:
534 #('Router1', 105L, '1/1/7', None, '2/2/10', 'Router2', 418L, 'Router', '10.2.34.113', '10.2.34.114', '1000Base-T', '1000Base-T')
535 #
536 def fnc_cross_conn_inter(connections,interfaces):
537 connection_list=[]
538
539 for conn in connections:
540
541 name1=conn[0]
542 id1=conn[1]
543 p1=conn[3]
544 cable=conn[4]
545 p2=conn[5]
546 name2=conn[7]
547 id2=conn[8]
548 router_type=conn[9]
549 ip1=""
550 ip2=""
551 p1t=conn[10]
552 p2t=conn[11]
553
554 int1=conn[2]
555 int2=conn[6]
556
557 for interface in interfaces:
558 int_name=interface[2]
559 ip=interface[3]
560 if int1==int_name:
561 ip1=ip
562 break
563 else:
564 ip1="N/A"
565
566 for interface in interfaces:
567 int_name=interface[2]
568 ip=interface[3]
569 if int2==int_name:
570 ip2=ip
571 break
572 else:
573 ip2="N/A"
574
575 connection_list.append((name1,id1,p1,cable,p2,name2,id2,router_type,ip1,ip2,p1t,p2t,int1,int2))
576
577 #fnc_print_list(connection_list)
578
579 return connection_list
580
581
582 # Function that builds a list which holds the connections among routers.
583 # The output of this function is used as input to graphviz
584 def fnc_edge_list(vector, graph_lag, graph_hp, graph_cpam, router_mode):
585 edge_list=[]
586 for row in vector:
587 routerA=row[0]
588 portA=row[2]
589 routerB=row[5]
590 portB=row[4]
591 cableID=row[3]
592 nodeA=routerA + "_" + portA
593 nodeB=routerB + "_" + portB
594
595 if not cableID: cableID=""
596
597 #print nodeA, cableID, nodeB
598
599 if ("LAG" in cableID.upper() and graph_lag=="n") or ("HAIRPIN" in cableID.upper() and graph_hp=="n") or ("CPAM" in cableID.upper() and graph_cpam=="n"):
600 a=1
601 else:
602 edge_list.append(((nodeA,nodeB),{'label':cableID}))
603
604 return edge_list
605
606 # Verifies that an object exists
607 def fnc_check_for_topo(objList):
608 if len(objList) == 0:
609 return 0
610 else:
611 return 1
612
613 # Function to print lists
614 def fnc_print_list(vector):
615 for vec in vector:
616 print vec
617
618 # Function to obtain topology name
619 def fnc_build_topo_name(vector):
620 topo_name=""
621 len_vector= len(vector)
622 i=1
623 for tn in vector:
624 if i < len_vector:
625 topo_name=topo_name+tn+"-"
626 else:
627 topo_name=topo_name+tn
628 i=i+1
629
630 return topo_name
631
632 # Function that returns the color of the router depending on its
633 # situation
634 def fnc_router_color(router_function,router_int,router_name):
635
636 # Ref_Order
637 router_sync_order=global_dict.get(router_name+"_Ref_Order","N/A")
638
639 # Color depending on function
640 if router_function == "High-Ran":
641 return 'lightblue4'
642 elif router_function == "Mid-Ran":
643 return 'lightpink4'
644 elif "si" in router_int:
645 # color depending on Ref_Order
646 if "ref1 ref2" in router_sync_order:
647 return 'lightblue3'
648 elif "ref2 ref1" in router_sync_order:
649 return 'lightblue1'
650 else:
651 return 'grey'
652 elif "TX" in router_function:
653 return 'yellow'
654 # Color depending on integration
655 elif router_int=="no":
656 return 'orange'
657 elif router_int=="out-of-service" or router_int=="desinsertado":
658 return 'red'
659 else:
660 return 'grey'
661
662 # Function that returns metadata of the router
663 def fnc_router_metadata(global_dict,router_name,what, router_function, router_ckt_id, router_mode):
664
665 router_sync_order=global_dict.get(router_name+"_Ref_Order","N/A")
666 router_ip=global_dict.get(router_name+"_system","N/A")
667
668 if "TX" in router_function:
669
670 if what=="labelHtml":
671
672 router_label=(
673 "<"+
674 "<font point-size=\"10\">"+router_ckt_id+"</font>"+"<BR />"
675 +">"
676 )
677 return router_label
678
679 elif what=="labelText":
680
681 router_label = router_ckt_id
682 return router_label
683
684 else:
685
686 if what=="labelHtml":
687
688 if router_mode=="3":
689 router_label=(
690 "<"+
691 "<font point-size=\"10\">"+router_name+"</font>"+"<BR />"+
692 "<font point-size=\"9\">" +router_ip+"</font>"+"<BR />"
693 +">"
694 )
695 return router_label
696
697 else:
698 router_label=(
699 "<"+
700 "<font point-size=\"10\">"+router_name+"</font>"+"<BR />"+
701 "<font point-size=\"9\">" +router_ip+"</font>"+"<BR />"+
702 "<font point-size=\"9\">" +router_sync_order+"</font>"
703 +">"
704 )
705 return router_label
706
707 elif what=="labelText":
708
709 if router_mode=="3":
710 router_label = router_name + "&#92;n" + router_ip
711 return router_label
712 else:
713 router_label = router_name + "&#92;n" + router_ip + "&#92;n" + router_sync_order
714 return router_label
715
716
717
718 # Function that returns port_string when router as a node
719 def fnc_port_string(router_label, port_string, color, router_mode, router_function):
720
721 port_string=port_string[1:]
722 temp_port = port_string.split("|")
723
724 if "TX" in router_function:
725
726 if router_function == "TX_MIX":
727
728 temp_string=""
729
730 for port in port_string.split("|"):
731 temp_string = temp_string + port.split("\n")[0] + "|"
732
733 port_string = temp_string[:-1]
734
735 temp_string = "{" + port_string + "}"
736 temp_string = " [" + color + ",label=\"" + temp_string + "\"]"
737 return temp_string
738
739 elif router_function == "TX_ARSAT":
740
741 #print router_label
742
743 temp_string = "{" + router_label + "}"
744 temp_string = " [" + color + ",label=\"" + temp_string + "\"]"
745 return temp_string
746
747 else:
748
749 if router_mode=="1":
750 temp_string = "{" + router_label + "|" + port_string + "}"
751 elif router_mode=="2":
752 temp_string = "{" + router_label + "|" + "{" + port_string + "}" + "}"
753 elif router_mode=="3":
754 temp_string = router_label
755
756 temp_string = " [" + color + ",label=\"" + temp_string + "\"]"
757 return temp_string
758
759
760 ########################################################################
761 # Program
762 ########################################################################
763
764 db = MySQLdb.connect(host="10.10.61.10", # your host, usually localhost
765 port=3306,
766 user="root", # your username
767 passwd="mysqlroot", # your password
768 db="racktables") # name of the data base
769
770 posProg = 0
771 posTopo = 1
772 posMode = 2
773 posFormat = 3
774 posAlgo = 4
775 posDirect = 5
776 posLine = 6
777 posAggreg = 7
778 #posLag = 8
779 #posHairPin = 9
780 #posCPAM = 10
781
782 # Check for inline parameters
783 if len(sys.argv)<8:
784 print "Not enough paramteres. Quitting..."
785 sys.exit(-1)
786
787 # Getting topo name
788 topo_name = sys.argv[posTopo]
789 topo_name = topo_name.upper()
790 topo_name = topo_name.split(",")
791
792 #==================================================================
793 #==================================================================
794 # query0 obtains the Id of the tag_name.
795
796 query0 = fnc_build_query_topo_id(topo_name)
797
798 cur = db.cursor()
799 cur.execute(query0)
800 topo_id = list(cur.fetchall())
801 if fnc_check_for_topo(topo_id) == 0:
802 print "Topology not found. Quitting..."
803 sys.exit(-1)
804
805 #==================================================================
806 #==================================================================
807 # query10 obtains the IDs of routers that have tag 'topo_name'
808 # The result is the following.
809
810 #(objeto_name, object_id)
811
812 query10 = fnc_build_query_objetos(topo_id)
813
814 cur = db.cursor()
815 cur.execute(query10)
816 object_list = list(cur.fetchall())
817
818 #==================================================================
819 #==================================================================
820 # query15 obtains the attributes of the routers that have tag
821 # 'topo_name'.
822 # It also brings de system IP of the router.
823 # The result is the following.
824
825 #('Router1', 'Router1_1/1/1', 'Sync_Ref1', '1/1/1', None, '10.2.21.168')
826 #('Router1', 'Router1_1/1/2', 'Sync_Ref2', '1/1/2', None, '10.2.21.168')
827 #('Router1', None, 'Sync_Ref_Order', None, 'ref1 ref2 external', '10.2.21.168')
828 #('Router1', None, 'Integrado', None, 'si', '10.2.21.168')
829
830 query15=fnc_build_query_attributes(object_list)
831 cur=db.cursor()
832 cur.execute(query15)
833 attr_list = list(cur.fetchall())
834 sync_dict = fnc_add_atributes_to_dic_ref(attr_list)
835 global_dict = fnc_add_atributes_to_dic_global(attr_list)
836
837 #==================================================================
838 #==================================================================
839 # query20 brings the connection among objects.
840 # This query also brings connections to routers that do not have the
841 # the requested tag.
842 # The result is the following.
843
844 #(Router1, port1, cableID, port1, Router2)
845
846 #('Router1', 172L, 'Router1_RTR1toRTR2_1_1G', '1/6/8', None, '2/2/14', 'Router2_RTR2toRTR1_1_1G', 'Router2', 418L, 'Router', '1000Base-T', '1000Base-T')
847
848 query20=fnc_build_query_connections(object_list)
849 cur = db.cursor()
850 cur.execute(query20)
851 object_connections = list(cur.fetchall())
852
853 #==================================================================
854 #==================================================================
855 # query25 brings the connection among objects.
856 # This query obtains the interfaces and IP addresses.
857
858 # (Router, ID, Interface_name, IP)
859
860 query25=fnc_build_query_interfaces(object_list)
861 cur = db.cursor()
862 cur.execute(query25)
863 object_interfaces = list(cur.fetchall())
864
865 #==================================================================
866 #==================================================================
867 # The function fnc_cross_conn_inter(.) crosses connections with
868 # interfaces to come out with the following information
869
870 #(Router1, port1, cableID, port1, Router2)
871 #('Router1', 105L, '1/1/7', None, '2/2/10', 'Router2', 418L, 'Router', '10.2.34.113', '10.2.34.114', '1000Base-T', '1000Base-T')
872
873 object_connections=fnc_cross_conn_inter(object_connections,object_interfaces)
874
875 #==================================================================
876 #==================================================================
877 # The function fnc_remove_routers_wotag(.) filters out the data
878 # obtained with query20 in such a way that only the connections
879 # to routers with the requested tag will remain.
880 # The result is the following.
881
882 #(Router1, port1, cableID, port1, Router2)
883 #('Router1', 105L, '1/1/7', None, '2/2/10', 'Router2', 418L, 'Router', '10.2.34.113', '10.2.34.114', '1000Base-T', '1000Base-T')
884
885 object_connections=fnc_remove_routers_wotag(object_list,object_connections)
886
887 #==================================================================
888 # The graph is created.
889 #==================================================================
890
891 # Format Dictionaries
892 mode_dict = {"0":"cluster", "1":"one-line", "2":"two-lines","3":"only-names"}
893 format_dict = {"0":"png", "1":"svg"}
894 algo_dict = {"0":"dot", "1":"fdp", "2":"circo", "3":"twopi", "4":"neato"}
895 rankdir_dict = {"0":"LR", "1":"TB"}
896 lines_dict = {"0":"line", "1":"true", "2":"ortho", "3":"polyline"}
897 aggr_dict = {"0":"n", "1":"y"}
898 port_dict = {}
899
900 router_mode = sys.argv[posMode]
901 output_format = sys.argv[posFormat]
902 output_algo = sys.argv[posAlgo]
903 output_direction = sys.argv[posDirect]
904 output_line = sys.argv[posLine]
905 aggregator = sys.argv[posAggreg]
906 graph_lag = "n"
907 graph_hp = "n"
908 graph_cpam = "n"
909
910 #print "mode", mode_dict[router_mode]
911 #print "format", format_dict[output_format]
912 #print "algori", algo_dict[output_algo]
913 #print "direcc", rankdir_dict[output_direction]
914 #print "line", lines_dict[output_line]
915 #print "aggr", aggr_dict[aggregator]
916
917 #==================================================================
918 #==================================================================
919 # At this instance of the run, the list object_connections[] only has
920 # connections to routers that do have the requested tag.
921 # The function fnc_edge_list(.) reorders that information
922 # so it will be easier to feed graphviz.
923
924 #((Router1_port1, Router2_port1), {label: cableID})
925
926 edges=fnc_edge_list(object_connections, graph_lag, graph_hp, graph_cpam, router_mode)
927
928 #===================================================================
929 #===================================================================
930 # The list edges[] holds the connections among routers that do have
931 # the requested tag.
932 # With this information we filter contruct a new list grouping ports
933 # per router.
934
935 #(Router1, Router1_portX, {'label':""}),(Router2, Router2_portY, {'label':""})
936 #('Router1', 'Router1_1/2/7', {'label': '1/2/7\nT-1Gb\n10.2.61.146\nSync_Ref1'}), ('Router2', 'Router2_1/2/8', {'label': '1/2/8\nT-1Gb\n10.2.61.149\nSync_Ref2'})
937
938 routers=fnc_node_list(object_connections,sync_dict, router_mode, graph_hp, graph_lag, graph_cpam)
939
940 #===================================================================
941 #===================================================================
942 # Gegin the plot
943
944 g0 = gv.Graph(format=format_dict[output_format], engine=algo_dict[output_algo])
945
946 topo = '\"'+fnc_build_topo_name(topo_name)+'\"'
947
948 g0.body.append('label='+topo)
949 g0.body.append('rankdir='+rankdir_dict[output_direction])
950 #g0.body.append('rank=min')
951 g0.body.append('splines='+lines_dict[output_line])
952 g0.node_attr['style']='filled'
953 g0.node_attr['fixedsize']='false'
954 g0.node_attr['fontsize']='9'
955
956 if router_mode=="0":
957 g0.node_attr['shape']='box'
958 labelType="labelHtml"
959 elif router_mode=="1" or router_mode=="2" or router_mode=="3":
960 g0.body.append('overlap=false')
961 g0.node_attr['shape']='Mrecord'
962 g0.node_attr['overlap']='false'
963 labelType="labelText"
964
965 if aggregator == "1":
966 g10 = gv.Graph('cluster_hr')
967 g20 = gv.Graph('cluster_mr')
968 g25 = gv.Graph('cluster_tx')
969 g30 = gv.Graph('cluster_lr', engine=algo_dict[output_algo])
970
971 g10.body.append('rankdir=TB')
972 g10.body.append('label=\"HR\"')
973
974 g20.body.append('rankdir=TB')
975 g20.body.append('label=\"MR\"')
976
977 g30.body.append('rankdir=TB')
978 g30.body.append('label=\"LR\"')
979
980 if router_mode=="0":
981 i = 1
982 for router in routers:
983 # Variables
984 router_name = router[0][0]
985 router_function=global_dict.get(router_name+"_function","N/A")
986 router_int=global_dict.get(router_name+"_Integrado","N/A")
987 router_ckt_id=global_dict.get(router_name+"_ckt_id","N/A")
988 router_label=fnc_router_metadata(global_dict,router_name,labelType, router_function, router_ckt_id, router_mode)
989 router_color=fnc_router_color(router_function,router_int,router_name)
990
991 #print router_name, router_function
992
993 # Parametrization
994 cluster_name = "cluster"+str(i)
995 c = gv.Graph(cluster_name)
996 c.body.append('label='+router_label)
997 c.body.append('shape=box')
998 c.body.append('style=filled')
999
1000 # Color depending on function in network
1001 c.body.append('fillcolor='+router_color)
1002 c.node_attr.update(style='filled')
1003
1004 # Ports workout
1005 for port in router:
1006
1007 node_id=port[1]
1008 if ":" in node_id: node_id=node_id.replace(":","#")
1009 port_id=port[2]['label']
1010 c.node(node_id,label=port_id)
1011
1012 # AsignaciĆ³n al cluster Low o High Run
1013 if aggregator == "1":
1014 if router_function == "High-Ran":
1015 g10.subgraph(c)
1016 elif router_function == "Mid-Ran":
1017 g20.subgraph(c)
1018 else:
1019 g30.subgraph(c)
1020
1021 g0.subgraph(g10)
1022 g0.subgraph(g20)
1023 g0.subgraph(g30)
1024
1025 # No grouping
1026 else:
1027 g0.subgraph(c)
1028
1029 i=i+1
1030
1031 for e in edges:
1032 edgeA=e[0][0]
1033 if ":" in edgeA: edgeA=edgeA.replace(":","#")
1034 edgeB=e[0][1]
1035 if ":" in edgeB: edgeB=edgeB.replace(":","#")
1036 edgeLabel=e[1]['label']
1037 g0.edge_attr['fontsize']='9'
1038 g0.edge(edgeA,edgeB,label=edgeLabel)
1039
1040 elif router_mode=="1" or router_mode=="2" or router_mode=="3":
1041 i = 1
1042 for router in routers:
1043 # Variables
1044 router_name = router[0][0]
1045 router_function=global_dict.get(router_name+"_function","N/A")
1046 router_int=global_dict.get(router_name+"_Integrado","N/A")
1047 router_ckt_id=global_dict.get(router_name+"_ckt_id","N/A")
1048 router_label=fnc_router_metadata(global_dict,router_name,labelType, router_function, router_ckt_id, router_mode)
1049 router_color=fnc_router_color(router_function,router_int,router_name)
1050
1051 # Parametrization
1052 struct_name = "struct"+str(i)
1053
1054 # Color depending on function in network
1055 color= 'fillcolor='+router_color
1056
1057 # Ports workout
1058 p=1
1059 port_string=""
1060 for port in router:
1061
1062 node_id=port[1]
1063 if ":" in node_id: node_id=node_id.replace(":","#")
1064 port_id=port[2]['label']
1065
1066 port_string=port_string+"|<f"+str(p)+">"+port_id
1067 dict_key = str(i)+"_"+str(p)
1068 port_dict[node_id]=dict_key
1069
1070 p=p+1
1071
1072 node_string = fnc_port_string(router_label, port_string, color, router_mode, router_function)
1073
1074 # AsignaciĆ³n al cluster Low o High Run
1075 if aggregator == "1":
1076 if router_function == "High-Ran": g10.body.append(struct_name+node_string)
1077 elif router_function == "Mid-Ran": g20.body.append(struct_name+node_string)
1078 else: g30.body.append(struct_name+node_string)
1079 g0.subgraph(g10)
1080 g0.subgraph(g20)
1081 g0.subgraph(g30)
1082
1083 # No grouping
1084 else:
1085 g0.body.append(struct_name+node_string)
1086
1087 i=i+1
1088
1089 for e in edges:
1090 tempA=e[0][0]
1091 if ":" in tempA: tempA=tempA.replace(":","#")
1092 tempA=port_dict[tempA].split("_")
1093 if router_mode=="3":
1094 edgeA="struct"+tempA[0]
1095 else:
1096 edgeA="struct"+tempA[0]+":f"+tempA[1]
1097
1098 tempB=e[0][1]
1099 if ":" in tempB: tempB=tempB.replace(":","#")
1100 tempB=port_dict[tempB].split("_")
1101 if router_mode=="3":
1102 edgeB="struct"+tempB[0]
1103 else:
1104 edgeB="struct"+tempB[0]+":f"+tempB[1]
1105
1106 edgeLabel=e[1]['label']
1107 g0.edge_attr['fontsize']='9'
1108 g0.edge(edgeA,edgeB,label=edgeLabel)
1109
1110 filename=fnc_build_filename(topo_name)
1111 print filename + "." + format_dict[output_format]
1112 g0.render(filename)