]>
Commit | Line | Data |
---|---|---|
a6f80f0e | 1 | #!/usr/bin/python |
3e8ee54f | 2 | # |
904908bc | 3 | # Copyright 2014 Cumulus Networks, Inc. All rights reserved. |
3e8ee54f | 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com |
5 | # | |
6 | # graph -- | |
7 | # graph helper module for ifupdown | |
8 | # | |
a6f80f0e | 9 | |
10 | import logging | |
615234a1 | 11 | import copy |
a6f80f0e | 12 | from collections import deque |
739f665b | 13 | try: |
14 | from gvgen import * | |
15 | except ImportError, e: | |
16 | pass | |
a6f80f0e | 17 | |
18 | class graph(): | |
2c0ad8b3 | 19 | """ graph functions to sort and print interface graph """ |
a6f80f0e | 20 | |
afe51251 | 21 | logger = logging.getLogger('ifupdown.graph') |
a6f80f0e | 22 | |
23 | @classmethod | |
615234a1 | 24 | def topological_sort_graphs_all(cls, dependency_graphs, indegrees_arg): |
2c0ad8b3 RP |
25 | """ runs topological sort on interface list passed as dependency graph |
26 | ||
27 | Args: | |
904908bc RP |
28 | **dependency_graphs** (dict): dependency graph with dependency |
29 | lists for interfaces | |
30 | ||
31 | **indegrees_arg** (dict): indegrees array for all interfaces | |
2c0ad8b3 | 32 | """ |
a6f80f0e | 33 | S = [] |
34 | Q = deque() | |
35 | ||
615234a1 | 36 | indegrees = copy.deepcopy(indegrees_arg) |
a6f80f0e | 37 | for ifname,indegree in indegrees.items(): |
38 | if indegree == 0: | |
39 | Q.append(ifname) | |
40 | ||
fe0a57d3 | 41 | while len(Q): |
cca03c30 | 42 | # initialize queue |
43 | x = Q.popleft() | |
44 | ||
45 | # Get dependents of x | |
46 | dlist = dependency_graphs.get(x) | |
fe0a57d3 | 47 | if not dlist: |
cca03c30 | 48 | S.append(x) |
49 | continue | |
50 | ||
51 | for y in dlist: | |
67cfaeb1 RP |
52 | try: |
53 | indegrees[y] = indegrees.get(y) - 1 | |
54 | except: | |
afe51251 | 55 | cls.logger.debug('topological_sort_graphs_all: did not find %s' %y) |
67cfaeb1 RP |
56 | indegrees[y] = 0 |
57 | pass | |
cca03c30 | 58 | if indegrees.get(y) == 0: |
59 | Q.append(y) | |
60 | ||
61 | S.append(x) | |
62 | ||
63 | for ifname,indegree in indegrees.items(): | |
64 | if indegree != 0: | |
65 | raise Exception('cycle found involving iface %s' %ifname + | |
66 | ' (indegree %d)' %indegree) | |
67 | ||
68 | return S | |
69 | ||
739f665b | 70 | @classmethod |
71 | def generate_dots(cls, dependency_graph, indegrees): | |
2c0ad8b3 RP |
72 | """ spits out interface dependency graph in dot format |
73 | ||
74 | Args: | |
904908bc RP |
75 | **dependency_graphs** (dict): dependency graph with dependency |
76 | lists for interfaces | |
77 | ||
78 | **indegrees_arg** (dict): indegrees array for all interfaces | |
2c0ad8b3 RP |
79 | """ |
80 | ||
83c1f241 | 81 | gvgraph = GvGen() |
82 | graphnodes = {} | |
83 | for v in dependency_graph.keys(): | |
84 | graphnodes[v] = gvgraph.newItem(v) | |
739f665b | 85 | |
83c1f241 | 86 | for i, v in graphnodes.items(): |
87 | dlist = dependency_graph.get(i, []) | |
88 | if not dlist: | |
89 | continue | |
90 | for d in dlist: | |
91 | gvgraph.newLink(v, graphnodes.get(d)) | |
92 | gvgraph.dot() |