cleanup
[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'] = str(int(interface['bwlimit'])/1000)
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': slice['name'],
121                              'type': 'plab-vserver', 
122                              'tags': []})
123             slivers[node_id]= sliver
124
125         # sort sliver attributes by node id    
126         tags = self.api.driver.GetSliceTags({'slice_tag_id': slice['slice_tag_ids']})
127         for tag in tags:
128             # most likely a default/global sliver attribute (node_id == None)
129             if tag['node_id'] not in slivers:
130                 sliver = Sliver({'sliver_id': urn_to_sliver_id(slice_urn, slice['slice_id'], ""),
131                                  'name': 'plab-vserver',
132                                  'tags': []})
133                 slivers[tag['node_id']] = sliver
134             slivers[tag['node_id']]['tags'].append(tag)
135         
136         return (slice, slivers)
137
138     def get_nodes (self, slice=None,slivers=[]):
139         filter = {}
140         tags_filter = {}
141         if slice and 'node_ids' in slice and slice['node_ids']:
142             filter['node_id'] = slice['node_ids']
143             tags_filter=filter.copy()
144         
145         filter.update({'peer_id': None})
146         nodes = self.api.driver.GetNodes(filter)
147        
148         site_ids = []
149         interface_ids = []
150         tag_ids = []
151         for node in nodes:
152             site_ids.append(node['site_id'])
153             interface_ids.extend(node['interface_ids'])
154             tag_ids.extend(node['node_tag_ids'])
155  
156         # get sites
157         sites_dict  = self.get_sites({'site_id': site_ids}) 
158         # get interfaces
159         interfaces = self.get_interfaces({'interface_id':interface_ids}) 
160         # get tags
161         node_tags = self.get_node_tags(tags_filter)
162         # get initscripts
163         pl_initscripts = self.get_pl_initscripts()
164
165         rspec_nodes = []
166         for node in nodes:
167             # skip whitelisted nodes
168             if node['slice_ids_whitelist']:
169                 if not slice or slice['slice_id'] not in node['slice_ids_whitelist']:
170                     continue
171             rspec_node = Node()
172             # xxx how to retrieve site['login_base']
173             site_id=node['site_id']
174             site=sites_dict[site_id]
175             rspec_node['component_id'] = hostname_to_urn(self.api.hrn, site['login_base'], node['hostname'])
176             rspec_node['component_name'] = node['hostname']
177             rspec_node['component_manager_id'] = self.api.hrn
178             rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.api.hrn, site['login_base']), 'authority+sa')
179             rspec_node['boot_state'] = node['boot_state']
180             rspec_node['exclusive'] = 'False'
181             rspec_node['hardware_types'].append(HardwareType({'name': 'plab-vserver'}))
182             # only doing this because protogeni rspec needs
183             # to advertise available initscripts 
184             rspec_node['pl_initscripts'] = pl_initscripts.values()
185              # add site/interface info to nodes.
186             # assumes that sites, interfaces and tags have already been prepared.
187             site = sites_dict[node['site_id']]
188             location = Location({'longitude': site['longitude'], 'latitude': site['latitude']})
189             rspec_node['location'] = location
190             rspec_node['interfaces'] = []
191             if_count=0
192             for if_id in node['interface_ids']:
193                 interface = Interface(interfaces[if_id]) 
194                 interface['ipv4'] = interface['ipv4']
195                 interface['component_id'] = PlXrn(auth=self.api.hrn, interface='node%s:eth%s' % (node['node_id'], if_count))
196                 rspec_node['interfaces'].append(interface)
197                 if_count+=1
198
199             tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids']]
200             rspec_node['tags'] = tags
201             if node['node_id'] in slivers:
202                 # add sliver info
203                 sliver = slivers[node['node_id']]
204                 rspec_node['sliver_id'] = sliver['sliver_id']
205                 rspec_node['client_id'] = node['hostname']
206                 rspec_node['slivers'] = [sliver]
207                 
208                 # slivers always provide the ssh service
209                 login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], port:'22'})
210                 service = Services({'login': login})
211                 rspec_node['services'].append(service)
212             rspec_nodes.append(rspec_node)
213         return rspec_nodes
214              
215         
216     def get_rspec(self, slice_xrn=None, version = None):
217
218         version_manager = VersionManager()
219         version = version_manager.get_version(version)
220         if not slice_xrn:
221             rspec_version = version_manager._get_version(version.type, version.version, 'ad')
222         else:
223             rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
224
225         slice, slivers = self.get_slice_and_slivers(slice_xrn)
226         rspec = RSpec(version=rspec_version, user_options=self.user_options)
227         if slice and 'expiration_date' in slice:
228             rspec.set('expires',  epochparse(slice['expiration_date'])) 
229         rspec.version.add_nodes(self.get_nodes(slice), slivers)
230         rspec.version.add_links(self.get_links(slice))
231         
232         # add sliver defaults
233         default_sliver_attribs = slivers.get(None, [])
234         for sliver_attrib in default_sliver_attribs:
235             rspec.version.add_default_sliver_attribute(sliver_attrib['name'], sliver_attrib['value'])  
236         
237         return rspec.toxml()
238
239