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 def get_slivers(api, slice_filter, node = None):
18 # Get slice information
19 slices = Slices(api, slice_filter)
21 # Build up list of users and slice attributes
23 slice_attribute_ids = set()
25 person_ids.update(slice['person_ids'])
26 slice_attribute_ids.update(slice['slice_attribute_ids'])
28 # Get user information
29 all_persons = Persons(api, person_ids).dict()
31 # Build up list of keys
33 for person in all_persons.values():
34 key_ids.update(person['key_ids'])
36 # Get user account keys
37 all_keys = Keys(api, key_ids).dict()
39 # Get slice attributes
40 all_slice_attributes = SliceAttributes(api, slice_attribute_ids).dict()
45 for person_id in slice['person_ids']:
46 if person_id in all_persons:
47 person = all_persons[person_id]
48 if not person['enabled']:
50 for key_id in person['key_ids']:
51 if key_id in all_keys:
52 key = all_keys[key_id]
53 keys += [{'key_type': key['key_type'],
58 # All (per-node and global) attributes for this slice
60 for slice_attribute_id in slice['slice_attribute_ids']:
61 if slice_attribute_id in all_slice_attributes:
62 slice_attributes.append(all_slice_attributes[slice_attribute_id])
64 # Per-node sliver attributes take precedence over global
65 # slice attributes, so set them first.
66 sliver_attributes = []
69 for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_attributes):
70 sliver_attributes.append(sliver_attribute['name'])
71 attributes.append({'name': sliver_attribute['name'],
72 'value': sliver_attribute['value']})
74 for slice_attribute in filter(lambda a: a['node_id'] is None, slice_attributes):
75 # Do not set any global slice attributes for
76 # which there is at least one sliver attribute
78 if slice_attribute['name'] not in sliver_attributes:
79 attributes.append({'name': slice_attribute['name'],
80 'value': slice_attribute['value']})
83 'name': slice['name'],
84 'slice_id': slice['slice_id'],
85 'instantiation': slice['instantiation'],
86 'expires': slice['expires'],
88 'attributes': attributes
93 class GetSlivers(Method):
95 Returns a struct containing information about the specified node
96 (or calling node, if called by a node and node_id_or_hostname is
97 not specified), including the current set of slivers bound to the
100 All of the information returned by this call can be gathered from
101 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
102 function exists almost solely for the benefit of Node Manager.
105 roles = ['admin', 'node']
109 Mixed(Node.fields['node_id'],
110 Node.fields['hostname']),
114 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
115 'node_id': Node.fields['node_id'],
116 'hostname': Node.fields['hostname'],
117 'networks': [NodeNetwork.fields],
118 'groups': [NodeGroup.fields['name']],
119 'conf_files': [ConfFile.fields],
121 'name': Slice.fields['name'],
122 'slice_id': Slice.fields['slice_id'],
123 'instantiation': Slice.fields['instantiation'],
124 'expires': Slice.fields['expires'],
126 'key_type': Key.fields['key_type'],
127 'key': Key.fields['key']
130 'name': SliceAttribute.fields['name'],
131 'value': SliceAttribute.fields['value']
136 def call(self, auth, node_id_or_hostname = None):
137 timestamp = int(time.time())
140 if node_id_or_hostname is None:
141 if isinstance(self.caller, Node):
144 raise PLCInvalidArgument, "'node_id_or_hostname' not specified"
146 nodes = Nodes(self.api, [node_id_or_hostname])
148 raise PLCInvalidArgument, "No such node"
151 if node['peer_id'] is not None:
152 raise PLCInvalidArgument, "Not a local node"
154 # Get nodenetwork information
155 networks = NodeNetworks(self.api, node['nodenetwork_ids'])
157 # Get node group information
158 nodegroups = NodeGroups(self.api, node['nodegroup_ids']).dict('name')
159 groups = nodegroups.keys()
161 # Get all (enabled) configuration files
162 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
165 # Global configuration files are the default. If multiple
166 # entries for the same global configuration file exist, it is
167 # undefined which one takes precedence.
168 for conf_file in all_conf_files.values():
169 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
170 conf_files[conf_file['dest']] = conf_file
172 # Node group configuration files take precedence over global
173 # ones. If a node belongs to multiple node groups for which
174 # the same configuration file is defined, it is undefined
175 # which one takes precedence.
176 for nodegroup in nodegroups.values():
177 for conf_file_id in nodegroup['conf_file_ids']:
178 if conf_file_id in all_conf_files:
179 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
181 # Node configuration files take precedence over node group
182 # configuration files.
183 for conf_file_id in node['conf_file_ids']:
184 if conf_file_id in all_conf_files:
185 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
188 system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
189 system_slice_ids = system_slice_attributes.keys()
191 slivers = get_slivers(self.api, system_slice_ids + node['slice_ids'], node)
194 'timestamp': timestamp,
195 'node_id': node['node_id'],
196 'hostname': node['hostname'],
197 'networks': networks,
199 'conf_files': conf_files.values(),