34 self.msg = msg |
34 self.msg = msg |
35 |
35 |
36 def __str__ (self) : |
36 def __str__ (self) : |
37 return "{self.file}:{self.line}: {self.msg}".format(self=self) |
37 return "{self.file}:{self.line}: {self.msg}".format(self=self) |
38 |
38 |
|
39 def _parse_snmp_part (part) : |
|
40 if part.isdigit() : |
|
41 return int(part) |
|
42 else : |
|
43 return part |
|
44 |
|
45 def _parse_snmp_line (line) : |
|
46 for part in line.split() : |
|
47 yield _parse_snmp_part(part) |
|
48 |
39 def _load_snmp_data (options, file) : |
49 def _load_snmp_data (options, file) : |
40 """ |
50 """ |
41 Load a data dict generated by pvl.hosts-snmp from a file. |
51 Load a data dict generated by pvl.hosts-snmp from a file. |
42 |
52 |
43 Yields (host, attr, value) |
53 Yields (host, attr, value) |
44 """ |
54 """ |
45 |
55 |
46 host = None |
56 host = None |
47 attr = None |
57 attr = None |
48 value = None |
58 value = None |
|
59 values = None |
49 |
60 |
50 for idx, line in enumerate(file, 1) : |
61 for idx, line in enumerate(file, 1) : |
51 indent = line.count('\t') |
62 indent = 0 |
|
63 |
|
64 while line.startswith('\t') : |
|
65 indent += 1 |
|
66 line = line[1:] |
|
67 |
52 line = line.strip() |
68 line = line.strip() |
|
69 |
|
70 if '\t' in line : |
|
71 args = line.split('\t', 1) |
|
72 |
|
73 line = args.pop(0) |
|
74 args = tuple(args) |
|
75 else : |
|
76 args = None |
53 |
77 |
54 if indent == 0 : |
78 if indent == 0 : |
55 host = line |
79 host = line |
56 attr = None |
80 attr = None |
57 value = None |
81 value = None |
|
82 values = None |
58 |
83 |
59 elif indent == 1 : |
84 elif indent == 1 : |
60 if attr and not value : |
85 if attr and not value and not values : |
61 yield host, attr, None |
86 raise ParseError(file, line, "[%s] %s: no value" % (host, attr)) |
62 |
87 |
63 attr = tuple((int(a) if a.isdigit() else a) for a in line.split()) |
88 attr = tuple(_parse_snmp_line(line)) |
64 value = None |
89 |
|
90 if args : |
|
91 value = tuple(tuple(_parse_snmp_line(arg)) for arg in args) |
|
92 else : |
|
93 value = None |
|
94 |
|
95 values = None |
|
96 |
|
97 if value : |
|
98 yield host, attr, value |
65 |
99 |
66 elif indent == 2 : |
100 elif indent == 2 : |
67 if not attr : |
101 if not attr : |
68 raise ParseError(file, line, "value outside of attr") |
102 raise ParseError(file, line, "[%s] %s: value outside of attr" % (host, attr)) |
69 |
103 |
70 value = line |
104 if value : |
71 |
105 raise ParseError(file, line, "[%s] %s: values with value" % (host, attr)) |
72 yield host, attr, value |
106 |
|
107 values = _parse_snmp_part(line) |
|
108 |
|
109 yield host, attr, set((values, )) |
73 |
110 |
74 def load_snmp_data (options, file, hosts) : |
111 def load_snmp_data (options, file, hosts) : |
75 """ |
112 """ |
76 Load snmp data as dict, from given file path, or stdin. |
113 Load snmp data as dict, from given file path, or stdin. |
77 """ |
114 """ |
87 host = hosts[host_name] |
124 host = hosts[host_name] |
88 |
125 |
89 log.info("[%s] %s%s", host, ' '.join(str(a) for a in attr), (': ' + str(value)) if value else '') |
126 log.info("[%s] %s%s", host, ' '.join(str(a) for a in attr), (': ' + str(value)) if value else '') |
90 |
127 |
91 item = root.setdefault(host, { }) |
128 item = root.setdefault(host, { }) |
92 |
129 |
93 if value : |
|
94 end = None |
|
95 else : |
|
96 end = attr[-1] |
|
97 attr = attr[:-1] |
|
98 |
|
99 for a in attr[:-1] : |
130 for a in attr[:-1] : |
100 item = item.setdefault(a, {}) |
131 item = item.setdefault(a, {}) |
101 |
132 |
102 a = attr[-1] |
133 a = attr[-1] |
103 |
134 |
104 if value is None : |
135 if isinstance(value, set) : |
105 item[a] = end |
136 item.setdefault(a, set()).update(value) |
106 else : |
137 |
107 item.setdefault(a, set()).add(value) |
138 else : |
108 |
139 item[a] = dict(value) |
|
140 |
109 return root |
141 return root |
110 |
142 |
111 def apply_graph (options, items, vlans={}) : |
143 def apply_graph (options, items, vlans={}) : |
112 import pydot |
144 import pydot |
113 |
145 |