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
16 from PLC.InitScripts import InitScript, InitScripts
18 def get_slivers(api, slice_filter, node = None):
19 # Get slice information
20 slices = Slices(api, slice_filter, ['slice_id', 'name', 'instantiation', 'expires', 'person_ids', 'slice_attribute_ids'])
22 # Build up list of users and slice attributes
24 slice_attribute_ids = set()
26 person_ids.update(slice['person_ids'])
27 slice_attribute_ids.update(slice['slice_attribute_ids'])
29 # Get user information
30 all_persons = Persons(api, {'person_id':person_ids,'enabled':True}, ['person_id', 'enabled', 'key_ids']).dict()
32 # Build up list of keys
34 for person in all_persons.values():
35 key_ids.update(person['key_ids'])
37 # Get user account keys
38 all_keys = Keys(api, key_ids, ['key_id', 'key', 'key_type']).dict()
40 # Get slice attributes
41 all_slice_attributes = SliceAttributes(api, slice_attribute_ids).dict()
46 for person_id in slice['person_ids']:
47 if person_id in all_persons:
48 person = all_persons[person_id]
49 if not person['enabled']:
51 for key_id in person['key_ids']:
52 if key_id in all_keys:
53 key = all_keys[key_id]
54 keys += [{'key_type': key['key_type'],
59 # All (per-node and global) attributes for this slice
61 for slice_attribute_id in slice['slice_attribute_ids']:
62 if slice_attribute_id in all_slice_attributes:
63 slice_attributes.append(all_slice_attributes[slice_attribute_id])
65 # Per-node sliver attributes take precedence over global
66 # slice attributes, so set them first.
67 # Then comes nodegroup slice attributes
68 # Followed by global slice attributes
69 sliver_attributes = []
72 for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_attributes):
73 sliver_attributes.append(sliver_attribute['name'])
74 attributes.append({'name': sliver_attribute['name'],
75 'value': sliver_attribute['value']})
77 # set nodegroup slice attributes
78 for slice_attribute in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_attributes):
79 # Do not set any nodegroup slice attributes for
80 # which there is at least one sliver attribute
82 if slice_attribute['name'] not in slice_attributes:
83 attributes.append({'name': slice_attribute['name'],
84 'value': slice_attribute['value']})
86 for slice_attribute in filter(lambda a: a['node_id'] is None, slice_attributes):
87 # Do not set any global slice attributes for
88 # which there is at least one sliver attribute
90 if slice_attribute['name'] not in sliver_attributes:
91 attributes.append({'name': slice_attribute['name'],
92 'value': slice_attribute['value']})
95 'name': slice['name'],
96 'slice_id': slice['slice_id'],
97 'instantiation': slice['instantiation'],
98 'expires': slice['expires'],
100 'attributes': attributes
105 class GetSlivers(Method):
107 Returns a struct containing information about the specified node
108 (or calling node, if called by a node and node_id_or_hostname is
109 not specified), including the current set of slivers bound to the
112 All of the information returned by this call can be gathered from
113 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
114 function exists almost solely for the benefit of Node Manager.
117 roles = ['admin', 'node']
121 Mixed(Node.fields['node_id'],
122 Node.fields['hostname']),
126 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
127 'node_id': Node.fields['node_id'],
128 'hostname': Node.fields['hostname'],
129 'networks': [NodeNetwork.fields],
130 'groups': [NodeGroup.fields['name']],
131 'conf_files': [ConfFile.fields],
132 'initscripts': [InitScript.fields],
134 'name': Slice.fields['name'],
135 'slice_id': Slice.fields['slice_id'],
136 'instantiation': Slice.fields['instantiation'],
137 'expires': Slice.fields['expires'],
139 'key_type': Key.fields['key_type'],
140 'key': Key.fields['key']
143 'name': SliceAttribute.fields['name'],
144 'value': SliceAttribute.fields['value']
149 def call(self, auth, node_id_or_hostname = None):
150 timestamp = int(time.time())
153 if node_id_or_hostname is None:
154 if isinstance(self.caller, Node):
157 raise PLCInvalidArgument, "'node_id_or_hostname' not specified"
159 nodes = Nodes(self.api, [node_id_or_hostname])
161 raise PLCInvalidArgument, "No such node"
164 if node['peer_id'] is not None:
165 raise PLCInvalidArgument, "Not a local node"
167 # Get nodenetwork information
168 networks = NodeNetworks(self.api, node['nodenetwork_ids'])
170 # Get node group information
171 nodegroups = NodeGroups(self.api, node['nodegroup_ids']).dict('name')
172 groups = nodegroups.keys()
174 # Get all (enabled) configuration files
175 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
178 # Global configuration files are the default. If multiple
179 # entries for the same global configuration file exist, it is
180 # undefined which one takes precedence.
181 for conf_file in all_conf_files.values():
182 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
183 conf_files[conf_file['dest']] = conf_file
185 # Node group configuration files take precedence over global
186 # ones. If a node belongs to multiple node groups for which
187 # the same configuration file is defined, it is undefined
188 # which one takes precedence.
189 for nodegroup in nodegroups.values():
190 for conf_file_id in nodegroup['conf_file_ids']:
191 if conf_file_id in all_conf_files:
192 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
194 # Node configuration files take precedence over node group
195 # configuration files.
196 for conf_file_id in node['conf_file_ids']:
197 if conf_file_id in all_conf_files:
198 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
201 # Get all (enabled) initscripts
202 initscripts = InitScripts(self.api, {'enabled': True})
205 system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
206 system_slice_ids = system_slice_attributes.keys()
208 # Get nm-controller slices
209 controller_and_delegated_slices = Slices(self.api, {'instantiation': ['nm-controller', 'delegated']}, ['slice_id']).dict('slice_id')
210 controller_and_delegated_slice_ids = controller_and_delegated_slices.keys()
211 slice_ids = system_slice_ids + controller_and_delegated_slice_ids + node['slice_ids']
213 slivers = get_slivers(self.api, slice_ids, node)
215 node.update_last_contact()
218 'timestamp': timestamp,
219 'node_id': node['node_id'],
220 'hostname': node['hostname'],
221 'networks': networks,
223 'conf_files': conf_files.values(),
224 'initscripts': initscripts,