1 from sfa.plc.slices import Slices
\r
2 from sfa.server.registry import Registries
\r
3 from sfa.util.xrn import urn_to_hrn, hrn_to_urn, get_authority, Xrn
\r
4 from sfa.util.plxrn import hrn_to_pl_slicename
\r
5 from sfa.util.sfalogging import logger
\r
6 from sfa.util.faults import *
\r
7 from sfa.util.config import Config
\r
8 from sfa.util.sfatime import utcparse
\r
9 from sfa.util.callids import Callids
\r
10 from sfa.util.version import version_core
\r
11 from sfa.rspecs.rspec_version import RSpecVersion
\r
12 from sfa.rspecs.sfa_rspec import sfa_rspec_version
\r
13 from sfa.rspecs.rspec_parser import parse_rspec
\r
14 from sfa.managers.aggregate_manager_pl import __get_registry_objects, ListSlices
\r
19 RSPEC_TMP_FILE_PREFIX = "/tmp/max_rspec"
\r
21 # execute shell command and return both exit code and text output
\r
22 def shell_execute(cmd, timeout):
\r
23 pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
\r
24 pipe = os.popen(cmd + ' 2>&1', 'r')
\r
32 if code is None: code = 0
\r
33 if text[-1:] == '\n': text = text[:-1]
\r
37 call AM API client with command like in the following example:
\r
38 cd aggregate_client; java -classpath AggregateWS-client-api.jar:lib/* \
\r
39 net.geni.aggregate.client.examples.CreateSliceNetworkClient \
\r
40 ./repo https://geni:8443/axis2/services/AggregateGENI \
\r
44 def call_am_apiclient(client_app, params, timeout):
\r
45 (client_path, am_url) = Config().get_max_aggrMgr_info()
\r
46 sys_cmd = "cd " + client_path + "; java -classpath AggregateWS-client-api.jar:lib/* net.geni.aggregate.client.examples." + client_app + " ./repo " + am_url + " " + ' '.join(params)
\r
47 ret = shell_execute(sys_cmd, timeout)
\r
48 logger.debug("shell_execute cmd: %s returns %s" % (sys_cmd, ret))
\r
51 # save request RSpec xml content to a tmp file
\r
52 def save_rspec_to_file(rspec):
\r
53 path = RSPEC_TMP_FILE_PREFIX + "_" + time.strftime('%Y%m%dT%H:%M:%S', time.gmtime(time.time())) +".xml"
\r
54 file = open(path, "w")
\r
59 # get stripped down slice id/name plc.maxpl.xislice1 --> maxpl_xislice1
\r
60 def get_plc_slice_id(cred, xrn):
\r
61 (hrn, type) = urn_to_hrn(xrn)
\r
62 slice_id = hrn.find(':')
\r
64 if hrn.find(':') != -1:
\r
66 elif hrn.find('+') != -1:
\r
70 slice_id = hrn.split(sep)[-2] + '_' + hrn.split(sep)[-1]
\r
74 def get_xml_by_tag(text, tag):
\r
75 indx1 = text.find('<'+tag)
\r
76 indx2 = text.find('/'+tag+'>')
\r
78 if indx1!=-1 and indx2>indx1:
\r
79 xml = text[indx1:indx2+len(tag)+2]
\r
82 def prepare_slice(api, slice_xrn, creds, users):
\r
83 reg_objects = __get_registry_objects(slice_xrn, creds, users)
\r
84 (hrn, type) = urn_to_hrn(slice_xrn)
\r
85 slices = Slices(api)
\r
86 peer = slices.get_peer(hrn)
\r
87 sfa_peer = slices.get_sfa_peer(hrn)
\r
90 slice_record = users[0].get('slice_record', {})
\r
91 registry = api.registries[api.hrn]
\r
92 credential = api.getCredential()
\r
93 # ensure site record exists
\r
94 site = slices.verify_site(hrn, slice_record, peer, sfa_peer)
\r
95 # ensure slice record exists
\r
96 slice = slices.verify_slice(hrn, slice_record, peer, sfa_peer)
\r
97 # ensure person records exists
\r
98 persons = slices.verify_persons(hrn, slice, users, peer, sfa_peer)
\r
100 def parse_resources(text, slice_xrn):
\r
102 urn = hrn_to_urn(slice_xrn, 'sliver')
\r
103 plc_slice = re.search("Slice Status => ([^\n]+)", text)
\r
104 if plc_slice.group(1) != 'NONE':
\r
106 res['geni_urn'] = urn + '_plc_slice'
\r
107 res['geni_error'] = ''
\r
108 res['geni_status'] = 'unknown'
\r
109 if plc_slice.group(1) == 'CREATED':
\r
110 res['geni_status'] = 'ready'
\r
111 resources.append(res)
\r
112 vlans = re.findall("GRI => ([^\n]+)\n\t Status => ([^\n]+)", text)
\r
115 res['geni_error'] = ''
\r
116 res['geni_urn'] = urn + '_vlan_' + vlan[0]
\r
117 if vlan[1] == 'ACTIVE':
\r
118 res['geni_status'] = 'ready'
\r
119 elif vlan[1] == 'FAILED':
\r
120 res['geni_status'] = 'failed'
\r
122 res['geni_status'] = 'configuring'
\r
123 resources.append(res)
\r
126 def slice_status(api, slice_xrn, creds):
\r
127 urn = hrn_to_urn(slice_xrn, 'slice')
\r
129 top_level_status = 'unknown'
\r
130 slice_id = get_plc_slice_id(creds, urn)
\r
131 (ret, output) = call_am_apiclient("QuerySliceNetworkClient", [slice_id,], 5)
\r
132 # parse output into rspec XML
\r
133 if output.find("Unkown Rspec:") > 0:
\r
134 top_level_staus = 'failed'
\r
135 result['geni_resources'] = ''
\r
139 if output.find("Status => FAILED") > 0:
\r
140 top_level_staus = 'failed'
\r
141 elif ( output.find("Status => ACCEPTED") > 0 or output.find("Status => PENDING") > 0
\r
142 or output.find("Status => INSETUP") > 0 or output.find("Status => INCREATE") > 0
\r
144 top_level_status = 'configuring'
\r
146 top_level_status = 'ready'
\r
147 result['geni_resources'] = parse_resources(output, slice_xrn)
\r
148 result['geni_urn'] = urn
\r
149 result['geni_status'] = top_level_status
\r
152 def create_slice(api, xrn, cred, rspec, users):
\r
153 indx1 = rspec.find("<RSpec")
\r
154 indx2 = rspec.find("</RSpec>")
\r
155 if indx1 > -1 and indx2 > indx1:
\r
156 rspec = rspec[indx1+len("<RSpec type=\"SFA\">"):indx2-1]
\r
157 rspec_path = save_rspec_to_file(rspec)
\r
158 prepare_slice(api, xrn, cred, users)
\r
159 slice_id = get_plc_slice_id(cred, xrn)
\r
160 sys_cmd = "sed -i \"s/rspec id=\\\"[^\\\"]*/rspec id=\\\"" +slice_id+ "/g\" " + rspec_path + ";sed -i \"s/:rspec=[^:'<\\\" ]*/:rspec=" +slice_id+ "/g\" " + rspec_path
\r
161 ret = shell_execute(sys_cmd, 1)
\r
162 sys_cmd = "sed -i \"s/rspec id=\\\"[^\\\"]*/rspec id=\\\"" + rspec_path + "/g\""
\r
163 ret = shell_execute(sys_cmd, 1)
\r
164 (ret, output) = call_am_apiclient("CreateSliceNetworkClient", [rspec_path,], 3)
\r
166 rspec = "<RSpec type=\"SFA\"> Done! </RSpec>"
\r
169 def delete_slice(api, xrn, cred):
\r
170 slice_id = get_plc_slice_id(cred, xrn)
\r
171 (ret, output) = call_am_apiclient("DeleteSliceNetworkClient", [slice_id,], 3)
\r
176 def get_rspec(api, cred, slice_urn):
\r
177 logger.debug("#### called max-get_rspec")
\r
178 #geni_slice_urn: urn:publicid:IDN+plc:maxpl+slice+xi_rspec_test1
\r
179 if slice_urn == None:
\r
180 (ret, output) = call_am_apiclient("GetResourceTopology", ['all', '\"\"'], 5)
\r
182 slice_id = get_plc_slice_id(cred, slice_urn)
\r
183 (ret, output) = call_am_apiclient("GetResourceTopology", ['all', slice_id,], 5)
\r
184 # parse output into rspec XML
\r
185 if output.find("No resouce found") > 0:
\r
186 rspec = "<RSpec type=\"SFA\"> <Fault>No resource found</Fault> </RSpec>"
\r
188 comp_rspec = get_xml_by_tag(output, 'computeResource')
\r
189 logger.debug("#### computeResource %s" % comp_rspec)
\r
190 topo_rspec = get_xml_by_tag(output, 'topology')
\r
191 logger.debug("#### topology %s" % topo_rspec)
\r
192 rspec = "<RSpec type=\"SFA\"> <network name=\"" + Config().get_interface_hrn() + "\">";
\r
193 if comp_rspec != None:
\r
194 rspec = rspec + get_xml_by_tag(output, 'computeResource')
\r
195 if topo_rspec != None:
\r
196 rspec = rspec + get_xml_by_tag(output, 'topology')
\r
197 rspec = rspec + "</network> </RSpec>"
\r
200 def start_slice(api, xrn, cred):
\r
201 # service not supported
\r
204 def stop_slice(api, xrn, cred):
\r
205 # service not supported
\r
208 def reset_slices(api, xrn):
\r
209 # service not supported
\r
213 GENI AM API Methods
\r
216 def GetVersion(api):
\r
218 request_rspec_versions = [dict(sfa_rspec_version)]
\r
219 ad_rspec_versions = [dict(sfa_rspec_version)]
\r
220 #TODO: MAX-AM specific
\r
221 version_more = {'interface':'aggregate',
\r
223 'hrn':xrn.get_hrn(),
\r
224 'request_rspec_versions': request_rspec_versions,
\r
225 'ad_rspec_versions': ad_rspec_versions,
\r
226 'default_ad_rspec': dict(sfa_rspec_version)
\r
228 return version_core(version_more)
\r
230 def SliverStatus(api, slice_xrn, creds, call_id):
\r
231 if Callids().already_handled(call_id): return {}
\r
232 return slice_status(api, slice_xrn, creds)
\r
234 def CreateSliver(api, slice_xrn, creds, rspec_string, users, call_id):
\r
235 if Callids().already_handled(call_id): return ""
\r
236 #TODO: create real CreateSliver response rspec
\r
237 ret = create_slice(api, slice_xrn, creds, rspec_string, users)
\r
239 return get_rspec(api, creds, slice_xrn)
\r
241 return "<?xml version=\"1.0\" ?> <RSpec type=\"SFA\"> Error! </RSpec>"
\r
243 def DeleteSliver(api, xrn, creds, call_id):
\r
244 if Callids().already_handled(call_id): return ""
\r
245 return delete_slice(api, xrn, creds)
\r
248 def ListResources(api, creds, options,call_id):
\r
249 if Callids().already_handled(call_id): return ""
\r
250 # version_string = "rspec_%s" % (rspec_version.get_version_name())
\r
251 slice_urn = options.get('geni_slice_urn')
\r
252 return get_rspec(api, creds, slice_urn)
\r
255 Returns the request context required by sfatables. At some point, this mechanism should be changed
\r
256 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
\r
257 return the basic information needed in a dict.
\r
259 def fetch_context(slice_hrn, user_hrn, contexts):
\r
260 base_context = {'sfa':{'user':{'hrn':user_hrn}}}
\r
261 return base_context
\r
263 create_slice(api, "plc.maxpl.test000", None, rspec_xml, None)
\r