bring over newinterface branch from Verivue
[plcapi.git] / PLC / Methods / Legacy / 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 legacy_node_fields = {
14     'node_id': Parameter(int, "Node identifier"),
15     'node_type': Parameter(str,"Node type",max=20),
16     'hostname': Parameter(str, "Fully qualified hostname", max = 255),
17     'site_id': Parameter(int, "Site at which this node is located"),
18     'boot_state': Parameter(str, "Boot state", max = 20),
19     'run_level': Parameter(str, "Run level", max = 20),
20     'model': Parameter(str, "Make and model of the actual machine", max = 255, nullok = True),
21     'boot_nonce': Parameter(str, "(Admin only) Random value generated by the node at last boot", max = 128),
22     'version': Parameter(str, "Apparent Boot CD version", max = 64),
23     'ssh_rsa_key': Parameter(str, "Last known SSH host key", max = 1024),
24     'date_created': Parameter(int, "Date and time when node entry was created", ro = True),
25     'last_updated': Parameter(int, "Date and time when node entry was created", ro = True),
26     'last_contact': Parameter(int, "Date and time when node last contacted plc", ro = True),
27     'last_boot': Parameter(int, "Date and time when node last booted", ro = True),
28     'last_download': Parameter(int, "Date and time when node boot image was created", ro = True),
29     'last_pcu_reboot': Parameter(int, "Date and time when PCU reboot was attempted", ro = True),
30     'last_pcu_confirmation': Parameter(int, "Date and time when PCU reboot was confirmed", ro = True),
31     'last_time_spent_online': Parameter(int, "Length of time the node was last online before shutdown/failure", ro = True),
32     'last_time_spent_offline': Parameter(int, "Length of time the node was last offline after failure and before reboot", ro = True),
33     'verified': Parameter(bool, "Whether the node configuration is verified correct", ro=False),
34     'key': Parameter(str, "(Admin only) Node key", max = 256),
35     'session': Parameter(str, "(Admin only) Node session value", max = 256, ro = True),
36     'interface_ids': Parameter([int], "List of network interfaces that this node has"),
37     'conf_file_ids': Parameter([int], "List of configuration files specific to this node"),
38     # 'root_person_ids': Parameter([int], "(Admin only) List of people who have root access to this node"),
39     'slice_ids': Parameter([int], "List of slices on this node"),
40     'slice_ids_whitelist': Parameter([int], "List of slices allowed on this node"),
41     'pcu_ids': Parameter([int], "List of PCUs that control this node"),
42     'ports': Parameter([int], "List of PCU ports that this node is connected to"),
43     'peer_id': Parameter(int, "Peer to which this node belongs", nullok = True),
44     'peer_node_id': Parameter(int, "Foreign node identifier at peer", nullok = True),
45     'node_tag_ids' : Parameter ([int], "List of tags attached to this node"),
46     'nodegroup_ids': Parameter([int], "List of node groups that this node is in"),
47     }
48
49 def clean_node_fields(node):
50     remove_keys = [key for key in node.keys() if key not in legacy_node_fields.keys()]
51     for key in remove_keys:
52         del node[key]
53     return node
54
55
56 class GetNodes(Method):
57     """
58     Returns an array of structs containing details about nodes. If
59     node_filter is specified and is an array of node identifiers or
60     hostnames, or a struct of node attributes, only nodes matching the
61     filter will be returned.
62
63     If return_fields is specified, only the specified details will be
64     returned. NOTE that if return_fields is unspecified, the complete
65     set of native fields are returned, which DOES NOT include tags at
66     this time.
67
68     Some fields may only be viewed by admins.
69     """
70
71     roles = ['admin', 'pi', 'user', 'tech', 'node', 'anonymous']
72
73     accepts = [
74         Auth(),
75         Mixed([Mixed(Node.fields['node_id'],
76                      Node.fields['hostname'])],
77               Parameter(str,"hostname"),
78               Parameter(int,"node_id"),
79               Filter(legacy_node_fields)),
80         Parameter([str], "List of fields to return", nullok = True),
81         ]
82
83     returns = [legacy_node_fields]
84
85
86     def call(self, auth, node_filter = None, return_fields = None):
87
88         # Must query at least slice_ids_whitelist
89         if return_fields is not None:
90             added_fields = set(['slice_ids_whitelist', 'site_id']).difference(return_fields)
91             return_fields += added_fields
92         else:
93             added_fields =[]
94
95         # Get node information
96         nodes = Nodes(self.api, node_filter, return_fields)
97
98         # Remove admin only fields
99         if not isinstance(self.caller, Person) or \
100            'admin' not in self.caller['roles']:
101             slice_ids = set()
102             site_ids = set()
103
104             if self.caller:
105                 slice_ids.update(self.caller['slice_ids'])
106                 if isinstance(self.caller, Node):
107                     site_ids.update([self.caller['site_id']])
108                 else:
109                     site_ids.update(self.caller['site_ids'])
110
111             # if node has whitelist, only return it if users is at
112             # the same site or user has a slice on the whitelist
113             for node in nodes[:]:
114                 if 'site_id' in node and \
115                    site_ids.intersection([node['site_id']]):
116                     continue
117                 if 'slice_ids_whitelist' in node and \
118                    node['slice_ids_whitelist'] and \
119                    not slice_ids.intersection(node['slice_ids_whitelist']):
120                     nodes.remove(node)
121
122             # remove remaining admin only fields
123             for node in nodes:
124                 for field in admin_only:
125                     if field in node:
126                         del node[field]
127
128         # remove added fields if not specified
129         if added_fields:
130             for node in nodes:
131                 for field in added_fields:
132                     del node[field]
133
134         for node in nodes:
135             node = clean_node_fields(node)
136
137         return nodes