41 if part.isdigit() : |
41 if part.isdigit() : |
42 return int(part) |
42 return int(part) |
43 else : |
43 else : |
44 return part |
44 return part |
45 |
45 |
46 def _parse_snmp_line (line) : |
46 def _parse_snmp_attr (line) : |
47 for part in line.split() : |
47 for part in line.split() : |
48 yield _parse_snmp_part(part) |
48 yield _parse_snmp_part(part) |
49 |
49 |
50 def _parse_snmp_attr (line) : |
50 def _parse_snmp_value (line) : |
51 parts = line.split() |
51 if '\t' in line : |
52 |
52 key, value = line.split('\t', 1) |
53 key = parts.pop(0) |
53 |
54 |
54 return { _parse_snmp_part(key): _parse_snmp_part(value) } |
55 if len(parts) == 0 : |
|
56 return key, None |
|
57 |
|
58 elif len(parts) == 1 : |
|
59 value, = parts |
|
60 |
|
61 return key, value |
|
62 |
55 |
63 else : |
56 else : |
64 return key, parts |
57 return set((_parse_snmp_part(line), )) |
65 |
58 |
66 def _load_snmp_data (options, file) : |
59 def _load_snmp_data (options, file) : |
67 """ |
60 """ |
68 Load a data dict generated by pvl.hosts-snmp from a file. |
61 Load a data dict generated by pvl.hosts-snmp from a file. |
69 |
62 |
70 Yields (host, attr, value) |
63 Yields (host, attr, value) |
71 """ |
64 """ |
72 |
65 |
73 host = None |
66 host = None |
74 attr = None |
67 attr = None |
75 value = None |
68 value = None |
76 values = None |
|
77 |
69 |
78 for idx, line in enumerate(file, 1) : |
70 for idx, line in enumerate(file, 1) : |
79 indent = 0 |
71 indent = 0 |
80 |
72 |
81 while line.startswith('\t') : |
73 while line.startswith('\t') : |
82 indent += 1 |
74 indent += 1 |
83 line = line[1:] |
75 line = line[1:] |
84 |
76 |
85 line = line.strip() |
77 line = line.lstrip('\t').rstrip('\n') |
86 |
|
87 if '\t' in line : |
|
88 args = line.split('\t') |
|
89 |
|
90 line = args.pop(0) |
|
91 args = tuple(args) |
|
92 else : |
|
93 args = None |
|
94 |
78 |
95 if indent == 0 : |
79 if indent == 0 : |
96 host = line |
80 host = line |
97 attr = None |
81 attr = None |
98 value = None |
82 value = None |
99 values = None |
|
100 |
83 |
101 elif indent == 1 : |
84 elif indent == 1 : |
102 if attr and not value and not values : |
85 attr = tuple(_parse_snmp_attr(line)) |
103 raise ParseError(file, line, "[%s] %s: no value" % (host, attr)) |
86 value = None |
104 |
87 |
105 attr = tuple(_parse_snmp_line(line)) |
88 yield host, attr, None |
106 |
|
107 if args : |
|
108 value = dict(_parse_snmp_attr(arg) for arg in args) |
|
109 else : |
|
110 value = None |
|
111 |
|
112 values = None |
|
113 |
|
114 if value : |
|
115 yield host, attr, value |
|
116 |
89 |
117 elif indent == 2 : |
90 elif indent == 2 : |
118 if not attr : |
91 if not attr : |
119 raise ParseError(file, line, "[%s] %s: value outside of attr" % (host, attr)) |
92 raise ParseError(file, line, "[%s] %s: value outside of attr" % (host, attr)) |
120 |
93 |
121 if value : |
94 value = _parse_snmp_value(line) |
122 raise ParseError(file, line, "[%s] %s: values with value" % (host, attr)) |
95 |
123 |
96 yield host, attr, value |
124 values = _parse_snmp_part(line) |
|
125 |
|
126 yield host, attr, set((values, )) |
|
127 |
97 |
128 def load_snmp_data (options, file, hosts) : |
98 def load_snmp_data (options, file, hosts) : |
129 """ |
99 """ |
130 Load snmp data as dict, from given file path, or stdin. |
100 Load snmp data as dict, from given file path, or stdin. |
131 """ |
101 """ |
137 |
107 |
138 root = { } |
108 root = { } |
139 |
109 |
140 for host_name, attr, value in _load_snmp_data(options, file) : |
110 for host_name, attr, value in _load_snmp_data(options, file) : |
141 host = hosts.get(host_name) |
111 host = hosts.get(host_name) |
142 |
112 |
143 log.info("[%s] %s%s", host, ' '.join(str(a) for a in attr), (': ' + str(value)) if value else '') |
113 if value : |
|
114 log.info("[%s] %s: %s", host, ' '.join(str(a) for a in attr), value) |
|
115 else : |
|
116 log.info("[%s] %s", host, ' '.join(str(a) for a in attr),) |
144 |
117 |
145 item = root.setdefault(host, { }) |
118 item = root.setdefault(host, { }) |
146 |
119 |
147 for a in attr[:-1] : |
120 for a in attr[:-1] : |
148 item = item.setdefault(a, {}) |
121 item = item.setdefault(a, {}) |
149 |
122 |
150 a = attr[-1] |
123 a = attr[-1] |
151 |
124 |
152 if isinstance(value, set) : |
125 if value is None : |
|
126 pass |
|
127 |
|
128 elif isinstance(value, set) : |
153 item.setdefault(a, set()).update(value) |
129 item.setdefault(a, set()).update(value) |
|
130 |
|
131 elif isinstance(value, dict) : |
|
132 item.setdefault(a, dict()).update(value) |
154 |
133 |
155 else : |
134 else : |
156 item[a] = value |
135 item[a] = value |
157 |
136 |
158 return root |
137 return root |
170 for port in snmp[host]['vlan'][vlan].get('tagged', ()) : |
149 for port in snmp[host]['vlan'][vlan].get('tagged', ()) : |
171 ports.add(port) |
150 ports.add(port) |
172 vlans_tagged[port].add(vlan) |
151 vlans_tagged[port].add(vlan) |
173 |
152 |
174 for port in snmp[host]['vlan'][vlan].get('untagged', ()) : |
153 for port in snmp[host]['vlan'][vlan].get('untagged', ()) : |
|
154 ports.add(port) |
175 vlans_untagged[port] = vlan |
155 vlans_untagged[port] = vlan |
176 |
156 |
177 out = { } |
157 out = { } |
178 for port in ports : |
158 for port in ports : |
179 untag = vlans_untagged.get(port) |
159 untag = vlans_untagged.get(port) |
180 tagged = vlans_tagged.get(port) |
160 tagged = vlans_tagged.get(port, ()) |
181 |
161 |
182 log.info("%s: %s: untag=%s tag=%s", host, port, untag, tagged) |
162 log.info("%s: %s: untag=%s tag=%s", host, port, untag, tagged) |
183 |
163 |
184 out[port] = (untag, tagged) |
164 out[port] = (untag, tagged) |
185 |
165 |