3 #yum -y install python-pip
6 import xml.etree.ElementTree as ET
10 # module for bonfire to connect with sfa (following the Rspec)
11 # inspired by the following documenation :
12 # https://svn.planet-lab.org/wiki/SfaDeveloperDummyTutorial#RunningSFAinDummyflavour
14 # 1) list all the resources of bonfire from sfa's point of view
15 # python -c 'import bonfire; print bonfire.bonsources()'
17 # 2) retrieve the url, the name and the key that will currently use by sfa for a compute N°3656 located at fr-inria
18 # python -c 'import bonfire; print bonfire.rsa_user_bonfire("fr-inria", "3656")'
20 # 3) create a new user and slice for sfa wrap
21 # python -c 'import bonfire; print bonfire.new_user_slice()'
23 # 4) changing the status to running status for the experiment 2911
24 # python -c 'import bonfire; print bonfire.provisioning("2911")'
26 # 5) stop virtual machine n°3756 at fr-inira testbed
27 # python -c 'import bonfire; print bonfire.stop_vm("fr-inria", "3756")'
29 # 6) allocation : create an experiment bonfire with slice information
30 # python -c 'import bonfire; print bonfire.allocate("nlebreto", "nlebreto", "tdes", "125", "topdomain.dummy.nicolasi", "https://api.integration.bonfire.grid5000.fr/experiments")'
32 # 7) remove slice or key
33 # python -c 'import bonfire; print bonfire.remove_slice("topdomain.dummy.alice_slice")'
35 # 8) attach slice to a user (did not work)
36 # python -c 'import bonfire; print bonfire.create_slice_attach_user("topdomain.dummy.alice")'
38 # ########################################################## #
39 # ########################################################## #
41 # pseudo authentication for bonfire
42 def bonfire_authenticate():
44 h["user"] = "nlebreto"
45 h["user_pass"] = "GDRU_23tc$"
46 h["location"] = "https://api.integration.bonfire.grid5000.fr"
49 # create a slice and attach a specific user to it
50 def create_slice_attach_user(user_slice):
51 call = "sfa.py add -x {0}_slice -t slice -r {0}@dummy.net".format(user_slice)
52 callcreateslice = subprocess.Popen(call, shell=True)
55 def remove_slice(name):
56 cmdremove = "sfaadmin.py reg remove {0}".format(name)
57 removeaction = subprocess.Popen(cmdremove, shell=True)
59 # show specific credential of a slice
60 def show_slice_credential(slice_name):
61 path = "/root/.sfi/{0}.slice.cred".format(slice_name)
65 hash["slice_native"] = root.findall(".//signatures//{http://www.w3.org/2000/09/xmldsig#}Signature//{http://www.w3.org/2000/09/xmldsig#}KeyInfo//{http://www.w3.org/2000/09/xmldsig#}X509Data//{http://www.w3.org/2000/09/xmldsig#}X509SubjectName")[0].text
66 for target in root.findall('credential'):
67 hash["slice_user_urn"] = target.find('owner_urn').text
68 hash["slice_urn"] = target.find('target_urn').text
69 hash["serial"] = target.find('serial').text
72 # create a bonfire experiment from a sfa point of view
73 def allocate(user_name, groups, description, walltime, slice_name):
75 hash = show_slice_credential(slice_name)
76 create_fed4fire_exp(user_name, groups, description, walltime, hash["slice_urn"], hash["slice_user_urn"], hash["slice_native"])
80 # retrieve the url, the name and the key that will currently use by sfa
81 def rsa_user_bonfire(testbed, num_compute):
82 url = "https://api.integration.bonfire.grid5000.fr/" + "locations/" + testbed + "/computes/" + num_compute
83 pagebonfirecompute = callcurl(url)
84 xmlreduit = ET.fromstring(pagebonfirecompute)
87 for name in xmlreduit:
88 if name.tag == "{http://api.bonfire-project.eu/doc/schemas/occi}groups":
89 hash["name"] = name.text
91 if context.tag == "{http://api.bonfire-project.eu/doc/schemas/occi}authorized_keys":
92 hash["keys"] = context.text
95 # create a new user and slice for sfa wrap
97 n = rsa_user_bonfire("fr-inria", "3656")
98 #url = n["url"] + "." + n["name"]
99 # fix to do add -k id_rsa.pub (pb key convert)
100 url = "topdomain.dummy." + n["name"]
101 txtcreateuser = "sfaadmin.py reg register -x {0} -t user -e {1}@dummy.net".format(url, n["name"])
102 createusersfa = subprocess.Popen(txtcreateuser, shell=True)
103 #slice = n["url"] + "." + n["name"] + "_" + n["name"]
104 slice = "topdomain.dummy." + n["name"] + "_slice"
105 txtslice = "sfaadmin.py reg register -x {0} -t slice -r {1}".format(slice, url)
106 createslice = subprocess.Popen(txtslice, shell=True)
108 # create a experiment bonfire with the slice urn and the experiment owner
109 def create_fed4fire_exp(name, groups, description, walltime, slice_urn, slice_user_urn, slice_native, url_experiment_bonfire):
110 xmldescription='<experiment xmlns="http://api.bonfire-project.eu/doc/schemas/occi"><name>' + name +'</name><groups>' + groups + '</groups><description>' + description + '</description><walltime>' + walltime + '</walltime><status>ready</status><slice_urn>' + slice_urn + '</slice_urn><slice_usr_urn>' + slice_user_urn + '<slice_usr_urn><slice_native>' + slice_native + '</slice_native></experiment>'
111 postexp(url_experiment_bonfire, xmldescription)
113 # simple post method for request
114 def postexp(url, xmldescription):
115 headers = {'content-type': 'application/vnd.bonfire+xml'}
116 h = bonfire_authenticate()
117 r = requests.post(url, data=xmldescription, headers=headers, verify=False, auth=(h["user"], h["user_pass"]))
119 # stop a virtual machine for bonfire
120 # changing the state to stopped state
121 def stop_vm(testbed, num_compute):
122 url = "https://api.integration.bonfire.grid5000.fr/" + "locations/" + testbed + "/computes/" + num_compute
123 xmldescription = '<compute xmlns="http://api.bonfire-project.eu/doc/schemas/occi"><state>stopped</state></compute>'
124 headers = {'content-type': 'application/vnd.bonfire+xml'}
125 h = bonfire_authenticate()
126 r = requests.post(url, data=xmldescription, headers=headers, verify=False, auth=(h["user"], h["user_pass"]))
128 # provisioning : set a bonfire's experiment to running
129 # changing the status to running status
130 def provisioning(num_experiment):
131 url = "https://api.integration.bonfire.grid5000.fr/experiments/" + num_experiment
132 xmldescription = '<experiment xmlns="http://api.bonfire-project.eu/doc/schemas/occi"><status>running</status></experiment>'
133 headers = {'content-type': 'application/vnd.bonfire+xml'}
134 h = bonfire_authenticate()
135 r = requests.post(url, data=xmldescription, headers=headers, verify=False, auth=(h["user"], h["user_pass"]))
137 # retrieving the url, the name and the keys for a specific compute
138 def rsa_user_bonfire(testbed, num_compute):
139 url = "https://api.integration.bonfire.grid5000.fr/" + "locations/" + testbed + "/computes/" + num_compute
140 pagebonfirecompute = callcurl(url)
141 xmlreduit = ET.fromstring(pagebonfirecompute)
144 for name in xmlreduit:
145 if name.tag == "{http://api.bonfire-project.eu/doc/schemas/occi}groups":
146 hash["name"] = name.text
148 if context.tag == "{http://api.bonfire-project.eu/doc/schemas/occi}authorized_keys":
149 hash["keys"] = context.text
154 h = bonfire_authenticate()
155 r = requests.get(url, verify=False, auth=(h["user"], h["user_pass"]))
156 if r.status_code == 200:
159 # create the url page
160 def buildpagehttp(part1, part2, locations):
162 for page in locations:
163 res.append(part1 + page + "/" + part2)
166 def boucle(itemname, xmltree, hashrspec, name):
167 for item in xmltree.findall(itemname):
168 hashrspec[name.text][itemname] = item.text
170 # method to list all information from testbeds
171 def jfedfeat(bonfires, pageurl):
172 pageforstatus = callcurl(pageurl)
173 xmlreduit = ET.fromstring(pageforstatus)
175 itemshost = ["DISK_USAGE", "MEM_USAGE", "CPU_USAGE", "MAX_DISK", "MAX_MEM", "MAX_CPU",
176 "FREE_DISK", "FREE_MEM", "FREE_CPU", "FREE_MEM", "FREE_CPU", "USED_DISK",
177 "USED_MEM", "USED_CPU", "RUNNING_VMS"
179 # retrieve info for xml tree
180 for host in xmlreduit.findall('HOST'):
181 for name in host.findall('NAME'):
182 hashrspec[name.text] = {"name" : name.text}
183 for hostshare in host.findall('HOST_SHARE'):
184 for itemshostname in itemshost:
185 boucle(itemshostname, hostshare, hashrspec, name)
188 for clef in hashrspec:
189 bonfires.append("<node component_manager_id=\"urn:publicid:IDN+topdomain+authority+cm" +
190 " component_id=\"urn:publicid:IDN+topdomain:" + hashrspec[clef]["name"] +
191 "\" component_name=" + hashrspec[clef]["name"] + "exclusive=\"false\">" +
192 " <location country=\"unknown\" longitude=\"123456\" latitude=\"654321\"/>" +
193 " <interface component_id=\"urn:publicid:IDN+ple+interface+node14312:eth0\"/>" +
194 " <available now=\"true\"/>" +
195 " <sliver_type name=\"" + hashrspec[clef]["name"] + "\">" +
196 " <bonfire:initscript name=\"" + hashrspec[clef]["name"] + "\"/>" +
198 for infohost in itemshost:
199 bonfires.append(" <bonfire:attribute name=\"" + infohost + "\"value=\"" + hashrspec[clef][infohost] + "\"/>")
200 bonfires.append("</node>")
202 # remove the useless xml tag version
203 def remove_needless_txt(txt):
205 txt=txt.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n","\n")
206 txt=txt.replace("<?xml version='1.0' encoding='UTF-8'?>\n","\n")
209 # list all bonfire resources following the sfa specification
212 locations = ["fr-inria", "be-ibbt", "uk-epcc"]
213 urlnetworks = buildpagehttp("https://api.integration.bonfire.grid5000.fr/locations/", "networks", locations)
214 urlstorages = buildpagehttp("https://api.integration.bonfire.grid5000.fr/locations/", "storages", locations)
215 urlcomputes = buildpagehttp("https://api.integration.bonfire.grid5000.fr/locations/", "computes", locations)
218 generatedtime = time.strftime("%FT%T%Z")
219 sfabegin = "<RSpec type=\"SFA\" generated=" + generatedtime + "\">"
220 bonfires.append("<?xml version=\"1.0\"?>")
221 bonfires.append(sfabegin)
222 bonfires.append("<managed_experiments>")
223 manag_exp = remove_needless_txt(callcurl("https://api.bonfire-project.eu/managed_experiments"))
224 bonfires.append(manag_exp)
225 bonfires.append("</managed_experiments><sites><machines>")
226 jfedfeat(bonfires, "http://frontend.bonfire.grid5000.fr/one-status.xml")
227 jfedfeat(bonfires, "http://bonfire.epcc.ed.ac.uk/one-status.xml")
228 jfedfeat(bonfires, "http://bonfire.psnc.pl/one-status.xml")
229 jfedfeat(bonfires, "http://nebulosus.rus.uni-stuttgart.de/one-status.xml")
230 bonfires.append("</machines><networks>")
231 for xmlnetworks in urlnetworks:
232 bonfires.append(remove_needless_txt(callcurl(xmlnetworks)))
233 bonfires.append("</networks><storages>")
234 for xmlstorages in urlstorages:
235 bonfires.append(remove_needless_txt(callcurl(xmlstorages)))
236 bonfires.append("</storages><instance_types><computes>")
237 for xmlcomputes in urlcomputes:
238 bonfires.append(remove_needless_txt(callcurl(xmlcomputes)))
239 bonfires.append("</computes></instance_types></sites><experiments>")
240 exp = callcurl("https://api.integration.bonfire.grid5000.fr/experiments")
241 rexp = remove_needless_txt(exp)
242 bonfires.append(rexp)
243 bonfires.append("</experiments><reservations>")
244 reserv = callcurl("https://api.integration.bonfire.grid5000.fr/locations/fr-inria/reservations")
245 rreserv = remove_needless_txt(reserv)
246 bonfires.append(rreserv)
247 bonfires.append("</reservations>")
248 bonfires.append("</RSpec>")
249 bonfires = "\n".join(bonfires)
250 bonfires = bonfires.replace("\n\n","")