GetPeerData() ignores Sites/Slices/Persons that have the tag sfa_created=True, so...
[plcapi.git] / PLC / Methods / GetPeerData.py
index d651fa9..aff8f88 100644 (file)
@@ -1,6 +1,8 @@
 #
 # Thierry Parmentelat - INRIA
-# 
+#
+
+import time
 
 from PLC.Faults import *
 from PLC.Method import Method
@@ -13,46 +15,102 @@ from PLC.Sites import Site, Sites
 from PLC.Keys import Key, Keys
 from PLC.Nodes import Node, Nodes
 from PLC.Persons import Person, Persons
-from PLC.SliceAttributeTypes import SliceAttributeType, SliceAttributeTypes
 from PLC.Slices import Slice, Slices
-from PLC.SliceAttributes import SliceAttribute, SliceAttributes
+from PLC.SliceTags import SliceTags
 
-class GetPeerData (Method):
+class GetPeerData(Method):
     """
-    Gather all data needed by RefreshPeer in a single xmlrpc request
+    Returns lists of local objects that a peer should cache in its
+    database as foreign objects. Also returns the list of foreign
+    nodes in this database, for which the calling peer is
+    authoritative, to assist in synchronization of slivers.
 
-    Expects a peer id or peer name, that identifies the requesting peer
-    
-    Returns a dict containing, for the various types of cached entities,
-    the local objects as well as the ones attached to that peer
+    See the implementation of RefreshPeer for how this data is used.
     """
 
-    roles = ['admin']
+    roles = ['admin', 'peer']
+
+    accepts = [Auth()]
+
+    returns = {
+        'Sites': Parameter([dict], "List of local sites"),
+        'Keys': Parameter([dict], "List of local keys"),
+        'Nodes': Parameter([dict], "List of local nodes"),
+        'Persons': Parameter([dict], "List of local users"),
+        'Slices': Parameter([dict], "List of local slices"),
+        'db_time': Parameter(float, "(Debug) Database fetch time"),
+        }
+
+    def call (self, auth):
+        start = time.time()
+
+        # Filter out various secrets
+        node_fields = [ field for field in Node.fields if field \
+                            not in ['boot_nonce', 'key', 'session', 'root_person_ids']]
+        node_fields += ['hrn']
+        nodes = Nodes(self.api, {'peer_id': None}, node_fields);
+        # filter out whitelisted nodes
+        nodes = [ n for n in nodes if not n['slice_ids_whitelist']]
 
-    accepts = [Auth(),
-               Parameter (int, "Peer id"),
-               ]
-    # for RefreshPeer 
-    returns = Parameter (dict,"Sites, Keys, Nodes, Persons, Slices")
 
-    def call (self, auth, peer_id):
-        # xxx a peer cannot yet compute it's peer_id under another plc
-        # so we return all foreign objects by now
+        person_fields = [ field for field in Person.fields if field \
+                              not in ['password', 'verification_key', 'verification_expires']]
+
+        site_fields = Site.fields
+        slice_fields = Slice.fields
+        try:
+            person_fields += ['sfa_created','hrn']
+            site_fields += ['sfa_created','hrn']
+            slice_fields +=['sfa_created','hrn']
         
-        return {
-            'Sites-local' : Sites (self.api,{'peer_id':None}),
-            'Sites-peer' : Sites (self.api,{'~peer_id':None}),
-            'Keys-local' : Keys (self.api,{'peer_id':None}),
-            'Keys-peer' : Keys (self.api,{'~peer_id':None}),
-            'Nodes-local' : Nodes (self.api,{'peer_id':None}),
-            'Nodes-peer' : Nodes (self.api,{'~peer_id':None}),
-            'Persons-local' : Persons (self.api,{'peer_id':None}),
-            'Persons-peer' : Persons (self.api,{'~peer_id':None}),
-            'SliceAttibuteTypes-local' : SliceAttributeTypes (self.api,{'peer_id':None}),
-            'SliceAttibuteTypes-peer' : SliceAttributeTypes (self.api,{'~peer_id':None}),
-            'Slices-local' : Slices (self.api,{'peer_id':None}),
-            'Slices-peer' : Slices (self.api,{'~peer_id':None}),
-            'SliceAttributes-local': SliceAttributes (self.api,{'peer_id':None}),
-            'SliceAttributes-peer': SliceAttributes (self.api,{'~peer_id':None}),
-            }
+            # XXX Optimize to return only those Persons, Keys, and Slices
+            # necessary for slice creation on the calling peer's nodes.
+
+            # filter out special person
         
+            persons = Persons(self.api, {'~email':[self.api.config.PLC_API_MAINTENANCE_USER, self.api.config.PLC_ROOT_USER], 'peer_id': None}, person_fields)
+
+            # filter out system slices
+            system_slice_ids = SliceTags(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
+            slices = Slices(self.api, {'peer_id': None,'~slice_id':system_slice_ids.keys()}, slice_fields)
+
+            sites = Sites(self.api, {'peer_id': None}, site_fields)
+       
+            # filter out objects with  sfa_created=True
+            filtered_sites = [site for site in sites if site.get('sfa_created', None) != 'True']
+            filtered_slices = [slice for slice in slices if slice.get('sfa_created', None) != 'True']
+            filtered_persons = [person for person in persons if person.get('sfa_created', None) != 'True']  
+
+        except:
+            # handle peers with old version of MyPLC that does not support 'sfa_created' and 'hrn' fields for Site/Slice/Person 
+            # XXX Optimize to return only those Persons, Keys, and Slices
+            # necessary for slice creation on the calling peer's nodes.
+
+            # filter out special person
+
+            filtered_persons = Persons(self.api, {'~email':[self.api.config.PLC_API_MAINTENANCE_USER, self.api.config.PLC_ROOT_USER], 'peer_id': None}, person_fields)
+
+            # filter out system slices
+            system_slice_ids = SliceTags(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
+            filtered_slices = Slices(self.api, {'peer_id': None,
+                                   '~slice_id':system_slice_ids.keys()}, slice_fields)
+
+            filtered_sites = Sites(self.api, {'peer_id': None}, site_fields)
+
+
+        result = {
+            'Sites': filtered_sites,
+            'Keys': Keys(self.api, {'peer_id': None}),
+            'Nodes': nodes,
+            'Persons': filtered_persons,
+            'Slices': filtered_slices,
+            }
+
+
+        if isinstance(self.caller, Peer):
+            result['PeerNodes'] = Nodes(self.api, {'peer_id': self.caller['peer_id']})
+
+        result['db_time'] = time.time() - start
+
+        return result