2 from sfa.util.xrn import Xrn, hrn_to_urn, urn_to_hrn, urn_to_sliver_id
3 from sfa.util.sfatime import epochparse
4 from sfa.util.sfalogging import logger
6 from sfa.rspecs.rspec import RSpec
7 from sfa.rspecs.elements.hardware_type import HardwareType
8 from sfa.rspecs.elements.node import Node
9 from sfa.rspecs.elements.link import Link
10 from sfa.rspecs.elements.sliver import Sliver
11 from sfa.rspecs.elements.login import Login
12 from sfa.rspecs.elements.location import Location
13 from sfa.rspecs.elements.interface import Interface
14 from sfa.rspecs.elements.services import Services
15 from sfa.rspecs.elements.pltag import PLTag
16 from sfa.rspecs.version_manager import VersionManager
18 from sfa.util.plxrn import PlXrn, hostname_to_urn, hrn_to_pl_slicename
19 from sfa.plc.vlink import get_tc_rate
20 from sfa.plc.topology import Topology
25 def __init__(self, driver):
27 self.user_options = {}
29 def get_sites(self, filter={}):
31 for site in self.driver.GetSites(filter):
32 sites[site['site_id']] = site
35 def get_interfaces(self, filter={}):
37 for interface in self.driver.GetInterfaces(filter):
39 if interface['bwlimit']:
40 interface['bwlimit'] = str(int(interface['bwlimit'])/1000)
41 interfaces[interface['interface_id']] = interface
44 def get_links(self, sites, nodes, interfaces):
48 for (site_id1, site_id2) in topology:
49 site_id1 = int(site_id1)
50 site_id2 = int(site_id2)
52 if not site_id1 in sites or site_id2 not in sites:
54 site1 = sites[site_id1]
55 site2 = sites[site_id2]
57 site1_hrn = self.driver.hrn + '.' + site1['login_base']
58 site2_hrn = self.driver.hrn + '.' + site2['login_base']
60 for s1_node_id in site1['node_ids']:
61 for s2_node_id in site2['node_ids']:
62 if s1_node_id not in nodes or s2_node_id not in nodes:
64 node1 = nodes[s1_node_id]
65 node2 = nodes[s2_node_id]
67 # just get first interface of the first node
68 if1_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node1['node_id']))
69 if1_ipv4 = interfaces[node1['interface_ids'][0]]['ip']
70 if2_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node2['node_id']))
71 if2_ipv4 = interfaces[node2['interface_ids'][0]]['ip']
73 if1 = Interface({'component_id': if1_xrn.urn, 'ipv4': if1_ipv4} )
74 if2 = Interface({'component_id': if2_xrn.urn, 'ipv4': if2_ipv4} )
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.driver.hrn, interface=link['component_name']).get_urn()
82 link['component_manager_id'] = hrn_to_urn(self.driver.hrn, 'authority+am')
87 def get_node_tags(self, filter={}):
89 for node_tag in self.driver.GetNodeTags(filter):
90 node_tags[node_tag['node_tag_id']] = node_tag
93 def get_pl_initscripts(self, filter={}):
95 filter.update({'enabled': True})
96 for initscript in self.driver.GetInitScripts(filter):
97 pl_initscripts[initscript['initscript_id']] = initscript
101 def get_slice_and_slivers(self, slice_xrn):
103 Returns a dict of slivers keyed on the sliver's node_id
108 return (slice, slivers)
109 slice_urn = hrn_to_urn(slice_xrn, 'slice')
110 slice_hrn, _ = urn_to_hrn(slice_xrn)
111 slice_name = hrn_to_pl_slicename(slice_hrn)
112 slices = self.driver.GetSlices(slice_name)
114 return (slice, slivers)
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',
123 slivers[node_id]= sliver
125 # sort sliver attributes by node id
126 tags = self.driver.GetSliceTags({'slice_tag_id': slice['slice_tag_ids']})
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',
133 slivers[tag['node_id']] = sliver
134 slivers[tag['node_id']]['tags'].append(tag)
136 return (slice, slivers)
138 def get_nodes_and_links(self, slice=None,slivers=[], options={}):
141 if slice and 'node_ids' in slice and slice['node_ids']:
142 filter['node_id'] = slice['node_ids']
143 tags_filter=filter.copy()
145 geni_available = options.get('geni_available')
147 filter['boot_state'] = 'boot'
149 filter.update({'peer_id': None})
150 nodes = self.driver.GetNodes(filter)
157 site_ids.append(node['site_id'])
158 interface_ids.extend(node['interface_ids'])
159 tag_ids.extend(node['node_tag_ids'])
160 nodes_dict[node['node_id']] = node
163 sites_dict = self.get_sites({'site_id': site_ids})
165 interfaces = self.get_interfaces({'interface_id':interface_ids})
167 node_tags = self.get_node_tags(tags_filter)
169 pl_initscripts = self.get_pl_initscripts()
171 links = self.get_links(sites_dict, nodes_dict, interfaces)
175 # skip whitelisted nodes
176 if node['slice_ids_whitelist']:
177 if not slice or slice['slice_id'] not in node['slice_ids_whitelist']:
180 # xxx how to retrieve site['login_base']
181 site_id=node['site_id']
182 site=sites_dict[site_id]
183 rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['login_base'], node['hostname'])
184 rspec_node['component_name'] = node['hostname']
185 rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
186 rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.driver.hrn, site['login_base']), 'authority+sa')
187 rspec_node['boot_state'] = node['boot_state']
188 rspec_node['exclusive'] = 'False'
189 rspec_node['hardware_types']= [HardwareType({'name': 'plab-pc'}),
190 HardwareType({'name': 'pc'})]
191 # only doing this because protogeni rspec needs
192 # to advertise available initscripts
193 rspec_node['pl_initscripts'] = pl_initscripts.values()
194 # add site/interface info to nodes.
195 # assumes that sites, interfaces and tags have already been prepared.
196 site = sites_dict[node['site_id']]
197 if site['longitude'] and site['latitude']:
198 location = Location({'longitude': site['longitude'], 'latitude': site['latitude']})
199 rspec_node['location'] = location
200 rspec_node['interfaces'] = []
202 for if_id in node['interface_ids']:
203 interface = Interface(interfaces[if_id])
204 interface['ipv4'] = interface['ip']
205 interface['component_id'] = PlXrn(auth=self.driver.hrn,
206 interface='node%s:eth%s' % (node['node_id'], if_count)).get_urn()
207 # interfaces in the manifest need a client id
209 interface['client_id'] = "%s:%s" % (node['node_id'], if_id)
210 rspec_node['interfaces'].append(interface)
213 tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids']]
214 rspec_node['tags'] = tags
215 if node['node_id'] in slivers:
217 sliver = slivers[node['node_id']]
218 rspec_node['sliver_id'] = sliver['sliver_id']
219 rspec_node['client_id'] = node['hostname']
220 rspec_node['slivers'] = [sliver]
222 # slivers always provide the ssh service
223 login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], 'port':'22'})
224 service = Services({'login': login})
225 rspec_node['services'] = [service]
226 rspec_nodes.append(rspec_node)
227 return (rspec_nodes, links)
230 def get_rspec(self, slice_xrn=None, version = None, options={}):
232 version_manager = VersionManager()
233 version = version_manager.get_version(version)
235 rspec_version = version_manager._get_version(version.type, version.version, 'ad')
237 rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
239 slice, slivers = self.get_slice_and_slivers(slice_xrn)
240 rspec = RSpec(version=rspec_version, user_options=options)
241 if slice and 'expires' in slice:
242 rspec.xml.set('expires', epochparse(slice['expires']))
244 nodes, links = self.get_nodes_and_links(slice, slivers)
245 rspec.version.add_nodes(nodes)
246 rspec.version.add_links(links)
248 # add sliver defaults
249 default_sliver = slivers.get(None, [])
251 default_sliver_attribs = default_sliver.get('tags', [])
252 for attrib in default_sliver_attribs:
254 rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])