3 # Helper functions that minipulate the PLC api.
5 # Faiyaz Ahmed <faiyaza@cs.princeton.edu>
6 # Copyright (C) 2006, 2007 The Trustees of Princeton University
8 # $Id: plc.py,v 1.6 2007/02/08 19:59:03 mef Exp $
11 from emailTxt import *
16 import getpass, getopt
19 logger = logging.getLogger("monitor")
20 XMLRPC_SERVER = 'https://www2.planet-lab.org/PLCAPI/'
21 api = xmlrpclib.Server(XMLRPC_SERVER, verbose=False, allow_none = True)
25 """Returns list of nodes in dbg as reported by PLC"""
29 allnodes = api.GetNodes(auth, None, ['hostname','boot_state'])
31 if node['boot_state'] == 'dbg': dbgNodes.append(node['hostname'])
32 logger.info("%d nodes in debug according to PLC." %len(dbgNodes))
37 """Returns loginbase for given nodename"""
41 site_ids = api.GetNodes(auth, [nodename], ['site_id'])
42 if len(site_ids) == 1:
43 site_id = [site_ids[0]['site_id']]
44 loginbase = api.GetSites (auth, site_id, ["login_base"])
45 return loginbase[0]['login_base']
48 """Returns list of slices for a site."""
50 global api, anon, auth
52 printUsage("not enough arguments; please provide loginbase")
57 printUsage("requires admin privs")
61 slices = api.GetSlices (auth, {'name':"%s_*"%loginbase})
66 slice_ids = api.GetSites(auth,{'login_base':loginbase},['slice_ids'])
68 slice_ids=slice_ids[0]
69 slice_ids=slice_ids['slice_ids']
70 slices = api.GetSlices(auth,slice_ids,['name'])
71 results = map(lambda x: x['name'],slices)
77 """Returns dict of PCU info of a given node."""
79 global api, anon, auth
80 nodename = argv[0].lower()
82 printUsage("requires admin privs")
85 pcus = api.GetNodes(auth, [nodename], ['pcu_ids'])
87 pcus = map(lambda x: x['pcu_ids'],pcus)[0]
88 nodepcus = api.GetPCUs(auth,pcus)
94 def getSiteNodes(argv):
95 """Returns all site nodes for site id (loginbase)."""
98 printUsage("not enough arguments; please provide loginbase")
103 site_ids = api.GetSites(auth, {'login_base': "%s" % loginbase}, ['node_ids'])
104 if len(site_ids) == 1:
105 node_ids = site_ids[0]['node_ids']
106 nodes = api.GetNodes(auth,node_ids,['hostname'])
107 nodelist = map(lambda x: x['hostname'], nodes)
108 elif len(site_ids) == 0:
109 logger.info("getSiteNodes: can't find site %s" %loginbase)
113 def renewAllSlices (argv):
114 """Sets the expiration date of all slices to given date"""
118 # convert time string using fmt "%B %d %Y" to epoch integer
120 newexp = int(time.mktime(time.strptime(newexp,"%B %d %Y")))
121 except ValueError, e:
122 errormsg = """Expecting date to be in Month Day Year
124 new expiration date provided %s""" % newexp
128 slices = api.GetSlices(auth)
131 exp = int(slice['expires'])
132 olddate = time.asctime(time.localtime(exp))
133 slice_attributes = api.GetSliceAttributes(auth,slice['slice_attribute_ids'])
134 for slice_attribute in slice_attributes:
135 if slice_attribute['name'] == "enabled":
136 print "%s is suspended" % name
139 newdate = time.asctime(time.localtime(newexp))
140 ret = api.SliceRenew(auth,name,newexp)
142 print "failed to renew %s" %name
144 def nodeBootState(argv):
145 """Sets boot state of a node."""
147 global api, anon, auth
149 printUsage("not enough arguments")
158 printUsage("requires admin privs")
161 node = api.GetNodes(auth, [nodename], ['node_id','boot_state'])
165 logger.info("%s boot_state=%s" %(nodename, node['boot_state']))
166 if len(argv) >=2 and not config.debug:
167 logger.info("Setting node %s boot_state=%s" %(nodename, state))
168 node_id = node['node_id']
169 api.UpdateNode(auth, node_id, {'boot_state': state})
170 except Exception, exc:
171 logger.info("nodeBootState: %s" % exc)
173 logger.info("Cant find node %s to toggle boot state" % nodename)
176 """Sends Ping Of Death to node."""
180 printUsage("not enough arguments")
185 printUsage("requires admin privs")
188 node = api.GetNodes(auth, [nodename], ['node_id'])
191 logger.info("Sending POD to %s" % nodename)
194 api.RebootNode(auth, node['node_id'])
195 except Exception, exc:
196 logger.info("nodePOD: %s" % exc)
198 logger.info("Cant find node %s to send POD." % nodename)
200 def suspendSlices(argv):
201 """Freeze all site slices."""
203 global api, anon, auth
205 printUsage("requires admin privs")
208 if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
209 else: siteslices = slices(argv)
211 for slice in siteslices:
212 logger.info("Suspending slice %s" % slice)
215 api.SliceAttributeAdd(auth, slice, "plc_slice_state",
216 {"state" : "suspended"})
217 except Exception, exc:
218 logger.info("suspendSlices: %s" % exc)
221 def enableSlices(argv):
222 """Enable suspended site slices."""
224 global api, anon, auth
226 printUsage("requires admin privs")
229 if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
230 else: siteslices = slices(argv)
232 for slice in siteslices:
233 logger.info("unfreezing slice %s" % slice)
234 api.SliceAttributeDelete(auth, slice, "plc_slice_state")
237 def removeSliceCreation(argv):
238 """Removes ability to create slices. Returns previous max_slices"""
240 global api, anon, auth
242 printUsage("requires admin privs")
246 if name.find(".") <> -1:
247 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
248 loginbase = siteId(name)
250 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})
253 numslices = api.AdmGetSites(auth, siteid, ["max_slices"])[0]['max_slices']
255 logger.info("Removing slice creation for site %s" % loginbase)
258 api.AdmUpdateSite(auth, siteid[0], {'max_slices': 0})
260 except Exception, exc:
261 logger.info("removeSliceCreation: %s" % exc)
263 logger.debug("Cant find site for %s. Cannot revoke creation." % loginbase)
265 def enableSliceCreation(argv):
268 global api, anon, auth
270 printUsage("requires admin privs")
274 printUsage("requires maxslice arg")
277 maxslices = int(argv[1])
279 if name.find(".") <> -1:
280 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
281 loginbase = siteId(name)
283 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})
287 logger.info("Enabling slice creation for site %s" % loginbase)
290 api.AdmUpdateSite(auth, siteid[0], {"max_slices" : maxslices})
291 except Exception, exc:
292 logger.info("API: %s" % exc)
294 logger.debug("Cant find site for %s. Cannot enable creation." % loginbase)
299 Usage: %s [-u user] [-p password] [-r role] CMD
302 -u PLC account username
303 -p PLC account password
308 def printUsage(error = None):
311 print "%s %s" %(sys.argv[0],error)
314 for name,function in funclist:
315 print "%20s\t%20s" % (name, function.__doc__)
318 global api, auth, anon
320 anon = {"AuthMethod":"anonymous"}
326 (opts, argv) = getopt.getopt(sys.argv[1:], "u:p:r:h")
331 for (opt, optval) in opts:
345 password = getpass.getpass()
346 except (EOFError, KeyboardInterrupt):
350 auth['Username'] = user
351 auth['AuthMethod'] = "password"
352 auth['AuthString'] = password
355 cmd = functbl.get(argv[0], None)
360 logger.setLevel(logging.DEBUG)
361 ch = logging.StreamHandler()
362 ch.setLevel(logging.DEBUG)
363 formatter = logging.Formatter('logger - %(message)s')
364 ch.setFormatter(formatter)
365 logger.addHandler(ch)
366 result = cmd(argv[1:])
370 funclist = (("nodesDbg",nodesDbg),
374 ("siteNodes", getSiteNodes),
375 ("nodeBootState", nodeBootState),
376 ("nodePOD", nodePOD),
377 ("freezeSlices", suspendSlices),
378 ("unfreezeSlices", enableSlices),
379 ("disableSliceCreation",removeSliceCreation),
380 ("enableSliceCreation", enableSliceCreation),
381 ("renewAllSlices", renewAllSlices))
387 if __name__=="__main__":