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']
64 def call(self, auth, node_filter = None):
65 timestamp = int(time.time())
67 if node_filter is None and isinstance(self.caller, Node):
68 all_nodes = {self.caller['node_id']: self.caller}
70 all_nodes = Nodes(self.api, node_filter).dict()
73 system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict()
74 system_slice_ids = [slice_attribute['slice_id'] for slice_attribute in system_slice_attributes.values()]
75 system_slice_ids = dict.fromkeys(system_slice_ids)
77 all_nodenetwork_ids = set()
78 all_nodegroup_ids = set()
79 all_slice_ids = set(system_slice_ids.keys())
80 for node_id, node in all_nodes.iteritems():
81 all_nodenetwork_ids.update(node['nodenetwork_ids'])
82 all_nodegroup_ids.update(node['nodegroup_ids'])
83 all_slice_ids.update(node['slice_ids'])
85 # Get nodenetwork information
86 all_nodenetworks = NodeNetworks(self.api, all_nodenetwork_ids).dict()
88 # Get node group information
89 all_nodegroups = NodeGroups(self.api, all_nodegroup_ids).dict()
91 # Get (enabled) configuration files
92 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
94 # Get slice information
95 all_slices = Slices(self.api, all_slice_ids).dict()
98 slice_attribute_ids = set()
99 for slice_id, slice in all_slices.iteritems():
100 ### still missing in foreign slices
101 if slice.get('person_ids'):
102 person_ids.update(slice['person_ids'])
103 ### still missing in foreign slices
104 if slice.get('slice_attribute_ids'):
105 slice_attribute_ids.update(slice['slice_attribute_ids'])
107 # Get user information
108 all_persons = Persons(self.api, person_ids).dict()
111 for person_id, person in all_persons.iteritems():
112 key_ids.update(person['key_ids'])
114 # Get user account keys
115 all_keys = Keys(self.api, key_ids).dict()
117 # Get slice attributes
118 all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids).dict()
121 for node_id, node in all_nodes.iteritems():
122 networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
123 nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
124 groups = [nodegroup['name'] for nodegroup in nodegroups]
126 # If multiple entries for the same global configuration
127 # file exist, it is undefined which one takes precedence.
129 for conf_file in all_conf_files.values():
130 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
131 conf_files[conf_file['dest']] = conf_file
133 # If a node belongs to multiple node
134 # groups for which the same configuration file is defined,
135 # it is undefined which one takes precedence.
136 for nodegroup in nodegroups:
137 for conf_file_id in nodegroup['conf_file_ids']:
138 if conf_file_id in all_conf_files:
139 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
141 # Node configuration files always take precedence over
142 # node group configuration files.
143 for conf_file_id in node['conf_file_ids']:
144 if conf_file_id in all_conf_files:
145 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
147 slice_ids = dict.fromkeys(node['slice_ids'])
149 # If not a foreign node, add all of our default system
151 if node['peer_id'] is not None:
152 slice_ids.update(system_slice_ids)
155 for slice in map(lambda id: all_slices[id], slice_ids.keys()):
157 ### still missing in foreign slices
159 for person in map(lambda id: all_persons[id], slice['person_ids']):
160 keys += [{'key_type': all_keys[key_id]['key_type'],
161 'key': all_keys[key_id]['key']} \
162 for key_id in person['key_ids']]
164 keys += [{'key_type':'missing',
165 'key':'key caching not implemented yet'}]
168 ### still missing in foreign slices
170 for slice_attribute in map(lambda id: all_slice_attributes[id],
171 slice['slice_attribute_ids']):
172 # Per-node sliver attributes (slice attributes
173 # with non-null node_id fields) take precedence
174 # over global slice attributes.
175 if not attributes.has_key(slice_attribute['name']) or \
176 slice_attribute['node_id'] is not None:
177 attributes[slice_attribute['name']] = {
178 'name': slice_attribute['name'],
179 'value': slice_attribute['value']
182 attributes={'ignored':{'name':'attributes caching','value':'not implemented yet'}}
185 'name': slice['name'],
186 'slice_id': slice['slice_id'],
187 'instantiation': slice['instantiation'],
188 'expires': slice['expires'],
190 'attributes': attributes.values()
194 'timestamp': timestamp,
195 'node_id': node['node_id'],
196 'hostname': node['hostname'],
197 'networks': networks,
199 'conf_files': conf_files.values(),