- fix conf_files handling
[plcapi.git] / PLC / Methods / GetSlivers.py
1 import time
2
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
15
16 class GetSlivers(Method):
17     """
18     Returns an array of structs representing slivers (slices bound to
19     nodes). If node_id_or_hostname_list is specified, only slivers
20     bound to the specified nodes are queried.
21
22     All of the information returned by this call can be gathered from
23     other calls, e.g. GetNodes, GetNodeNetworks, GetSlices, etc. This
24     function exists primarily for the benefit of Node Manager and
25     Federation Manager.
26     """
27
28     roles = ['admin', 'node']
29
30     accepts = [
31         Auth(),
32         [Mixed(Node.fields['node_id'],
33                Node.fields['hostname'])]
34         ]
35
36     returns = [{
37         'timestamp': Parameter(int, "Timestamp of this call, in seconds since UNIX epoch"),
38         'node_id': Node.fields['node_id'],
39         'hostname': Node.fields['hostname'],
40         'boot_state': Node.fields['boot_state'],
41         'networks': [NodeNetwork.fields],
42         'groups': [NodeGroup.fields['name']],
43         'conf_files': [ConfFile.fields],
44         'slivers': [{
45             'name': Slice.fields['name'],
46             'slice_id': Slice.fields['slice_id'],
47             'instantiation': Slice.fields['instantiation'],
48             'expires': Slice.fields['expires'],
49             'keys': [{
50                 'key_type': Key.fields['key_type'],
51                 'key': Key.fields['key']
52             }],
53             'attributes': [{
54                 'name': SliceAttribute.fields['name'],
55                 'value': SliceAttribute.fields['value']
56             }]
57         }]
58     }]
59
60     def call(self, auth, node_id_or_hostname_list = None):
61         timestamp = int(time.time())
62
63         all_nodes = Nodes(self.api, node_id_or_hostname_list)
64
65         nodenetwork_ids = set()
66         nodegroup_ids = set()
67         slice_ids = set()
68         for node_id, node in all_nodes.iteritems():
69             nodenetwork_ids.update(node['nodenetwork_ids'])
70             nodegroup_ids.update(node['nodegroup_ids'])
71             slice_ids.update(node['slice_ids'])
72
73         # Get nodenetwork information
74         if nodenetwork_ids:
75             all_nodenetworks = NodeNetworks(self.api, nodenetwork_ids)
76         else:
77             all_nodenetworks = {}
78
79         # Get node group information
80         if nodegroup_ids:
81             all_nodegroups = NodeGroups(self.api, nodegroup_ids)
82         else:
83             all_nodegroups = {}
84
85         # Get configuration files
86         all_conf_files = ConfFiles(self.api, enabled = True)
87
88         if slice_ids:
89             # Get slices
90             all_slices = Slices(self.api, slice_ids)
91
92             person_ids = set()
93             slice_attribute_ids = set()
94             for slice_id, slice in all_slices.iteritems():
95                 person_ids.update(slice['person_ids'])
96                 slice_attribute_ids.update(slice['slice_attribute_ids'])
97
98             # Get user accounts
99             all_persons = Persons(self.api, person_ids)
100
101             key_ids = set()
102             for person_id, person in all_persons.iteritems():
103                 key_ids.update(person['key_ids'])
104
105             # Get user account keys
106             all_keys = Keys(self.api, key_ids)
107
108             # Get slice attributes
109             all_slice_attributes = SliceAttributes(self.api, slice_attribute_ids)
110
111         nodes = []
112         for node_id, node in all_nodes.iteritems():
113             networks = [all_nodenetworks[nodenetwork_id] for nodenetwork_id in node['nodenetwork_ids']]
114             nodegroups = [all_nodegroups[nodegroup_id] for nodegroup_id in node['nodegroup_ids']]
115             groups = [nodegroup['name'] for nodegroup in nodegroups]
116             conf_files = dict([(conf_file['dest'], conf_file) for conf_file in all_conf_files.values()])
117
118             # If a node belongs to multiple node
119             # groups for which the same configuration file is defined,
120             # it is undefined which one takes precedence.
121             for nodegroup in nodegroups:
122                 for conf_file in map(lambda id: all_conf_files[id], nodegroup['conf_file_ids']):
123                     conf_files[conf_file['dest']] = conf_file
124
125             # Node configuration files always take precedence over
126             # node group configuration files.
127             for conf_file in map(lambda id: all_conf_files[id], node['conf_file_ids']):
128                 conf_files[conf_file['dest']] = conf_file
129
130             slivers = []
131             for slice in map(lambda id: all_slices[id], node['slice_ids']):
132                 keys = []
133                 for person in map(lambda id: all_persons[id], slice['person_ids']):
134                     keys += [{'key_type': all_keys[key_id]['key_type'],
135                               'key': all_keys[key_id]['key']} \
136                              for key_id in person['key_ids']]
137
138                 attributes = {}
139                 for slice_attribute in map(lambda id: all_slice_attributes[id],
140                                            slice['slice_attribute_ids']):
141                     # Per-node sliver attributes (slice attributes
142                     # with non-null node_id fields) take precedence
143                     # over global slice attributes.
144                     if not attributes.has_key(slice_attribute['name']) or \
145                        slice_attribute['node_id'] is not None:
146                         attributes[slice_attribute['name']] = {
147                             'name': slice_attribute['name'],
148                             'value': slice_attribute['value']
149                             }
150
151                 slivers.append({
152                     'name': slice['name'],
153                     'slice_id': slice['slice_id'],
154                     'instantiation': slice['instantiation'],
155                     'expires': slice['expires'],
156                     'keys': keys,
157                     'attributes': attributes.values()
158                     })
159
160             nodes.append({
161                 'timestamp': timestamp,
162                 'node_id': node['node_id'],
163                 'hostname': node['hostname'],
164                 'networks': networks,
165                 'groups': groups,
166                 'conf_files': conf_files.values(),
167                 'slivers': slivers
168                 })
169
170         return nodes