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 hashref(rows, key_field):
20 d[row[key_field]] = row
23 class GetSlivers(Method):
25 Returns an array of structs representing nodes and their slivers
26 (slices bound to nodes). If node_filter is specified, only
27 information about the specified nodes will be returned. If
28 node_filter is not specified and called by a node, only
29 information about the caller will be returned.
31 All of the information returned by this call can be gathered from
32 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
33 function exists primarily for the benefit of Node Manager and
37 roles = ['admin', 'node']
41 Mixed([Mixed(Node.fields['node_id'],
42 Node.fields['hostname'])],
47 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
48 'node_id': Node.fields['node_id'],
49 'hostname': Node.fields['hostname'],
50 'networks': [NodeNetwork.fields],
51 'groups': [NodeGroup.fields['name']],
52 'conf_files': [ConfFile.fields],
54 'name': Slice.fields['name'],
55 'slice_id': Slice.fields['slice_id'],
56 'instantiation': Slice.fields['instantiation'],
57 'expires': Slice.fields['expires'],
59 'key_type': Key.fields['key_type'],
60 'key': Key.fields['key']
63 'name': SliceAttribute.fields['name'],
64 'value': SliceAttribute.fields['value']
69 def call(self, auth, node_filter = None):
70 timestamp = int(time.time())
72 if node_filter is None and isinstance(self.caller, Node):
73 all_nodes = {self.caller['node_id']: self.caller}
75 all_nodes = hashref(Nodes(self.api, node_filter), 'node_id')
76 # XXX Add foreign nodes
78 nodenetwork_ids = set()
81 for node_id, node in all_nodes.iteritems():
82 nodenetwork_ids.update(node['nodenetwork_ids'])
83 nodegroup_ids.update(node['nodegroup_ids'])
84 slice_ids.update(node['slice_ids'])
86 # Get nodenetwork information
87 all_nodenetworks = hashref(NodeNetworks(self.api, nodenetwork_ids), 'nodenetwork_id')
89 # Get node group information
90 all_nodegroups = hashref(NodeGroups(self.api, nodegroup_ids), 'nodegroup_id')
92 # Get (enabled) configuration files
93 all_conf_files = hashref(ConfFiles(self.api, {'enabled': True}), 'conf_file_id')
97 all_slices = hashref(Slices(self.api, slice_ids), 'slice_id')
100 slice_attribute_ids = set()
101 for slice_id, slice in all_slices.iteritems():
102 person_ids.update(slice['person_ids'])
103 slice_attribute_ids.update(slice['slice_attribute_ids'])
106 all_persons = hashref(Persons(self.api, person_ids), 'person_id')
109 for person_id, person in all_persons.iteritems():
110 key_ids.update(person['key_ids'])
112 # Get user account keys
113 all_keys = hashref(Keys(self.api, key_ids), 'key_id')
115 # Get slice attributes
116 all_slice_attributes = hashref(SliceAttributes(self.api, slice_attribute_ids), 'slice_attribute_id')
119 for node_id, node in all_nodes.iteritems():
120 networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
121 nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
122 groups = [nodegroup['name'] for nodegroup in nodegroups]
124 # If multiple entries for the same global configuration
125 # file exist, it is undefined which one takes precedence.
127 for conf_file in all_conf_files.values():
128 if not conf_file['node_ids'] and not conf_file['nodegroup_ids']:
129 conf_files[conf_file['dest']] = conf_file
131 # If a node belongs to multiple node
132 # groups for which the same configuration file is defined,
133 # it is undefined which one takes precedence.
134 for nodegroup in nodegroups:
135 for conf_file_id in nodegroup['conf_file_ids']:
136 if conf_file_id in all_conf_files:
137 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
139 # Node configuration files always take precedence over
140 # node group configuration files.
141 for conf_file_id in node['conf_file_ids']:
142 if conf_file_id in all_conf_files:
143 conf_files[conf_file['dest']] = all_conf_files[conf_file_id]
146 for slice in map(lambda id: all_slices[id], node['slice_ids']):
148 for person in map(lambda id: all_persons[id], slice['person_ids']):
149 keys += [{'key_type': all_keys[key_id]['key_type'],
150 'key': all_keys[key_id]['key']} \
151 for key_id in person['key_ids']]
154 for slice_attribute in map(lambda id: all_slice_attributes[id],
155 slice['slice_attribute_ids']):
156 # Per-node sliver attributes (slice attributes
157 # with non-null node_id fields) take precedence
158 # over global slice attributes.
159 if not attributes.has_key(slice_attribute['name']) or \
160 slice_attribute['node_id'] is not None:
161 attributes[slice_attribute['name']] = {
162 'name': slice_attribute['name'],
163 'value': slice_attribute['value']
167 'name': slice['name'],
168 'slice_id': slice['slice_id'],
169 'instantiation': slice['instantiation'],
170 'expires': slice['expires'],
172 'attributes': attributes.values()
176 'timestamp': timestamp,
177 'node_id': node['node_id'],
178 'hostname': node['hostname'],
179 'networks': networks,
181 'conf_files': conf_files.values(),