4 # Helper functions that minipulate the PLC api.
6 # Faiyaz Ahmed <faiyaza@cs.princeton.edu
8 # $Id: plc.py,v 1.18 2007/08/29 17:26:50 soltesz Exp $
15 from monitor import database
18 from monitor import config
22 logger = logging.getLogger("monitor")
25 def __init__(self, username=None, password=None):
26 if username==None and password==None:
27 self.auth = {'AuthMethod': "anonymous"}
29 self.auth = {'Username' : username,
30 'AuthMethod' : 'password',
31 'AuthString' : password}
34 # NOTE: this host is used by default when there are no auth files.
35 XMLRPC_SERVER="https://boot.planet-lab.org/PLCAPI/"
37 # NOTE: by default, use anonymous access, but if auth files are
38 # configured, use them, with their auth definitions.
41 from monitor import config
42 auth.auth = {'Username' : config.API_AUTH_USER,
43 'AuthMethod' : 'password',
44 'AuthString' : config.API_AUTH_PASSWORD}
45 auth.server = config.API_SERVER
49 auth.server = auth.plc
52 auth.server = XMLRPC_SERVER
54 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
57 def __init__(self, auth, url):
60 self.api = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
62 def __getattr__(self, name):
63 method = getattr(self.api, name)
65 raise AssertionError("method does not exist")
67 return lambda *params : method(self.auth, *params)
70 return self.api.__repr__()
74 def _param_to_str(self, name, *params):
77 retstr += "%s-" % name
82 def __getattr__(self, name):
83 method = getattr(self.api, name)
85 raise AssertionError("method does not exist")
87 def run_or_returncached(*params):
88 cachename = self._param_to_str(name, *params)
89 #print "cachename is %s" % cachename
90 if hasattr(config, 'refresh'):
91 refresh = config.refresh
96 if not database.cachedRecently(cachename):
97 load_old_cache = False
99 values = method(self.auth, *params)
101 print "Call %s FAILED: Using old cached data" % cachename
102 load_old_cache = True
105 values = database.dbLoad(cachename)
107 database.dbDump(cachename, values)
111 values = database.dbLoad(cachename)
114 return method(self.auth, *params)
116 return run_or_returncached
120 return xmlrpclib.Server(url, verbose=False, allow_none=True)
123 return PLC(auth.auth, auth.server)
125 def getCachedAuthAPI():
126 return CachedPLC(auth.auth, auth.server)
128 def getTechEmails(loginbase):
130 For the given site, return all user email addresses that have the 'tech' role.
134 s = api.GetSites(loginbase)[0]
136 p = api.GetPersons(s['person_ids'])
137 # pull out those with the right role.
138 emails = [ person['email'] for person in filter(lambda x: 'tech' in x['roles'], p) ]
141 def getPIEmails(loginbase):
143 For the given site, return all user email addresses that have the 'tech' role.
147 s = api.GetSites(loginbase)[0]
149 p = api.GetPersons(s['person_ids'])
150 # pull out those with the right role.
151 emails = [ person['email'] for person in filter(lambda x: 'pi' in x['roles'], p) ]
154 def getSliceUserEmails(loginbase):
156 For the given site, return all user email addresses that have the 'tech' role.
160 s = api.GetSites(loginbase)[0]
162 slices = api.GetSlices(s['slice_ids'])
165 people += api.GetPersons(slice['person_ids'])
166 # pull out those with the right role.
167 emails = [ person['email'] for person in filter(lambda x: 'pi' in x['roles'], people) ]
168 unique_emails = [ x for x in set(emails) ]
172 Returns list of nodes in dbg as reported by PLC
176 api = xmlrpclib.Server(auth.server, verbose=False)
177 anon = {'AuthMethod': "anonymous"}
178 for node in api.GetNodes(anon, {"boot_state":"dbg"},["hostname"]):
179 dbgNodes.append(node['hostname'])
180 logger.info("%s nodes in debug according to PLC." %len(dbgNodes))
185 Returns loginbase for given nodename
187 def siteId(nodename):
188 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
189 site_id = api.GetNodes (auth.auth, {"hostname": nodename}, ['site_id'])
190 if len(site_id) == 1:
191 loginbase = api.GetSites (auth.auth, site_id[0], ["login_base"])
192 return loginbase[0]['login_base']
194 print "Not nodes returned!!!!"
197 Returns list of slices for a site.
199 def slices(loginbase):
201 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
202 sliceids = api.GetSites (auth.auth, {"login_base" : loginbase}, ["slice_ids"])[0]['slice_ids']
203 for slice in api.GetSlices(auth.auth, {"slice_id" : sliceids}, ["name"]):
204 siteslices.append(slice['name'])
208 Returns dict of PCU info of a given node.
210 def getpcu(nodename):
211 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
212 anon = {'AuthMethod': "anonymous"}
213 nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0]
214 if nodeinfo['pcu_ids']:
216 sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0]
218 print nodeinfo["ports"]
219 sitepcu[nodename] = nodeinfo["ports"][0]
222 logger.info("%s doesn't have PCU" % nodename)
225 def GetPCUs(filter=None, fields=None):
226 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
227 pcu_list = api.GetPCUs(auth.auth, filter, fields)
231 Returns all site nodes for site id (loginbase).
233 def getSiteNodes(loginbase, fields=None):
234 api = xmlrpclib.Server(auth.server, verbose=False)
236 anon = {'AuthMethod': "anonymous"}
238 nodeids = api.GetSites(anon, {"login_base": loginbase}, fields)[0]['node_ids']
239 for node in api.GetNodes(anon, {"node_id": nodeids}, ['hostname']):
240 nodelist.append(node['hostname'])
241 except Exception, exc:
242 logger.info("getSiteNodes: %s" % exc)
243 print "getSiteNodes: %s" % exc
247 def getPersons(filter=None, fields=None):
248 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
251 persons = api.GetPersons(auth.auth, filter, fields)
252 except Exception, exc:
253 print "getPersons: %s" % exc
254 logger.info("getPersons: %s" % exc)
257 def getSites(filter=None, fields=None):
258 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
260 anon = {'AuthMethod': "anonymous"}
262 #sites = api.GetSites(anon, filter, fields)
263 sites = api.GetSites(auth.auth, filter, fields)
264 except Exception, exc:
265 traceback.print_exc()
266 print "getSites: %s" % exc
267 logger.info("getSites: %s" % exc)
270 def getSiteNodes2(loginbase):
271 api = xmlrpclib.Server(auth.server, verbose=False)
273 anon = {'AuthMethod': "anonymous"}
275 nodeids = api.GetSites(anon, {"login_base": loginbase})[0]['node_ids']
276 nodelist += getNodes({'node_id':nodeids})
277 except Exception, exc:
278 logger.info("getSiteNodes2: %s" % exc)
281 def getNodeNetworks(filter=None):
282 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
283 nodenetworks = api.GetNodeNetworks(auth.auth, filter, None)
286 def getNodes(filter=None, fields=None):
287 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
288 nodes = api.GetNodes(auth.auth, filter, fields)
289 #['boot_state', 'hostname',
290 #'site_id', 'date_created', 'node_id', 'version', 'nodenetwork_ids',
291 #'last_updated', 'peer_node_id', 'ssh_rsa_key' ])
295 Sets boot state of a node.
297 def nodeBootState(nodename, state):
298 api = xmlrpclib.Server(auth.server, verbose=False)
300 return api.UpdateNode(auth.auth, nodename, {'boot_state': state})
301 except Exception, exc:
302 logger.info("nodeBootState: %s" % exc)
304 def updateNodeKey(nodename, key):
305 api = xmlrpclib.Server(auth.server, verbose=False)
307 return api.UpdateNode(auth.auth, nodename, {'key': key})
308 except Exception, exc:
309 logger.info("updateNodeKey: %s" % exc)
312 Sends Ping Of Death to node.
314 def nodePOD(nodename):
315 api = xmlrpclib.Server(auth.server, verbose=False)
316 logger.info("Sending POD to %s" % nodename)
319 return api.RebootNode(auth.auth, nodename)
320 except Exception, exc:
321 logger.info("nodePOD: %s" % exc)
324 Freeze all site slices.
326 def suspendSlices(nodename):
327 api = xmlrpclib.Server(auth.server, verbose=False)
328 for slice in slices(siteId(nodename)):
329 logger.info("Suspending slice %s" % slice)
332 api.AddSliceAttribute(auth.auth, slice, "enabled", "0")
333 except Exception, exc:
334 logger.info("suspendSlices: %s" % exc)
336 def enableSlices(nodename):
337 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
338 for slice in slices(siteId(nodename)):
339 logger.info("Enabling slices %s" % slice)
342 slice_list = api.GetSlices(auth.auth, {'name': slice}, None)
343 if len(slice_list) == 0:
345 slice_id = slice_list[0]['slice_id']
346 l_attr = api.GetSliceAttributes(auth.auth, {'slice_id': slice_id}, None)
348 if "enabled" == attr['name'] and attr['value'] == "0":
349 logger.info("Deleted enable=0 attribute from slice %s" % slice)
350 api.DeleteSliceAttribute(auth.auth, attr['slice_attribute_id'])
351 except Exception, exc:
352 logger.info("enableSlices: %s" % exc)
353 print "exception: %s" % exc
355 #I'm commenting this because this really should be a manual process.
357 #Enable suspended site slices.
359 #def enableSlices(nodename, slicelist):
360 # api = xmlrpclib.Server(auth.server, verbose=False)
361 # for slice in slices(siteId(nodename)):
362 # logger.info("Suspending slice %s" % slice)
363 # api.SliceAttributeAdd(auth.auth, slice, "plc_slice_state", {"state" : "suspended"})
365 def enableSliceCreation(nodename):
366 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
368 loginbase = siteId(nodename)
369 logger.info("Enabling slice creation for site %s" % loginbase)
371 logger.info("\tcalling UpdateSite(%s, enabled=True)" % loginbase)
372 api.UpdateSite(auth.auth, loginbase, {'enabled': True})
373 except Exception, exc:
374 print "ERROR: enableSliceCreation: %s" % exc
375 logger.info("ERROR: enableSliceCreation: %s" % exc)
378 Removes ability to create slices. Returns previous max_slices
380 def removeSliceCreation(nodename):
381 print "removeSliceCreation(%s)" % nodename
382 api = xmlrpclib.Server(auth.server, verbose=False)
384 loginbase = siteId(nodename)
385 #numslices = api.GetSites(auth.auth, {"login_base": loginbase},
386 # ["max_slices"])[0]['max_slices']
387 logger.info("Removing slice creation for site %s" % loginbase)
389 #api.UpdateSite(auth.auth, loginbase, {'max_slices': 0})
390 api.UpdateSite(auth.auth, loginbase, {'enabled': False})
391 except Exception, exc:
392 logger.info("removeSliceCreation: %s" % exc)
397 #def enableSliceCreation(nodename, maxslices):
398 # api = xmlrpclib.Server(auth.server, verbose=False)
399 # anon = {'AuthMethod': "anonymous"}
400 # siteid = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
401 # if len(siteid) == 1:
402 # logger.info("Enabling slice creation for site %s" % siteId(nodename))
405 # api.AdmUpdateSite(auth.auth, siteid[0], {"max_slices" : maxslices})
406 # except Exception, exc:
407 # logger.info("API: %s" % exc)
409 # logger.debug("Cant find site for %s. Cannot enable creation." % nodename)
412 logger.setLevel(logging.DEBUG)
413 ch = logging.StreamHandler()
414 ch.setLevel(logging.DEBUG)
415 formatter = logging.Formatter('logger - %(message)s')
416 ch.setFormatter(formatter)
417 logger.addHandler(ch)
418 #print getpcu("kupl2.ittc.ku.edu")
419 #print getpcu("planetlab1.cse.msu.edu")
420 #print getpcu("alice.cs.princeton.edu")
422 #nodeBootState("alice.cs.princeton.edu", "boot")
423 #freezeSite("alice.cs.princeton.edu")
424 print removeSliceCreation("alice.cs.princeton.edu")
425 #enableSliceCreation("alice.cs.princeton.edu", 1024)
426 #print getSiteNodes("princeton")
427 #print siteId("alice.cs.princeton.edu")
428 #print nodePOD("alice.cs.princeton.edu")
429 #print slices("princeton")
431 if __name__=="__main__":