pvl.hosts-graph: parse new attribute-values format
authorTero Marttila <terom@paivola.fi>
Tue, 18 Mar 2014 23:53:16 +0200
changeset 400 41dd2a867e0a
parent 399 aadf76a05ec1
child 401 e57c200f3e26
pvl.hosts-graph: parse new attribute-values format
bin/pvl.hosts-graph
--- a/bin/pvl.hosts-graph	Tue Mar 18 23:14:01 2014 +0200
+++ b/bin/pvl.hosts-graph	Tue Mar 18 23:53:16 2014 +0200
@@ -36,6 +36,16 @@
     def __str__ (self) :
         return "{self.file}:{self.line}: {self.msg}".format(self=self)
 
+def _parse_snmp_part (part) :
+    if part.isdigit() :
+        return int(part)
+    else :
+        return part
+
+def _parse_snmp_line (line) :
+    for part in line.split() :
+        yield _parse_snmp_part(part)
+
 def _load_snmp_data (options, file) :
     """
         Load a data dict generated by pvl.hosts-snmp from a file.
@@ -46,30 +56,57 @@
     host = None
     attr = None
     value = None
+    values = None
     
     for idx, line in enumerate(file, 1) :
-        indent = line.count('\t')
+        indent = 0
+
+        while line.startswith('\t') :
+            indent += 1
+            line = line[1:]
+
         line = line.strip()
 
+        if '\t' in line :
+            args = line.split('\t', 1)
+
+            line = args.pop(0)
+            args = tuple(args)
+        else :
+            args = None
+
         if indent == 0 :
             host = line
             attr = None
             value = None
+            values = None
 
         elif indent == 1 :
-            if attr and not value :
-                yield host, attr, None
+            if attr and not value and not values :
+                raise ParseError(file, line, "[%s] %s: no value" % (host, attr))
 
-            attr = tuple((int(a) if a.isdigit() else a) for a in line.split())
-            value = None
+            attr = tuple(_parse_snmp_line(line))
+
+            if args :
+                value = tuple(tuple(_parse_snmp_line(arg)) for arg in args)
+            else :
+                value = None
+            
+            values = None
+
+            if value :
+                yield host, attr, value
 
         elif indent == 2 :
             if not attr :
-                raise ParseError(file, line, "value outside of attr")
+                raise ParseError(file, line, "[%s] %s: value outside of attr" % (host, attr))
+            
+            if value :
+                raise ParseError(file, line, "[%s] %s: values with value" % (host, attr))
 
-            value = line
+            values = _parse_snmp_part(line)
 
-            yield host, attr, value
+            yield host, attr, set((values, ))
 
 def load_snmp_data (options, file, hosts) :
     """
@@ -89,23 +126,18 @@
         log.info("[%s] %s%s", host, ' '.join(str(a) for a in attr), (': ' + str(value)) if value else '')
 
         item = root.setdefault(host, { })
-
-        if value :
-            end = None
-        else :
-            end = attr[-1]
-            attr = attr[:-1]
-
+        
         for a in attr[:-1] :
             item = item.setdefault(a, {})
 
         a = attr[-1]
+        
+        if isinstance(value, set) :
+            item.setdefault(a, set()).update(value)
 
-        if value is None :
-            item[a] = end
         else :
-            item.setdefault(a, set()).add(value)
-    
+            item[a] = dict(value)
+            
     return root
 
 def apply_graph (options, items, vlans={}) :