4 from PLC.Faults import *
5 from PLC.Method import Method
6 from PLC.Parameter import Parameter, Mixed
7 from PLC.Filter import Filter
8 from PLC.Auth import Auth
9 from PLC.Nodes import Node, Nodes
10 from PLC.Interfaces import Interface, Interfaces
11 from PLC.NodeGroups import NodeGroup, NodeGroups
12 from PLC.ConfFiles import ConfFile, ConfFiles
13 from PLC.Slices import Slice, Slices
14 from PLC.Persons import Person, Persons
15 from PLC.Keys import Key, Keys
16 from PLC.SliceTags import SliceTag, SliceTags
17 from PLC.InitScripts import InitScript, InitScripts
19 def get_slivers(api, slice_filter, node = None):
20 # Get slice information
21 slices = Slices(api, slice_filter, ['slice_id', 'name', 'instantiation', 'expires', 'person_ids', 'slice_tag_ids'])
23 # Build up list of users and slice attributes
27 person_ids.update(slice['person_ids'])
28 slice_tag_ids.update(slice['slice_tag_ids'])
30 # Get user information
31 all_persons = Persons(api, {'person_id':person_ids,'enabled':True}, ['person_id', 'enabled', 'key_ids']).dict()
33 # Build up list of keys
35 for person in all_persons.values():
36 key_ids.update(person['key_ids'])
38 # Get user account keys
39 all_keys = Keys(api, key_ids, ['key_id', 'key', 'key_type']).dict()
41 # Get slice attributes
42 all_slice_tags = SliceTags(api, slice_tag_ids).dict()
47 for person_id in slice['person_ids']:
48 if person_id in all_persons:
49 person = all_persons[person_id]
50 if not person['enabled']:
52 for key_id in person['key_ids']:
53 if key_id in all_keys:
54 key = all_keys[key_id]
55 keys += [{'key_type': key['key_type'],
60 # All (per-node and global) attributes for this slice
62 for slice_tag_id in slice['slice_tag_ids']:
63 if slice_tag_id in all_slice_tags:
64 slice_tags.append(all_slice_tags[slice_tag_id])
66 # Per-node sliver attributes take precedence over global
67 # slice attributes, so set them first.
68 # Then comes nodegroup slice attributes
69 # Followed by global slice attributes
70 sliver_attributes = []
73 for sliver_attribute in filter(lambda a: a['node_id'] == node['node_id'], slice_tags):
74 sliver_attributes.append(sliver_attribute['tagname'])
75 attributes.append({'tagname': sliver_attribute['tagname'],
76 'value': sliver_attribute['value']})
78 # set nodegroup slice attributes
79 for slice_tag in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_tags):
80 # Do not set any nodegroup slice attributes for
81 # which there is at least one sliver attribute
83 if slice_tag['tagname'] not in slice_tags:
84 attributes.append({'tagname': slice_tag['tagname'],
85 'value': slice_tag['value']})
87 for slice_tag in filter(lambda a: a['node_id'] is None, slice_tags):
88 # Do not set any global slice attributes for
89 # which there is at least one sliver attribute
91 if slice_tag['tagname'] not in sliver_attributes:
92 attributes.append({'tagname': slice_tag['tagname'],
93 'value': slice_tag['value']})
96 'name': slice['name'],
97 'slice_id': slice['slice_id'],
98 'instantiation': slice['instantiation'],
99 'expires': slice['expires'],
101 'attributes': attributes
106 class GetSlivers(Method):
108 Returns a struct containing information about the specified node
109 (or calling node, if called by a node and node_id_or_hostname is
110 not specified), including the current set of slivers bound to the
113 All of the information returned by this call can be gathered from
114 other calls, e.g. GetNodes, GetInterfaces, GetSlices, etc. This
115 function exists almost solely for the benefit of Node Manager.
118 roles = ['admin', 'node']
122 Mixed(Node.fields['node_id'],
123 Node.fields['hostname']),
127 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
128 'node_id': Node.fields['node_id'],
129 'hostname': Node.fields['hostname'],
130 'networks': [Interface.fields],
131 'groups': [NodeGroup.fields['groupname']],
132 'conf_files': [ConfFile.fields],
133 'initscripts': [InitScript.fields],
135 'name': Slice.fields['name'],
136 'slice_id': Slice.fields['slice_id'],
137 'instantiation': Slice.fields['instantiation'],
138 'expires': Slice.fields['expires'],
140 'key_type': Key.fields['key_type'],
141 'key': Key.fields['key']
144 'tagname': SliceTag.fields['tagname'],
145 'value': SliceTag.fields['value']
150 def call(self, auth, node_id_or_hostname = None):
151 timestamp = int(time.time())
154 if node_id_or_hostname is None:
155 if isinstance(self.caller, Node):
158 raise PLCInvalidArgument, "'node_id_or_hostname' not specified"
160 nodes = Nodes(self.api, [node_id_or_hostname])
162 raise PLCInvalidArgument, "No such node"
165 if node['peer_id'] is not None:
166 raise PLCInvalidArgument, "Not a local node"
168 # Get interface information
169 networks = Interfaces(self.api, node['interface_ids'])
171 # Get node group information
172 nodegroups = NodeGroups(self.api, node['nodegroup_ids']).dict('groupname')
173 groups = nodegroups.keys()
175 # Get all (enabled) configuration files
176 all_conf_files = ConfFiles(self.api, {'enabled': True}).dict()
179 # Global configuration files are the default. If multiple
180 # entries for the same global configuration file exist, it is
181 # undefined which one takes precedence.
182 for conf_file in all_conf_files.values():
183 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
184 conf_files[conf_file['dest']] = conf_file
186 # Node group configuration files take precedence over global
187 # ones. If a node belongs to multiple node groups for which
188 # the same configuration file is defined, it is undefined
189 # which one takes precedence.
190 for nodegroup in nodegroups.values():
191 for conf_file_id in nodegroup['conf_file_ids']:
192 if conf_file_id in all_conf_files:
193 conf_file = all_conf_files[conf_file_id]
194 conf_files[conf_file['dest']] = conf_file
196 # Node configuration files take precedence over node group
197 # configuration files.
198 for conf_file_id in node['conf_file_ids']:
199 if conf_file_id in all_conf_files:
200 conf_file = all_conf_files[conf_file_id]
201 conf_files[conf_file['dest']] = conf_file
203 # Get all (enabled) initscripts
204 initscripts = InitScripts(self.api, {'enabled': True})
207 system_slice_tags = SliceTags(self.api, {'tagname': 'system', 'value': '1'}).dict('slice_id')
208 system_slice_ids = system_slice_tags.keys()
210 # Get nm-controller slices
211 controller_and_delegated_slices = Slices(self.api, {'instantiation': ['nm-controller', 'delegated']}, ['slice_id']).dict('slice_id')
212 controller_and_delegated_slice_ids = controller_and_delegated_slices.keys()
213 slice_ids = system_slice_ids + controller_and_delegated_slice_ids + node['slice_ids']
215 slivers = get_slivers(self.api, slice_ids, node)
217 node.update_last_contact()
220 'timestamp': timestamp,
221 'node_id': node['node_id'],
222 'hostname': node['hostname'],
223 'networks': networks,
225 'conf_files': conf_files.values(),
226 'initscripts': initscripts,