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
11 admin_only = ['key', 'session', 'boot_nonce' ]
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"),
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:
56 class GetNodes(Method):
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.
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
68 Some fields may only be viewed by admins.
71 roles = ['admin', 'pi', 'user', 'tech', 'node', 'anonymous']
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),
83 returns = [legacy_node_fields]
85 # needed for generating the doc and prevent conflicts in the xml ids
88 def call(self, auth, node_filter = None, return_fields = None):
90 # Must query at least slice_ids_whitelist
91 if return_fields is not None:
92 added_fields = set(['slice_ids_whitelist', 'site_id']).difference(return_fields)
93 return_fields += added_fields
97 # Get node information
98 nodes = Nodes(self.api, node_filter, return_fields)
100 # Remove admin only fields
101 if not isinstance(self.caller, Person) or \
102 'admin' not in self.caller['roles']:
107 slice_ids.update(self.caller['slice_ids'])
108 if isinstance(self.caller, Node):
109 site_ids.update([self.caller['site_id']])
111 site_ids.update(self.caller['site_ids'])
113 # if node has whitelist, only return it if users is at
114 # the same site or user has a slice on the whitelist
115 for node in nodes[:]:
116 if 'site_id' in node and \
117 site_ids.intersection([node['site_id']]):
119 if 'slice_ids_whitelist' in node and \
120 node['slice_ids_whitelist'] and \
121 not slice_ids.intersection(node['slice_ids_whitelist']):
124 # remove remaining admin only fields
126 for field in admin_only:
130 # remove added fields if not specified
133 for field in added_fields:
137 node = clean_node_fields(node)