3 from PLC.Faults import *
4 from PLC.Method import Method
5 from PLC.Parameter import Parameter, Mixed
6 from PLC.Auth import Auth
7 from PLC.Nodes import Node, Nodes
8 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
9 from PLC.NodeGroups import NodeGroup, NodeGroups
10 from PLC.ConfFiles import ConfFile, ConfFiles
11 from PLC.Slices import Slice, Slices
12 from PLC.Persons import Person, Persons
13 from PLC.Keys import Key, Keys
14 from PLC.SliceAttributes import SliceAttribute, SliceAttributes
16 class GetSlivers(Method):
18 Returns an array of structs representing nodes and their slivers
19 (slices bound to nodes). If node_hostnames is specified, only
20 information about the specified nodes will be returned. If not
21 specified and called by a node, only information about the caller
24 All of the information returned by this call can be gathered from
25 other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
26 function exists primarily for the benefit of Node Manager and
30 roles = ['admin', 'node']
34 [Mixed(Node.fields['node_id'],
35 Node.fields['hostname'])]
39 'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
40 'node_id': Node.fields['node_id'],
41 'hostname': Node.fields['hostname'],
42 'boot_state': Node.fields['boot_state'],
43 'networks': [NodeNetwork.fields],
44 'groups': [NodeGroup.fields['name']],
45 'conf_files': [ConfFile.fields],
47 'name': Slice.fields['name'],
48 'slice_id': Slice.fields['slice_id'],
49 'instantiation': Slice.fields['instantiation'],
50 'expires': Slice.fields['expires'],
52 'key_type': Key.fields['key_type'],
53 'key': Key.fields['key']
56 'name': SliceAttribute.fields['name'],
57 'value': SliceAttribute.fields['value']
62 def call(self, auth, node_id_or_hostname_list = None):
63 timestamp = int(time.time())
65 if node_id_or_hostname_list is None and isinstance(self.caller, Node):
66 all_nodes = {self.caller['node_id']: self.caller}
68 all_nodes = Nodes(self.api, node_id_or_hostname_list)
69 # XXX Add foreign nodes
71 nodenetwork_ids = set()
74 for node_id, node in all_nodes.iteritems():
75 nodenetwork_ids.update(node['nodenetwork_ids'])
76 nodegroup_ids.update(node['nodegroup_ids'])
77 slice_ids.update(node['slice_ids'])
79 # Get nodenetwork information
81 all_nodenetworks = NodeNetworks(self.api, nodenetwork_ids)
85 # Get node group information
87 all_nodegroups = NodeGroups(self.api, nodegroup_ids)
91 # Get configuration files
92 all_conf_files = ConfFiles(self.api, {'enabled': True})
96 all_slices = Slices(self.api, slice_ids)
99 slice_attribute_ids = set()
100 for slice_id, slice in all_slices.iteritems():
101 person_ids.update(slice['person_ids'])
102 slice_attribute_ids.update(slice['slice_attribute_ids'])
105 all_persons = Persons(self.api, person_ids)
108 for person_id, person in all_persons.iteritems():
109 key_ids.update(person['key_ids'])
111 # Get user account keys
112 all_keys = Keys(self.api, key_ids)
114 # Get slice attributes
115 all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids)
118 for node_id, node in all_nodes.iteritems():
119 networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
120 nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
121 groups = [nodegroup['name'] for nodegroup in nodegroups]
122 conf_files = dict([(conf_file['dest'], conf_file) for conf_file in all_conf_files.values()])
124 # If a node belongs to multiple node
125 # groups for which the same configuration file is defined,
126 # it is undefined which one takes precedence.
127 for nodegroup in nodegroups:
128 for conf_file in map(lambda id: all_conf_files[id], nodegroup['conf_file_ids']):
129 conf_files[conf_file['dest']] = conf_file
131 # Node configuration files always take precedence over
132 # node group configuration files.
133 for conf_file in map(lambda id: all_conf_files[id], node['conf_file_ids']):
134 conf_files[conf_file['dest']] = conf_file
137 for slice in map(lambda id: all_slices[id], node['slice_ids']):
139 for person in map(lambda id: all_persons[id], slice['person_ids']):
140 keys += [{'key_type': all_keys[key_id]['key_type'],
141 'key': all_keys[key_id]['key']} \
142 for key_id in person['key_ids']]
145 for slice_attribute in map(lambda id: all_slice_attributes[id],
146 slice['slice_attribute_ids']):
147 # Per-node sliver attributes (slice attributes
148 # with non-null node_id fields) take precedence
149 # over global slice attributes.
150 if not attributes.has_key(slice_attribute['name']) or \
151 slice_attribute['node_id'] is not None:
152 attributes[slice_attribute['name']] = {
153 'name': slice_attribute['name'],
154 'value': slice_attribute['value']
158 'name': slice['name'],
159 'slice_id': slice['slice_id'],
160 'instantiation': slice['instantiation'],
161 'expires': slice['expires'],
163 'attributes': attributes.values()
167 'timestamp': timestamp,
168 'node_id': node['node_id'],
169 'hostname': node['hostname'],
170 'networks': networks,
172 'conf_files': conf_files.values(),