2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License version 2 as
7 # published by the Free Software Foundation;
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from nepi.util.logger import Logger
20 from sfa.rspecs.rspec import RSpec
21 from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
23 log = Logger("SFA RSpec Processing")
24 log.debug("Package sfa-common not installed.\
25 Could not import sfa.rspecs.rspec and sfa.util.xrn")
27 from six import string_types
30 class SfaRSpecProcessing(object):
32 Class to process SFA RSpecs, parse the RSpec replies such as Advertisement RSpecs,
33 and build in the case of Request RSpecs.
35 def __init__(self, config=None):
36 self._log = Logger("SFA RSpec Processing")
39 def make_dict_rec(self, obj):
40 if not obj or isinstance(obj, (bool,) + string_types):
42 if isinstance(obj, list):
45 objcopy.append(self.make_dict_rec(x))
47 # We thus suppose we have a child of dict
49 for k, v in obj.items():
50 objcopy[k] = self.make_dict_rec(v)
53 def parse_sfa_rspec(self, rspec_string):
55 Parse the RSpec XML as a string.
57 # rspec_type and rspec_version should be set in the config of the platform,
58 # we use GENIv3 as default one if not
60 if 'rspec_type' and 'rspec_version' in self.config:
61 rspec_version = self.config['rspec_type'] + ' ' + self.config['rspec_version']
63 rspec_version = 'GENI 3'
64 self._log.debug(rspec_version)
65 rspec = RSpec(rspec_string, version=rspec_version)
68 nodes = rspec.version.get_nodes()
69 except Exception as e:
70 self._log.warn("Could not retrieve nodes in RSpec: %s" % e)
72 leases = rspec.version.get_leases()
73 except Exception as e:
74 self._log.warn("Could not retrieve leases in RSpec: %s" % e)
76 links = rspec.version.get_links()
77 except Exception as e:
78 self._log.warn("Could not retrieve links in RSpec: %s" % e)
80 channels = rspec.version.get_channels()
81 except Exception as e:
82 self._log.warn("Could not retrieve channels in RSpec: %s" % e)
85 # Extend object and Format object field's name
88 node['network_hrn'] = Xrn(node['component_id']).authority[0] # network ? XXX
89 node['hrn'] = urn_to_hrn(node['component_id'])[0]
90 node['urn'] = node['component_id']
91 node['hostname'] = node['component_name']
92 node['initscripts'] = node.pop('pl_initscripts')
93 if 'exclusive' in node and node['exclusive']:
94 node['exclusive'] = node['exclusive'].lower() == 'true'
96 # XXX This should use a MAP as before
97 if 'position' in node: # iotlab
98 node['x'] = node['position']['posx']
99 node['y'] = node['position']['posy']
100 node['z'] = node['position']['posz']
103 if 'location' in node:
105 node['latitude'] = node['location']['latitude']
106 node['longitude'] = node['location']['longitude']
112 for tag in node['tags']:
113 node[tag['tagname']] = tag['value']
117 # We suppose we have children of dict that cannot be serialized
118 # with xmlrpc, let's make dict
119 resources.append(self.make_dict_rec(node))
121 # NOTE a channel is a resource and should not be treated independently
124 # +----+------+-------+
126 # node link channel etc.
127 #resources.extend(nodes)
128 #resources.extend(channels)
130 return {'resource': resources, 'lease': leases }
131 # 'channel': channels \
135 def build_sfa_rspec(self, slice_id, resources, properties, leases):
137 Build the XML RSpec from list of resources' urns.
138 eg. resources = ["urn:publicid:IDN+ple:modenaple+node+planetlab-1.ing.unimo.it"]
140 #if isinstance(resources, str):
141 # resources = eval(resources)
142 # rspec_type and rspec_version should be set in the config of the platform,
143 # we use GENIv3 as default one if not
145 if 'rspec_type' and 'rspec_version' in self.config:
146 rspec_version = self.config['rspec_type'] + ' ' + self.config['rspec_version']
148 rspec_version = 'GENI 3'
150 # extend rspec version with "content_type"
151 rspec_version += ' request'
153 rspec = RSpec(version=rspec_version)
158 self._log.debug("Building RSpec for resources %s" % resources)
161 for urn in resources:
162 # XXX TO BE CORRECTED, this handles None values
167 # TODO: take into account the case where we send a dict of URNs without keys
168 #resource['component_id'] = resource.pop('urn')
169 resource['component_id'] = urn
170 resource_hrn, resource_type = urn_to_hrn(resource['component_id'])
171 # build component_manager_id
172 top_auth = resource_hrn.split('.')[0]
174 resource['component_manager_id'] = "%s+%s+authority+cm" % (cm[0],top_auth)
176 if resource_type == 'node':
177 # XXX dirty hack WiLab !!!
178 # Commented Lucia, doesn't work for wilabt
180 # if 'wilab2' in self.config['sm']:
181 # resource['client_id'] = "PC"
182 # resource['sliver_type'] = "raw-pc"
185 resource['client_id'] = "node%s" % cardinal
186 resource['sliver_type'] = "raw-pc"
187 resource['disk_image'] = "hola"
188 top_auth = resource_hrn.replace("\\", "").split('.')
190 top_auth = '.'.join(top_auth)
192 resource['component_manager_id'] = "%s+%s+authority+cm" % (cm[0],top_auth)
194 nodes.append(resource)
195 elif resource_type == 'link':
196 links.append(resource)
197 elif resource_type == 'channel':
198 channels.append(resource)
200 raise Exception("Not supported type of resource")
202 rspec.version.add_nodes(nodes, rspec_content_type="request")
203 #rspec.version.add_leases(leases)
204 #rspec.version.add_links(links)
205 #rspec.version.add_channels(channels)
207 #self._log.debug("request rspec: %s"%rspec.toxml())
208 string = rspec.toxml()
209 if wilab and properties is not None:
210 ## dirty hack for the f4f demo
211 b = string.split('\n')
212 for i, n in enumerate(b):
213 if 'sliver_type name="raw-pc"' in n:
214 b[i] = '<sliver_type name="raw-pc">'
215 b.insert(i+1, '<disk_image name="urn:publicid:IDN+wall2.ilabt.iminds.be+image+emulab-ops//%s"/>' % properties['disk_image'])
216 #b.insert(i+1, '<disk_image name="urn:publicid:IDN+wilab2.ilabt.iminds.be+image+nepi:%s"/>' % properties['disk_image'])
217 b.insert(i+2, '</sliver_type>')
219 self._log.debug("request rspec : %s" % string)