use epcohparse() to parse slice's expiration date. Set manifest rspec expiration...
[sfa.git] / sfa / plc / aggregate.py
1 #!/usr/bin/python
2 from sfa.util.xrn import hrn_to_urn, urn_to_hrn, urn_to_sliver_id
3 from sfa.util.plxrn import PlXrn, hostname_to_urn, hrn_to_pl_slicename
4
5 from sfa.rspecs.rspec import RSpec
6 from sfa.rspecs.elements.hardware_type import HardwareType
7 from sfa.rspecs.elements.node import Node
8 from sfa.rspecs.elements.link import Link
9 from sfa.rspecs.elements.login import Login
10 from sfa.rspecs.elements.location import Location
11 from sfa.rspecs.elements.interface import Interface
12 from sfa.rspecs.elements.services import Services
13 from sfa.rspecs.elements.pltag import PLTag
14 from sfa.util.topology import Topology
15 from sfa.rspecs.version_manager import VersionManager
16 from sfa.plc.vlink import get_tc_rate
17 from sfa.util.sfatime import epochparse
18
19 class Aggregate:
20
21     api = None
22     #panos new user options variable
23     user_options = {}
24
25     def __init__(self, api, user_options={}):
26         self.api = api
27         self.user_options = user_options
28
29     def get_sites(self, filter={}):
30         sites = {}
31         for site in self.api.driver.GetSites(filter):
32             sites[site['site_id']] = site
33         return sites
34
35     def get_interfaces(self, filter={}):
36         interfaces = {}
37         for interface in self.api.driver.GetInterfaces(filter):
38             iface = Interface()
39             iface['interface_id'] = interface['interface_id']
40             iface['node_id'] = interface['node_id']
41             iface['ipv4'] = interface['ip']
42             iface['bwlimit'] = interface['bwlimit']
43             interfaces[iface['interface_id']] = iface
44         return interfaces
45
46     def get_links(self, filter={}):
47         
48         if not self.api.config.SFA_AGGREGATE_TYPE.lower() == 'vini':
49             return []
50
51         topology = Topology() 
52         links = {}
53         for (site_id1, site_id2) in topology:
54             link = Link()
55             if not site_id1 in self.sites or site_id2 not in self.sites:
56                 continue
57             site1 = self.sites[site_id1]
58             site2 = self.sites[site_id2]
59             # get hrns
60             site1_hrn = self.api.hrn + '.' + site1['login_base']
61             site2_hrn = self.api.hrn + '.' + site2['login_base']
62             # get the first node
63             node1 = self.nodes[site1['node_ids'][0]]
64             node2 = self.nodes[site2['node_ids'][0]]
65
66             # set interfaces
67             # just get first interface of the first node
68             if1_xrn = PlXrn(auth=self.api.hrn, interface='node%s:eth0' % (node1['node_id']))
69             if1_ipv4 = self.interfaces[node1['interface_ids'][0]]['ip']
70             if2_xrn = PlXrn(auth=self.api.hrn, interface='node%s:eth0' % (node2['node_id']))
71             if2_ipv4 = self.interfaces[node2['interface_ids'][0]]['ip']
72
73             if1 = Interface({'component_id': if1_xrn.urn, 'ipv4': if1_ipv4} )
74             if2 = Interface({'component_id': if2_xrn.urn, 'ipv4': if2_ipv4} )
75
76             # set link
77             link = Link({'capacity': '1000000', 'latency': '0', 'packet_loss': '0', 'type': 'ipv4'})
78             link['interface1'] = if1
79             link['interface2'] = if2
80             link['component_name'] = "%s:%s" % (site1['login_base'], site2['login_base'])
81             link['component_id'] = PlXrn(auth=self.api.hrn, interface=link['component_name']).get_urn()
82             link['component_manager_id'] =  hrn_to_urn(self.api.hrn, 'authority+am')
83             links[link['component_name']] = link
84
85         return links
86
87     def get_node_tags(self, filter={}):
88         node_tags = {}
89         for node_tag in self.api.driver.GetNodeTags(filter):
90             node_tags[node_tag['node_tag_id']] = node_tag
91         return node_tags
92
93     def get_pl_initscripts(self, filter={}):
94         pl_initscripts = {}
95         filter.update({'enabled': True})
96         for initscript in self.api.driver.GetInitScripts(filter):
97             pl_initscripts[initscript['initscript_id']] = initscript
98         return pl_initscripts
99
100
101     def get_slice_and_slivers(self, slice_xrn):
102         """
103         Returns a dict of slivers keyed on the sliver's node_id
104         """
105         slivers = {}
106         slice = None
107         if not slice_xrn:
108             return (slice, slivers)
109         slice_urn = hrn_to_urn(slice_xrn)
110         slice_hrn, _ = urn_to_hrn(slice_xrn)
111         slice_name = hrn_to_pl_slicename(slice_hrn)
112         slices = self.api.driver.GetSlices(slice_name)
113         if not slices:
114             return (slice, slivers)
115         slice = slices[0]
116
117         # sort slivers by node id    
118         for node_id in slice['node_ids']:
119             sliver = Sliver({'sliver_id': urn_to_sliver_id(slice_urn, slice['slice_id'], node_id),
120                              'name': 'plab-vserver', 
121                              'tags': []})
122             slivers[node_id]= sliver
123
124         # sort sliver attributes by node id    
125         tags = self.api.driver.GetSliceTags({'slice_tag_id': slice['slice_tag_ids']})
126         for tag in tags:
127             # most likely a default/global sliver attribute (node_id == None)
128             if tag['node_id'] not in slivers:
129                 sliver = Sliver({'sliver_id': urn_to_sliver_id(slice_urn, slice['slice_id'], ""),
130                                  'name': 'plab-vserver',
131                                  'tags': []})
132                 slivers[tag['node_id']] = sliver
133             slivers[tag['node_id']]['tags'].append(tag)
134         
135         return (slice, slivers)
136
137     def get_nodes (self, slice=None,slivers=[]):
138         filter = {}
139         tags_filter = {}
140         if slice and 'node_ids' in slice and slice['node_ids']:
141             filter['node_id'] = slice['node_ids']
142             tags_filter=filter.copy()
143         
144         filter.update({'peer_id': None})
145         nodes = self.api.driver.GetNodes(filter)
146        
147         site_ids = []
148         interface_ids = []
149         tag_ids = []
150         for node in nodes:
151             site_ids.append(node['site_id'])
152             interface_ids.extend(node['interface_ids'])
153             tag_ids.extend(node['node_tag_ids'])
154  
155         # get sites
156         sites_dict  = self.get_sites({'site_id': site_ids}) 
157         # get interfaces
158         interfaces = self.get_interfaces({'interface_id':interface_ids}) 
159         # get slivers
160         # 
161         # thierry: no get_slivers, we have slivers as a result of
162         # get_slice_and_slivers passed as an argument
163         # 
164 #        slivers = self.get_slivers(slice)
165
166         # get tags
167         node_tags = self.get_node_tags(tags_filter)
168         # get initscripts
169         pl_initscripts = self.get_pl_initscripts()
170
171         rspec_nodes = []
172         for node in nodes:
173             # skip whitelisted nodes
174             if node['slice_ids_whitelist']:
175                 if not slice or slice['slice_id'] not in node['slice_ids_whitelist']:
176                     continue
177             rspec_node = Node()
178             # xxx how to retrieve site['login_base']
179             site_id=node['site_id']
180             site=sites_dict[site_id]
181             rspec_node['component_id'] = hostname_to_urn(self.api.hrn, site['login_base'], node['hostname'])
182             rspec_node['component_name'] = node['hostname']
183             rspec_node['component_manager_id'] = self.api.hrn
184             rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.api.hrn, site['login_base']), 'authority+sa')
185             rspec_node['boot_state'] = node['boot_state']
186             rspec_node['exclusive'] = 'False'
187             rspec_node['hardware_types'].append(HardwareType({'name': 'plab-vserver'}))
188             # only doing this because protogeni rspec needs
189             # to advertise available initscripts 
190             rspec_node['pl_initscripts'] = pl_initscripts
191              # add site/interface info to nodes.
192             # assumes that sites, interfaces and tags have already been prepared.
193             site = sites_dict[node['site_id']]
194             location = Location({'longitude': site['longitude'], 'latitude': site['latitude']})
195             rspec_node['location'] = location
196             rspec_node['interfaces'] = []
197             for if_id in node['interface_ids']:
198                 interface = Interface(interfaces[if_id]) 
199                 interface['ipv4'] = interface['ipv4']
200                 rspec_node['interfaces'].append(interface)
201             tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids']]
202             rspec_node['tags'] = tags
203             if node['node_id'] in slivers:
204                 # add sliver info
205                 sliver = slivers[node['node_id']]
206                 rspec_node['sliver_id'] = sliver['sliver_id']
207                 rspec_node['client_id'] = node['hostname']
208                 rspec_node['slivers'] = [slivers[node['node_id']]]
209                 
210                 # slivers always provide the ssh service
211                 login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], port:'22'})
212                 service = Services({'login': login})
213                 rspec_node['services'].append(service)
214             rspec_nodes.append(rspec_node)
215         return rspec_nodes
216              
217         
218     def get_rspec(self, slice_xrn=None, version = None):
219
220         version_manager = VersionManager()
221         version = version_manager.get_version(version)
222         if not slice_xrn:
223             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
224         else:
225             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
226
227         slice, slivers = self.get_slice_and_slivers(slice_xrn)
228         rspec = RSpec(version=rspec_version, user_options=self.user_options)
229         if slice and 'expiration_date' in slice:
230             rspec.set('expires',  epochparse(slice['expiration_date'])) 
231         rspec.version.add_nodes(self.get_nodes(slice), slivers)
232         rspec.version.add_links(self.get_links(slice))
233         
234         # add sliver defaults
235         default_sliver_attribs = slivers.get(None, [])
236         for sliver_attrib in default_sliver_attribs:
237             rspec.version.add_default_sliver_attribute(sliver_attrib['name'], sliver_attrib['value'])  
238         
239         return rspec.toxml()
240
241