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.Auth import Auth
8 from PLC.Nodes import Node, Nodes
9 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
10 from PLC.NodeGroups import NodeGroup, NodeGroups
11 from PLC.ConfFiles import ConfFile, ConfFiles
12 from PLC.Slices import Slice, Slices
13 from PLC.Persons import Person, Persons
14 from PLC.Keys import Key, Keys
15 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
17 class GetSlivers(Method):
19 Returns a struct containing information about the specified node
20 (or calling node, if called by a node and node_id_or_hostname is
21 not specified), including the current set of slivers bound to the
24 All of the information returned by this call can be gathered from
25 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
26 function exists almost solely for the benefit of Node Manager.
29 roles = ['admin', 'node']
33 Mixed(Node.fields['node_id'],
34 Node.fields['hostname']),
38 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
39 'node_id': Node.fields['node_id'],
40 'hostname': Node.fields['hostname'],
41 'networks': [NodeNetwork.fields],
42 'groups': [NodeGroup.fields['name']],
43 'conf_files': [ConfFile.fields],
45 'name': Slice.fields['name'],
46 'slice_id': Slice.fields['slice_id'],
47 'instantiation': Slice.fields['instantiation'],
48 'expires': Slice.fields['expires'],
50 'key_type': Key.fields['key_type'],
51 'key': Key.fields['key']
54 'name': SliceAttribute.fields['name'],
55 'value': SliceAttribute.fields['value']
60 def call(self, auth, node_id_or_hostname = None):
61 timestamp = int(time.time())
64 if node_id_or_hostname is None:
65 if isinstance(self.caller, Node):
68 raise PLCInvalidArgument, "'node_id_or_hostname' not specified"
70 nodes = Nodes(self.api, [node_id_or_hostname])
72 raise PLCInvalidArgument, "No such node"
75 if node['peer_id'] is not None:
76 raise PLCInvalidArgument, "Not a local node"
78 # Get nodenetwork information
79 networks = NodeNetworks(self.api, node['nodenetwork_ids'])
81 # Get node group information
82 nodegroups = NodeGroups(self.api, node['nodegroup_ids']).dict('name')
83 groups = nodegroups.keys()
86 system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
87 system_slice_ids = system_slice_attributes.keys()
89 # Get slice information
90 slices = Slices(self.api, system_slice_ids + node['slice_ids'])
92 # Build up list of users and slice attributes
94 slice_attribute_ids = set()
96 person_ids.update(slice['person_ids'])
97 slice_attribute_ids.update(slice['slice_attribute_ids'])
99 # Get user information
100 all_persons = Persons(self.api, person_ids).dict()
102 # Build up list of keys
104 for person in all_persons.values():
105 key_ids.update(person['key_ids'])
107 # Get user account keys
108 all_keys = Keys(self.api, key_ids).dict()
110 # Get slice attributes
111 all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids).dict()
113 # Get all (enabled) configuration files
114 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
117 # Global configuration files are the default. If multiple
118 # entries for the same global configuration file exist, it is
119 # undefined which one takes precedence.
120 for conf_file in all_conf_files.values():
121 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
122 conf_files[conf_file['dest']] = conf_file
124 # Node group configuration files take precedence over global
125 # ones. If a node belongs to multiple node groups for which
126 # the same configuration file is defined, it is undefined
127 # which one takes precedence.
128 for nodegroup in nodegroups.values():
129 for conf_file_id in nodegroup['conf_file_ids']:
130 if conf_file_id in all_conf_files:
131 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
133 # Node configuration files take precedence over node group
134 # configuration files.
135 for conf_file_id in node['conf_file_ids']:
136 if conf_file_id in all_conf_files:
137 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
142 for person_id in slice['person_ids']:
143 if person_id in all_persons:
144 person = all_persons[person_id]
145 if not person['enabled']:
147 for key_id in person['key_ids']:
148 if key_id in all_keys:
149 key = all_keys[key_id]
150 keys += [{'key_type': key['key_type'],
155 # All (per-node and global) attributes for this slice
156 slice_attributes = []
157 for slice_attribute_id in slice['slice_attribute_ids']:
158 if slice_attribute_id in all_slice_attributes:
159 slice_attributes.append(all_slice_attributes[slice_attribute_id])
161 # Per-node sliver attributes take precedence over global
162 # slice attributes, so set them first.
163 sliver_attributes = []
164 for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_attributes):
165 sliver_attributes.append(sliver_attribute['name'])
166 attributes.append({'name': sliver_attribute['name'],
167 'value': sliver_attribute['value']})
169 for slice_attribute in filter(lambda a: a['node_id'] is None, slice_attributes):
170 # Do not set any global slice attributes for
171 # which there is at least one sliver attribute
173 if slice_attribute['name'] not in sliver_attributes:
174 attributes.append({'name': slice_attribute['name'],
175 'value': slice_attribute['value']})
178 'name': slice['name'],
179 'slice_id': slice['slice_id'],
180 'instantiation': slice['instantiation'],
181 'expires': slice['expires'],
183 'attributes': attributes
187 'timestamp': timestamp,
188 'node_id': node['node_id'],
189 'hostname': node['hostname'],
190 'networks': networks,
192 'conf_files': conf_files.values(),