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