svn keywords
[plcapi.git] / PLC / Methods / GetNodes.py
1 # $Id$
2 # $URL$
3 from PLC.Faults import *
4 from PLC.Method import Method
5 from PLC.Parameter import Parameter, Mixed
6 from PLC.Filter import Filter
7 from PLC.Nodes import Node, Nodes
8 from PLC.Persons import Person, Persons
9 from PLC.Auth import Auth
10
11 admin_only = ['key', 'session', 'boot_nonce' ]
12
13 class v43GetNodes(Method):
14     """
15     Returns an array of structs containing details about nodes. If
16     node_filter is specified and is an array of node identifiers or
17     hostnames, or a struct of node attributes, only nodes matching the
18     filter will be returned. 
19
20     If return_fields is specified, only the specified details will be
21     returned. NOTE that if return_fields is unspecified, the complete
22     set of native fields are returned, which DOES NOT include tags at
23     this time.
24
25     Some fields may only be viewed by admins.
26     """
27
28     roles = ['admin', 'pi', 'user', 'tech', 'node', 'anonymous']
29
30     accepts = [
31         Auth(),
32         Mixed([Mixed(Node.fields['node_id'],
33                      Node.fields['hostname'])],
34               Parameter(str,"hostname"),
35               Parameter(int,"node_id"),
36               Filter(Node.fields)),
37         Parameter([str], "List of fields to return", nullok = True),
38         ]
39
40     returns = [Node.fields]
41
42
43     def call(self, auth, node_filter = None, return_fields = None):
44         
45         # Must query at least slice_ids_whitelist
46         if return_fields is not None:
47             added_fields = set(['slice_ids_whitelist', 'site_id']).difference(return_fields)
48             return_fields += added_fields
49         else:
50             added_fields =[]    
51
52         # Get node information
53         nodes = Nodes(self.api, node_filter, return_fields)
54
55         # Remove admin only fields
56         if not isinstance(self.caller, Person) or \
57            'admin' not in self.caller['roles']:
58             slice_ids = set()
59             site_ids = set()
60             
61             if self.caller:
62                 slice_ids.update(self.caller['slice_ids'])
63                 if isinstance(self.caller, Node):
64                     site_ids.update([self.caller['site_id']])
65                 else:  
66                     site_ids.update(self.caller['site_ids'])
67
68             # if node has whitelist, only return it if users is at
69             # the same site or user has a slice on the whitelist 
70             for node in nodes[:]:
71                 if 'site_id' in node and \
72                    site_ids.intersection([node['site_id']]):
73                     continue    
74                 if 'slice_ids_whitelist' in node and \
75                    node['slice_ids_whitelist'] and \
76                    not slice_ids.intersection(node['slice_ids_whitelist']):
77                     nodes.remove(node)
78
79             # remove remaining admin only fields
80             for node in nodes:    
81                 for field in admin_only:
82                     if field in node:
83                         del node[field]
84         
85         # remove added fields if not specified
86         if added_fields:
87             for node in nodes:
88                 for field in added_fields:
89                     del node[field]     
90
91         return nodes
92
93 node_fields = Node.fields.copy()
94 node_fields['nodenetwork_ids']=Parameter([int], "Legacy version of interface_ids")
95
96 class v42GetNodes(v43GetNodes):
97     """
98     Legacy wrapper for v43GetNodes.
99     """
100
101     accepts = [
102         Auth(),
103         Mixed([Mixed(Node.fields['node_id'],
104                      Node.fields['hostname'])],
105               Parameter(str,"hostname"),
106               Parameter(int,"node_id"),
107               Filter(node_fields)),
108         Parameter([str], "List of fields to return", nullok = True),
109         ]
110     returns = [node_fields]
111
112     def call(self, auth, node_filter = None, return_fields = None):
113         # convert nodenetwork_ids -> interface_ids
114         if isinstance(node_filter, dict):
115             if node_filter.has_key('nodenetwork_ids'):
116                 interface_ids = node_filter.pop('nodenetwork_ids')
117                 if not node_filter.has_key('interface_ids'):
118                     node_filter['interface_ids']=interface_ids
119
120         if isinstance(return_fields, list):
121             if 'nodenetwork_ids' in return_fields:
122                 return_fields.remove('nodenetwork_ids')
123                 if 'interface_ids' not in return_fields:
124                     return_fields.append('interface_ids')
125         nodes = v43GetNodes.call(self,auth,node_filter,return_fields)
126         # if interface_ids are present, then create a nodenetwork_ids mapping
127         for node in nodes:
128             if node.has_key('interface_ids'):
129                 node['nodenetwork_ids']=node['interface_ids']
130         return nodes
131
132 class GetNodes(v42GetNodes):
133     """
134     Returns an array of structs containing details about nodes. If
135     node_filter is specified and is an array of node identifiers or
136     hostnames, or a struct of node attributes, only nodes matching the
137     filter will be returned. If return_fields is specified, only the
138     specified details will be returned.
139
140     Some fields may only be viewed by admins.
141     """
142
143     pass