5 from sfa.util.faults import *
\r
6 from sfa.util.sfalogging import logger
\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.util.xrn import urn_to_hrn, hrn_to_urn, get_authority, Xrn
\r
12 from sfa.util.plxrn import hrn_to_pl_slicename
\r
14 from sfa.server.sfaapi import SfaApi
\r
15 from sfa.server.registry import Registries
\r
16 from sfa.rspecs.rspec_version import RSpecVersion
\r
17 from sfa.rspecs.sfa_rspec import sfa_rspec_version
\r
18 from sfa.rspecs.rspec_parser import parse_rspec
\r
20 from sfa.managers.aggregate_manager import __get_registry_objects, ListSlices
\r
22 from sfa.plc.slices import Slices
\r
25 RSPEC_TMP_FILE_PREFIX = "/tmp/max_rspec"
\r
27 # execute shell command and return both exit code and text output
\r
28 def shell_execute(cmd, timeout):
\r
29 pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
\r
30 pipe = os.popen(cmd + ' 2>&1', 'r')
\r
38 if code is None: code = 0
\r
39 if text[-1:] == '\n': text = text[:-1]
\r
43 call AM API client with command like in the following example:
\r
44 cd aggregate_client; java -classpath AggregateWS-client-api.jar:lib/* \
\r
45 net.geni.aggregate.client.examples.CreateSliceNetworkClient \
\r
46 ./repo https://geni:8443/axis2/services/AggregateGENI \
\r
50 def call_am_apiclient(client_app, params, timeout):
\r
51 (client_path, am_url) = Config().get_max_aggrMgr_info()
\r
52 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
53 ret = shell_execute(sys_cmd, timeout)
\r
54 logger.debug("shell_execute cmd: %s returns %s" % (sys_cmd, ret))
\r
57 # save request RSpec xml content to a tmp file
\r
58 def save_rspec_to_file(rspec):
\r
59 path = RSPEC_TMP_FILE_PREFIX + "_" + time.strftime('%Y%m%dT%H:%M:%S', time.gmtime(time.time())) +".xml"
\r
60 file = open(path, "w")
\r
65 # get stripped down slice id/name plc.maxpl.xislice1 --> maxpl_xislice1
\r
66 def get_plc_slice_id(cred, xrn):
\r
67 (hrn, type) = urn_to_hrn(xrn)
\r
68 slice_id = hrn.find(':')
\r
70 if hrn.find(':') != -1:
\r
72 elif hrn.find('+') != -1:
\r
76 slice_id = hrn.split(sep)[-2] + '_' + hrn.split(sep)[-1]
\r
80 def get_xml_by_tag(text, tag):
\r
81 indx1 = text.find('<'+tag)
\r
82 indx2 = text.find('/'+tag+'>')
\r
84 if indx1!=-1 and indx2>indx1:
\r
85 xml = text[indx1:indx2+len(tag)+2]
\r
88 def prepare_slice(api, slice_xrn, creds, users):
\r
89 reg_objects = __get_registry_objects(slice_xrn, creds, users)
\r
90 (hrn, type) = urn_to_hrn(slice_xrn)
\r
91 slices = Slices(api)
\r
92 peer = slices.get_peer(hrn)
\r
93 sfa_peer = slices.get_sfa_peer(hrn)
\r
96 slice_record = users[0].get('slice_record', {})
\r
97 registry = api.registries[api.hrn]
\r
98 credential = api.getCredential()
\r
99 # ensure site record exists
\r
100 site = slices.verify_site(hrn, slice_record, peer, sfa_peer)
\r
101 # ensure slice record exists
\r
102 slice = slices.verify_slice(hrn, slice_record, peer, sfa_peer)
\r
103 # ensure person records exists
\r
104 persons = slices.verify_persons(hrn, slice, users, peer, sfa_peer)
\r
106 def parse_resources(text, slice_xrn):
\r
108 urn = hrn_to_urn(slice_xrn, 'sliver')
\r
109 plc_slice = re.search("Slice Status => ([^\n]+)", text)
\r
110 if plc_slice.group(1) != 'NONE':
\r
112 res['geni_urn'] = urn + '_plc_slice'
\r
113 res['geni_error'] = ''
\r
114 res['geni_status'] = 'unknown'
\r
115 if plc_slice.group(1) == 'CREATED':
\r
116 res['geni_status'] = 'ready'
\r
117 resources.append(res)
\r
118 vlans = re.findall("GRI => ([^\n]+)\n\t Status => ([^\n]+)", text)
\r
121 res['geni_error'] = ''
\r
122 res['geni_urn'] = urn + '_vlan_' + vlan[0]
\r
123 if vlan[1] == 'ACTIVE':
\r
124 res['geni_status'] = 'ready'
\r
125 elif vlan[1] == 'FAILED':
\r
126 res['geni_status'] = 'failed'
\r
128 res['geni_status'] = 'configuring'
\r
129 resources.append(res)
\r
132 def slice_status(api, slice_xrn, creds):
\r
133 urn = hrn_to_urn(slice_xrn, 'slice')
\r
135 top_level_status = 'unknown'
\r
136 slice_id = get_plc_slice_id(creds, urn)
\r
137 (ret, output) = call_am_apiclient("QuerySliceNetworkClient", [slice_id,], 5)
\r
138 # parse output into rspec XML
\r
139 if output.find("Unkown Rspec:") > 0:
\r
140 top_level_staus = 'failed'
\r
141 result['geni_resources'] = ''
\r
145 if output.find("Status => FAILED") > 0:
\r
146 top_level_staus = 'failed'
\r
147 elif ( output.find("Status => ACCEPTED") > 0 or output.find("Status => PENDING") > 0
\r
148 or output.find("Status => INSETUP") > 0 or output.find("Status => INCREATE") > 0
\r
150 top_level_status = 'configuring'
\r
152 top_level_status = 'ready'
\r
153 result['geni_resources'] = parse_resources(output, slice_xrn)
\r
154 result['geni_urn'] = urn
\r
155 result['geni_status'] = top_level_status
\r
158 def create_slice(api, xrn, cred, rspec, users):
\r
159 indx1 = rspec.find("<RSpec")
\r
160 indx2 = rspec.find("</RSpec>")
\r
161 if indx1 > -1 and indx2 > indx1:
\r
162 rspec = rspec[indx1+len("<RSpec type=\"SFA\">"):indx2-1]
\r
163 rspec_path = save_rspec_to_file(rspec)
\r
164 prepare_slice(api, xrn, cred, users)
\r
165 slice_id = get_plc_slice_id(cred, xrn)
\r
166 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
167 ret = shell_execute(sys_cmd, 1)
\r
168 sys_cmd = "sed -i \"s/rspec id=\\\"[^\\\"]*/rspec id=\\\"" + rspec_path + "/g\""
\r
169 ret = shell_execute(sys_cmd, 1)
\r
170 (ret, output) = call_am_apiclient("CreateSliceNetworkClient", [rspec_path,], 3)
\r
172 rspec = "<RSpec type=\"SFA\"> Done! </RSpec>"
\r
175 def delete_slice(api, xrn, cred):
\r
176 slice_id = get_plc_slice_id(cred, xrn)
\r
177 (ret, output) = call_am_apiclient("DeleteSliceNetworkClient", [slice_id,], 3)
\r
182 def get_rspec(api, cred, slice_urn):
\r
183 logger.debug("#### called max-get_rspec")
\r
184 #geni_slice_urn: urn:publicid:IDN+plc:maxpl+slice+xi_rspec_test1
\r
185 if slice_urn == None:
\r
186 (ret, output) = call_am_apiclient("GetResourceTopology", ['all', '\"\"'], 5)
\r
188 slice_id = get_plc_slice_id(cred, slice_urn)
\r
189 (ret, output) = call_am_apiclient("GetResourceTopology", ['all', slice_id,], 5)
\r
190 # parse output into rspec XML
\r
191 if output.find("No resouce found") > 0:
\r
192 rspec = "<RSpec type=\"SFA\"> <Fault>No resource found</Fault> </RSpec>"
\r
194 comp_rspec = get_xml_by_tag(output, 'computeResource')
\r
195 logger.debug("#### computeResource %s" % comp_rspec)
\r
196 topo_rspec = get_xml_by_tag(output, 'topology')
\r
197 logger.debug("#### topology %s" % topo_rspec)
\r
198 rspec = "<RSpec type=\"SFA\"> <network name=\"" + Config().get_interface_hrn() + "\">";
\r
199 if comp_rspec != None:
\r
200 rspec = rspec + get_xml_by_tag(output, 'computeResource')
\r
201 if topo_rspec != None:
\r
202 rspec = rspec + get_xml_by_tag(output, 'topology')
\r
203 rspec = rspec + "</network> </RSpec>"
\r
206 def start_slice(api, xrn, cred):
\r
207 # service not supported
\r
210 def stop_slice(api, xrn, cred):
\r
211 # service not supported
\r
214 def reset_slices(api, xrn):
\r
215 # service not supported
\r
219 GENI AM API Methods
\r
222 def GetVersion(api):
\r
224 request_rspec_versions = [dict(sfa_rspec_version)]
\r
225 ad_rspec_versions = [dict(sfa_rspec_version)]
\r
226 #TODO: MAX-AM specific
\r
227 version_more = {'interface':'aggregate',
\r
229 'hrn':xrn.get_hrn(),
\r
230 'request_rspec_versions': request_rspec_versions,
\r
231 'ad_rspec_versions': ad_rspec_versions,
\r
232 'default_ad_rspec': dict(sfa_rspec_version)
\r
234 return version_core(version_more)
\r
236 def SliverStatus(api, slice_xrn, creds, call_id):
\r
237 if Callids().already_handled(call_id): return {}
\r
238 return slice_status(api, slice_xrn, creds)
\r
240 def CreateSliver(api, slice_xrn, creds, rspec_string, users, call_id):
\r
241 if Callids().already_handled(call_id): return ""
\r
242 #TODO: create real CreateSliver response rspec
\r
243 ret = create_slice(api, slice_xrn, creds, rspec_string, users)
\r
245 return get_rspec(api, creds, slice_xrn)
\r
247 return "<?xml version=\"1.0\" ?> <RSpec type=\"SFA\"> Error! </RSpec>"
\r
249 def DeleteSliver(api, xrn, creds, call_id):
\r
250 if Callids().already_handled(call_id): return ""
\r
251 return delete_slice(api, xrn, creds)
\r
254 def ListResources(api, creds, options,call_id):
\r
255 if Callids().already_handled(call_id): return ""
\r
256 # version_string = "rspec_%s" % (rspec_version.get_version_name())
\r
257 slice_urn = options.get('geni_slice_urn')
\r
258 return get_rspec(api, creds, slice_urn)
\r
260 def fetch_context(slice_hrn, user_hrn, contexts):
\r
262 Returns the request context required by sfatables. At some point, this mechanism should be changed
\r
263 to refer to "contexts", which is the information that sfatables is requesting. But for now, we just
\r
264 return the basic information needed in a dict.
\r
266 base_context = {'sfa':{'user':{'hrn':user_hrn}}}
\r
267 return base_context
\r
269 create_slice(api, "plc.maxpl.test000", None, rspec_xml, None)
\r