- re-enable return_fields specification
[plcapi.git] / PLC / Methods / GetSlivers.py
index 04982d4..181db4d 100644 (file)
@@ -3,6 +3,7 @@ import time
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Faults import *
 from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
+from PLC.Filter import Filter
 from PLC.Auth import Auth
 from PLC.Nodes import Node, Nodes
 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
 from PLC.Auth import Auth
 from PLC.Nodes import Node, Nodes
 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
@@ -13,13 +14,19 @@ from PLC.Persons import Person, Persons
 from PLC.Keys import Key, Keys
 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
 
 from PLC.Keys import Key, Keys
 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
 
+def hashref(rows, key_field):
+    d = {}
+    for row in rows:
+        d[row[key_field]] = row
+    return d
+
 class GetSlivers(Method):
     """
     Returns an array of structs representing nodes and their slivers
 class GetSlivers(Method):
     """
     Returns an array of structs representing nodes and their slivers
-    (slices bound to nodes). If node_hostnames is specified, only
-    information about the specified nodes will be returned. If not
-    specified and called by a node, only information about the caller
-    will be returned.
+    (slices bound to nodes). If node_filter is specified, only
+    information about the specified nodes will be returned. If
+    node_filter is not specified and called by a node, only
+    information about the caller will be returned.
 
     All of the information returned by this call can be gathered from
     other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
 
     All of the information returned by this call can be gathered from
     other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
@@ -31,15 +38,15 @@ class GetSlivers(Method):
 
     accepts = [
         Auth(),
 
     accepts = [
         Auth(),
-        [Mixed(Node.fields['node_id'],
-               Node.fields['hostname'])]
+        Mixed([Mixed(Node.fields['node_id'],
+                     Node.fields['hostname'])],
+              Filter(Node.fields)),
         ]
 
     returns = [{
         'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
         'node_id': Node.fields['node_id'],
         'hostname': Node.fields['hostname'],
         ]
 
     returns = [{
         'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
         'node_id': Node.fields['node_id'],
         'hostname': Node.fields['hostname'],
-        'boot_state': Node.fields['boot_state'],
         'networks': [NodeNetwork.fields],
         'groups': [NodeGroup.fields['name']],
         'conf_files': [ConfFile.fields],
         'networks': [NodeNetwork.fields],
         'groups': [NodeGroup.fields['name']],
         'conf_files': [ConfFile.fields],
@@ -59,13 +66,13 @@ class GetSlivers(Method):
         }]
     }]
 
         }]
     }]
 
-    def call(self, auth, node_id_or_hostname_list = None):
+    def call(self, auth, node_filter = None):
         timestamp = int(time.time())
 
         timestamp = int(time.time())
 
-        if node_id_or_hostname_list is None and isinstance(self.caller, Node):
+        if node_filter is None and isinstance(self.caller, Node):
             all_nodes = {self.caller['node_id']: self.caller}
         else:
             all_nodes = {self.caller['node_id']: self.caller}
         else:
-            all_nodes = Nodes(self.api, node_id_or_hostname_list)
+            all_nodes = hashref(Nodes(self.api, node_filter), 'node_id')
             # XXX Add foreign nodes
 
         nodenetwork_ids = set()
             # XXX Add foreign nodes
 
         nodenetwork_ids = set()
@@ -77,23 +84,17 @@ class GetSlivers(Method):
             slice_ids.update(node['slice_ids'])
 
         # Get nodenetwork information
             slice_ids.update(node['slice_ids'])
 
         # Get nodenetwork information
-        if nodenetwork_ids:
-            all_nodenetworks = NodeNetworks(self.api, nodenetwork_ids)
-        else:
-            all_nodenetworks = {}
+        all_nodenetworks = hashref(NodeNetworks(self.api, nodenetwork_ids), 'nodenetwork_id')
 
         # Get node group information
 
         # Get node group information
-        if nodegroup_ids:
-            all_nodegroups = NodeGroups(self.api, nodegroup_ids)
-        else:
-            all_nodegroups = {}
+        all_nodegroups = hashref(NodeGroups(self.api, nodegroup_ids), 'nodegroup_id')
 
 
-        # Get configuration files
-        all_conf_files = ConfFiles(self.api, {'enabled': True})
+        # Get (enabled) configuration files
+        all_conf_files = hashref(ConfFiles(self.api, {'enabled': True}), 'conf_file_id')
 
         if slice_ids:
             # Get slices
 
         if slice_ids:
             # Get slices
-            all_slices = Slices(self.api, slice_ids)
+            all_slices = hashref(Slices(self.api, slice_ids), 'slice_id')
 
             person_ids = set()
             slice_attribute_ids = set()
 
             person_ids = set()
             slice_attribute_ids = set()
@@ -102,36 +103,44 @@ class GetSlivers(Method):
                 slice_attribute_ids.update(slice['slice_attribute_ids'])
 
             # Get user accounts
                 slice_attribute_ids.update(slice['slice_attribute_ids'])
 
             # Get user accounts
-            all_persons = Persons(self.api, person_ids)
+            all_persons = hashref(Persons(self.api, person_ids), 'person_id')
 
             key_ids = set()
             for person_id, person in all_persons.iteritems():
                 key_ids.update(person['key_ids'])
 
             # Get user account keys
 
             key_ids = set()
             for person_id, person in all_persons.iteritems():
                 key_ids.update(person['key_ids'])
 
             # Get user account keys
-            all_keys = Keys(self.api, key_ids)
+            all_keys = hashref(Keys(self.api, key_ids), 'key_id')
 
             # Get slice attributes
 
             # Get slice attributes
-            all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids)
+            all_slice_attributes = hashref(SliceAttributes(self.api, slice_attribute_ids), 'slice_attribute_id')
 
         nodes = []
         for node_id, node in all_nodes.iteritems():
             networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
             nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
             groups = [nodegroup['name'] for nodegroup in nodegroups]
 
         nodes = []
         for node_id, node in all_nodes.iteritems():
             networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
             nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
             groups = [nodegroup['name'] for nodegroup in nodegroups]
-            conf_files = dict([(conf_file['dest'], conf_file) for conf_file in all_conf_files.values()])
+
+            # If multiple entries for the same global configuration
+            # file exist, it is undefined which one takes precedence.
+            conf_files = {}
+            for conf_file in all_conf_files.values():
+                if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
+                    conf_files[conf_file['dest']] = conf_file
 
             # If a node belongs to multiple node
             # groups for which the same configuration file is defined,
             # it is undefined which one takes precedence.
             for nodegroup in nodegroups:
 
             # If a node belongs to multiple node
             # groups for which the same configuration file is defined,
             # it is undefined which one takes precedence.
             for nodegroup in nodegroups:
-                for conf_file in map(lambda id: all_conf_files[id], nodegroup['conf_file_ids']):
-                    conf_files[conf_file['dest']] = conf_file
+                for conf_file_id in nodegroup['conf_file_ids']:
+                    if conf_file_id in all_conf_files:
+                        conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
 
             # Node configuration files always take precedence over
             # node group configuration files.
 
             # Node configuration files always take precedence over
             # node group configuration files.
-            for conf_file in map(lambda id: all_conf_files[id], node['conf_file_ids']):
-                conf_files[conf_file['dest']] = conf_file
+            for conf_file_id in node['conf_file_ids']:
+                if conf_file_id in all_conf_files:
+                    conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
 
             slivers = []
             for slice in map(lambda id: all_slices[id], node['slice_ids']):
 
             slivers = []
             for slice in map(lambda id: all_slices[id], node['slice_ids']):