PlanetLab support toon-up: home_cleanup only nepi folders + make server support longe...
[nepi.git] / src / nepi / util / sfiapi.py
index 90affff..d82b28c 100644 (file)
@@ -1,27 +1,44 @@
 # -*- coding: utf-8 -*-
 
+
+import logging
+
 from nepi.util.parser import sfa
 
+###
+# TODO: This API is a mega hack to adapt the sfa interface to the plc interface.
+#       The right way to implement this would be to make node.py invoke generic 
+#       methods and to adapt the sfa and plc APIs to provide the reuired 
+#       data.
+
 class SFIAPI(object):
-    def __init__(self):
+    def __init__(self, slice_id):
         self._slice_tags = dict()
         self._slice_nodes = set()
         self._all_nodes = dict()
-        self._slice_id = None
-
-    def FetchSliceInfo(self, slice_id):
         self._slice_id = slice_id
+
+        self._logger = logging.getLogger('nepi.utils.sfiapi')
+        
+        self.FetchSliceInfo()
+
+    def FetchSliceInfo(self):
         p = sfa.SFAResourcesParser()
         import commands
         xml = commands.getoutput("sfi.py resources")
-        self._all_nodes = p.resources_from_xml(xml)
-        xml = commands.getoutput("sfi.py resources %s" % slice_id)
-        self._slice_tags, self._slice_nodes = p.slice_info_from_xml(xml)
+        try:
+            self._all_nodes = p.resources_from_xml(xml)
+            xml = commands.getoutput("sfi.py resources %s" % self._slice_id)
+            self._slice_tags, self._slice_nodes = p.slice_info_from_xml(xml)
+        except:
+            self._logger.error("Error in SFA responds: %s", xml)
+            raise
     
     def GetSliceNodes(self, slicename):
         return list(self._slice_nodes)
 
     def GetNodeInfo(self, node_id):
+        # TODO: thread-unsafe!! sanitize!
         info = self.GetNodes(node_id)
         tags = self.GetNodeTags(node_id=node_id, fields=('tagname','value'))
         return info, tags
@@ -50,7 +67,6 @@ class SFIAPI(object):
 
     def GetNodes(self, nodeIdOrName=None, fields=[], **kw):
         #TODO: filter - peer
-        #      field - interface_ids
         nodes = self._all_nodes
         if nodeIdOrName is not None:
             node_ids = nodeIdOrName
@@ -62,8 +78,12 @@ class SFIAPI(object):
             if '|slice_ids' in filters:
                 nodes = self._FilterByNodeId(nodes, self._slice_nodes)
                 del filters['|slice_ids']
+            # TODO: Remove this!! need to allow filter '>last_contact' !!!
+            for f in ['>last_contact', 'node_type', 'run_level']:
+                if f in filters:
+                    del filters[f]
             nodes = self._FilterByFilters(nodes, filters)
-        return self._GetNodeInfo(nodes, fields)
+        return self._GetNodeFieldsInfo(nodes, fields)
     
     def _FilterByNodeId(self, nodes, node_ids):
         return dict((k, nodes[k]) for k in node_ids if k in nodes)
@@ -72,23 +92,36 @@ class SFIAPI(object):
         def has_all_tags(node_id):
             data = nodes[node_id]
             for name, value in filters.iteritems():
-                #if  (name == '>last_contact' and data['lastcontact'] > value) or \
-                if (not name in data or data[tag] != value):
-                    return False
+                if name == 'value' or name == 'tagname':
+                    tagname = filters['tagname']
+                    tagval = filters['value']
+                    if data[tagname] != tagval:
+                        return False
+                elif name == 'node_id':
+                    node_ids = list(value)
+                    if node_id not in node_ids:
+                        return False
+                else:
+                    #if  (name == '>last_contact' and data['lastcontact'] > value) or \
+                    if (not name in data or data[name] != value):
+                        return False
             return True
         return dict((k, value) for k, value in nodes.iteritems() if has_all_tags(k))
 
-    def _GetNodeInfo(self, nodes, fields):
+    def _GetNodeFieldsInfo(self, nodes, fields):
         result = list()
         for k, data in nodes.iteritems():
+            if not fields:
+                result.append(data)
+                continue
             r_data = dict()
-            result.append(r_data)
             for f in fields:
                 if f == "node_id":
                     value = k
                 else:
                     value = data[f]
                 r_data[f] = value
+            result.append(r_data)
         return result
 
     def _GetTagInfo(self, nodes, tagnames, fields):
@@ -124,7 +157,6 @@ class SFIAPI(object):
         #print out
 
 def sfiapi(slice_id):
-    api = SFIAPI()
-    api.FetchSliceInfo(slice_id)
+    api = SFIAPI(slice_id)
     return api