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