more pep8-friendly, and log calls to GetNodes() as well for troubleshooting database...
[plcapi.git] / PLC / Methods / GetNodes.py
1 from PLC.Faults import *
2 from PLC.Method import Method
3 from PLC.Parameter import Parameter, Mixed
4 from PLC.Filter import Filter
5 from PLC.Nodes import Node, Nodes
6 from PLC.Persons import Person, Persons
7 from PLC.Auth import Auth
8 from PLC.Logger import logger
9
10 admin_only = ['key', 'session', 'boot_nonce']
11
12 class GetNodes(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'])
47                             .difference(return_fields))
48             return_fields += added_fields
49         else:
50             added_fields = []
51
52         logger.info("incoming GetNodes, filter={}, return fields={}"
53                     .format(node_filter, return_fields))
54
55         # Get node information
56         nodes = Nodes(self.api, node_filter, return_fields)
57
58         # Remove admin only fields
59         if not isinstance(self.caller, Person) or \
60            'admin' not in self.caller['roles']:
61             slice_ids = set()
62             site_ids = set()
63
64             if self.caller:
65                 slice_ids.update(self.caller['slice_ids'])
66                 if isinstance(self.caller, Node):
67                     site_ids.update([self.caller['site_id']])
68                 else:
69                     site_ids.update(self.caller['site_ids'])
70
71             # if node has whitelist, only return it if users is at
72             # the same site or user has a slice on the whitelist
73             for node in nodes[:]:
74                 if 'site_id' in node and \
75                    site_ids.intersection([node['site_id']]):
76                     continue
77                 if 'slice_ids_whitelist' in node and \
78                    node['slice_ids_whitelist'] and \
79                    not slice_ids.intersection(node['slice_ids_whitelist']):
80                     nodes.remove(node)
81
82             # remove remaining admin only fields
83             for node in nodes:
84                 for field in admin_only:
85                     if field in node:
86                         del node[field]
87
88         # remove added fields if not specified
89         if added_fields:
90             for node in nodes:
91                 for field in added_fields:
92                     del node[field]
93
94         return nodes