2 from sfa.util.xrn import Xrn, hrn_to_urn, urn_to_hrn, urn_to_sliver_id
3 from sfa.util.sfatime import utcparse, datetime_to_string
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):
28 def get_sites(self, filter={}):
30 for site in self.driver.shell.GetSites(filter):
31 sites[site['site_id']] = site
34 def get_interfaces(self, filter={}):
36 for interface in self.driver.shell.GetInterfaces(filter):
38 if interface['bwlimit']:
39 interface['bwlimit'] = str(int(interface['bwlimit'])/1000)
40 interfaces[interface['interface_id']] = interface
43 def get_links(self, sites, nodes, interfaces):
47 for (site_id1, site_id2) in topology:
48 site_id1 = int(site_id1)
49 site_id2 = int(site_id2)
51 if not site_id1 in sites or site_id2 not in sites:
53 site1 = sites[site_id1]
54 site2 = sites[site_id2]
56 site1_hrn = self.driver.hrn + '.' + site1['login_base']
57 site2_hrn = self.driver.hrn + '.' + site2['login_base']
59 for s1_node_id in site1['node_ids']:
60 for s2_node_id in site2['node_ids']:
61 if s1_node_id not in nodes or s2_node_id not in nodes:
63 node1 = nodes[s1_node_id]
64 node2 = nodes[s2_node_id]
66 # just get first interface of the first node
67 if1_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node1['node_id']))
68 if1_ipv4 = interfaces[node1['interface_ids'][0]]['ip']
69 if2_xrn = PlXrn(auth=self.driver.hrn, interface='node%s:eth0' % (node2['node_id']))
70 if2_ipv4 = interfaces[node2['interface_ids'][0]]['ip']
72 if1 = Interface({'component_id': if1_xrn.urn, 'ipv4': if1_ipv4} )
73 if2 = Interface({'component_id': if2_xrn.urn, 'ipv4': if2_ipv4} )
76 link = Link({'capacity': '1000000', 'latency': '0', 'packet_loss': '0', 'type': 'ipv4'})
77 link['interface1'] = if1
78 link['interface2'] = if2
79 link['component_name'] = "%s:%s" % (site1['login_base'], site2['login_base'])
80 link['component_id'] = PlXrn(auth=self.driver.hrn, interface=link['component_name']).get_urn()
81 link['component_manager_id'] = hrn_to_urn(self.driver.hrn, 'authority+am')
86 def get_node_tags(self, filter={}):
88 for node_tag in self.driver.shell.GetNodeTags(filter):
89 node_tags[node_tag['node_tag_id']] = node_tag
92 def get_pl_initscripts(self, filter={}):
94 filter.update({'enabled': True})
95 for initscript in self.driver.shell.GetInitScripts(filter):
96 pl_initscripts[initscript['initscript_id']] = initscript
100 def get_slice_and_slivers(self, slice_xrn):
102 Returns a dict of slivers keyed on the sliver's node_id
107 return (slice, slivers)
108 slice_urn = hrn_to_urn(slice_xrn, 'slice')
109 slice_hrn, _ = urn_to_hrn(slice_xrn)
110 slice_name = hrn_to_pl_slicename(slice_hrn)
111 slices = self.driver.shell.GetSlices(slice_name)
113 return (slice, slivers)
116 # sort slivers by node id
117 for node_id in slice['node_ids']:
118 sliver = Sliver({'sliver_id': urn_to_sliver_id(slice_urn, slice['slice_id'], node_id),
119 'name': slice['name'],
120 'type': 'plab-vserver',
122 slivers[node_id]= sliver
124 # sort sliver attributes by node id
125 tags = self.driver.shell.GetSliceTags({'slice_tag_id': slice['slice_tag_ids']})
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': slice['name'],
131 'type': '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_xrn, slice=None,slivers=[], options={}):
139 # if we are dealing with a slice that has no node just return
142 if not slice or not slice['node_ids']:
147 if slice and 'node_ids' in slice and slice['node_ids']:
148 filter['node_id'] = slice['node_ids']
149 tags_filter=filter.copy()
151 geni_available = options.get('geni_available')
153 filter['boot_state'] = 'boot'
155 filter.update({'peer_id': None})
156 nodes = self.driver.shell.GetNodes(filter)
163 site_ids.append(node['site_id'])
164 interface_ids.extend(node['interface_ids'])
165 tag_ids.extend(node['node_tag_ids'])
166 nodes_dict[node['node_id']] = node
169 sites_dict = self.get_sites({'site_id': site_ids})
171 interfaces = self.get_interfaces({'interface_id':interface_ids})
173 node_tags = self.get_node_tags(tags_filter)
175 pl_initscripts = self.get_pl_initscripts()
177 links = self.get_links(sites_dict, nodes_dict, interfaces)
181 # skip whitelisted nodes
182 if node['slice_ids_whitelist']:
183 if not slice or slice['slice_id'] not in node['slice_ids_whitelist']:
186 # xxx how to retrieve site['login_base']
187 site_id=node['site_id']
188 site=sites_dict[site_id]
189 rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['login_base'], node['hostname'])
190 rspec_node['component_name'] = node['hostname']
191 rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
192 rspec_node['authority_id'] = hrn_to_urn(PlXrn.site_hrn(self.driver.hrn, site['login_base']), 'authority+sa')
193 # do not include boot state (<available> element) in the manifest rspec
195 rspec_node['boot_state'] = node['boot_state']
196 rspec_node['exclusive'] = 'false'
197 rspec_node['hardware_types'] = [HardwareType({'name': 'plab-pc'}),
198 HardwareType({'name': 'pc'})]
199 # only doing this because protogeni rspec needs
200 # to advertise available initscripts
201 rspec_node['pl_initscripts'] = pl_initscripts.values()
202 # add site/interface info to nodes.
203 # assumes that sites, interfaces and tags have already been prepared.
204 site = sites_dict[node['site_id']]
205 if site['longitude'] and site['latitude']:
206 location = Location({'longitude': site['longitude'], 'latitude': site['latitude'], 'country': 'unknown'})
207 rspec_node['location'] = location
208 rspec_node['interfaces'] = []
210 for if_id in node['interface_ids']:
211 interface = Interface(interfaces[if_id])
212 interface['ipv4'] = interface['ip']
213 interface['component_id'] = PlXrn(auth=self.driver.hrn,
214 interface='node%s:eth%s' % (node['node_id'], if_count)).get_urn()
215 # interfaces in the manifest need a client id
217 interface['client_id'] = "%s:%s" % (node['node_id'], if_id)
218 rspec_node['interfaces'].append(interface)
221 tags = [PLTag(node_tags[tag_id]) for tag_id in node['node_tag_ids']]
222 rspec_node['tags'] = tags
223 if node['node_id'] in slivers:
225 sliver = slivers[node['node_id']]
226 rspec_node['sliver_id'] = sliver['sliver_id']
227 rspec_node['client_id'] = node['hostname']
228 rspec_node['slivers'] = [sliver]
230 # slivers always provide the ssh service
231 login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], 'port':'22', 'username': sliver['name']})
232 service = Services({'login': login})
233 rspec_node['services'] = [service]
234 rspec_nodes.append(rspec_node)
235 return (rspec_nodes, links)
238 def get_rspec(self, slice_xrn=None, version = None, options={}):
240 version_manager = VersionManager()
241 version = version_manager.get_version(version)
243 rspec_version = version_manager._get_version(version.type, version.version, 'ad')
245 rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
247 slice, slivers = self.get_slice_and_slivers(slice_xrn)
248 rspec = RSpec(version=rspec_version, user_options=options)
249 if slice and 'expires' in slice:
250 rspec.xml.set('expires', datetime_to_string(utcparse(slice['expires'])))
252 nodes, links = self.get_nodes_and_links(slice_xrn, slice, slivers)
253 rspec.version.add_nodes(nodes)
254 rspec.version.add_links(links)
256 # add sliver defaults
257 default_sliver = slivers.get(None, [])
259 default_sliver_attribs = default_sliver.get('tags', [])
260 for attrib in default_sliver_attribs:
262 rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])