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.ForeignSlices import ForeignSlice, ForeignSlices
14 from PLC.Persons import Person, Persons
15 from PLC.Keys import Key, Keys
16 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
18 class GetSlivers(Method):
20 Returns an array of structs representing nodes and their slivers
21 (slices bound to nodes). If node_filter is specified, only
22 information about the specified nodes will be returned. If
23 node_filter is not specified and called by a node, only
24 information about the caller will be returned.
26 All of the information returned by this call can be gathered from
27 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
28 function exists primarily for the benefit of Node Manager and
32 roles = ['admin', 'node']
36 Mixed([Mixed(Node.fields['node_id'],
37 Node.fields['hostname'])],
42 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
43 'node_id': Node.fields['node_id'],
44 'hostname': Node.fields['hostname'],
45 'networks': [NodeNetwork.fields],
46 'groups': [NodeGroup.fields['name']],
47 'conf_files': [ConfFile.fields],
49 'name': Slice.fields['name'],
50 'slice_id': Slice.fields['slice_id'],
51 'instantiation': Slice.fields['instantiation'],
52 'expires': Slice.fields['expires'],
54 'key_type': Key.fields['key_type'],
55 'key': Key.fields['key']
58 'name': SliceAttribute.fields['name'],
59 'value': SliceAttribute.fields['value']
65 def call(self, auth, node_filter = None):
66 timestamp = int(time.time())
68 if node_filter is None and isinstance(self.caller, Node):
69 all_nodes = {self.caller['node_id']: self.caller}
71 all_nodes = Nodes(self.api, node_filter).dict()
73 # Get local default slices
74 system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1', 'peer_id': None}).dict()
75 system_slice_ids = [slice_attribute['slice_id'] for slice_attribute in system_slice_attributes.values()]
76 system_slice_ids = dict.fromkeys(system_slice_ids)
78 all_nodenetwork_ids = set()
79 all_nodegroup_ids = set()
80 all_slice_ids = set(system_slice_ids.keys())
81 for node_id, node in all_nodes.iteritems():
82 all_nodenetwork_ids.update(node['nodenetwork_ids'])
83 all_nodegroup_ids.update(node['nodegroup_ids'])
84 all_slice_ids.update(node['slice_ids'])
86 # Get nodenetwork information
87 all_nodenetworks = NodeNetworks(self.api, all_nodenetwork_ids).dict()
89 # Get node group information
90 all_nodegroups = NodeGroups(self.api, all_nodegroup_ids).dict()
92 # Get (enabled) configuration files
93 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
95 # Get slice information
96 all_slices = Slices(self.api, all_slice_ids).dict()
99 slice_attribute_ids = set()
100 for slice_id, slice in all_slices.iteritems():
101 ### still missing in foreign slices
102 if slice.get('person_ids'):
103 person_ids.update(slice['person_ids'])
104 ### still missing in foreign slices
105 if slice.get('slice_attribute_ids'):
106 slice_attribute_ids.update(slice['slice_attribute_ids'])
108 # Get user information
109 all_persons = Persons(self.api, person_ids).dict()
112 for person_id, person in all_persons.iteritems():
113 key_ids.update(person['key_ids'])
115 # Get user account keys
116 all_keys = Keys(self.api, key_ids).dict()
118 # Get slice attributes
119 all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids).dict()
122 for node_id, node in all_nodes.iteritems():
123 networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
124 nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
125 groups = [nodegroup['name'] for nodegroup in nodegroups]
127 # If multiple entries for the same global configuration
128 # file exist, it is undefined which one takes precedence.
130 for conf_file in all_conf_files.values():
131 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
132 conf_files[conf_file['dest']] = conf_file
134 # If a node belongs to multiple node
135 # groups for which the same configuration file is defined,
136 # it is undefined which one takes precedence.
137 for nodegroup in nodegroups:
138 for conf_file_id in nodegroup['conf_file_ids']:
139 if conf_file_id in all_conf_files:
140 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
142 # Node configuration files always take precedence over
143 # node group configuration files.
144 for conf_file_id in node['conf_file_ids']:
145 if conf_file_id in all_conf_files:
146 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
148 # filter out any slices in this nodes slice_id list that may be invalid
149 # (i.e. expired slices)
150 slice_ids = dict.fromkeys(filter(lambda slice_id: slice_id in all_slice_ids, node['slice_ids']))
152 # If not a foreign node, add all of our default system
154 if node['peer_id'] is None:
155 slice_ids.update(system_slice_ids)
159 for slice in map(lambda id: all_slices[id], slice_ids.keys()):
161 ### still missing in foreign slices
163 for person in map(lambda id: all_persons[id], slice['person_ids']):
164 keys += [{'key_type': all_keys[key_id]['key_type'],
165 'key': all_keys[key_id]['key']} \
166 for key_id in person['key_ids']]
168 keys += [{'key_type':'missing',
169 'key':'key caching not implemented yet'}]
171 sliver_attributes = []
173 ### still missing in foreign slices
175 slice_attributes = map(lambda id: all_slice_attributes[id],
176 slice['slice_attribute_ids'])
178 # Per-node sliver attributes take precedence over
179 # global slice attributes, so set them first.
180 for sliver_attribute in filter(lambda a: a['node_id'] == node_id, slice_attributes):
181 sliver_attributes.append(sliver_attribute['name'])
182 attributes.append({'name': sliver_attribute['name'],
183 'value': sliver_attribute['value']})
185 for slice_attribute in filter(lambda a: a['node_id'] is None, slice_attributes):
186 # Do not set any global slice attributes for
187 # which there is at least one sliver attribute
189 if slice_attribute['name'] not in sliver_attributes:
190 attributes.append({'name': slice_attribute['name'],
191 'value': slice_attribute['value']})
192 except Exception, err:
193 attributes=[{'name':'attributes caching','value':'not implemented yet'}]
196 'name': slice['name'],
197 'slice_id': slice['slice_id'],
198 'instantiation': slice['instantiation'],
199 'expires': slice['expires'],
201 'attributes': attributes
205 'timestamp': timestamp,
206 'node_id': node['node_id'],
207 'hostname': node['hostname'],
208 'networks': networks,
210 'conf_files': conf_files.values(),