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.10 2007/02/12 19:59:00 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."""
52 printUsage("not enough arguments; please provide loginbase")
57 printUsage("requires admin privs")
60 slices = api.GetSlices (auth, {'name':"%s_*"%loginbase},['name'])
61 slices = map(lambda x: x['name'],slices)
65 """Returns dict of PCU info of a given node."""
68 nodename = argv[0].lower()
70 printUsage("requires admin privs")
73 pcus = api.GetNodes(auth, [nodename], ['pcu_ids'])
75 pcus = map(lambda x: x['pcu_ids'],pcus)[0]
76 nodepcus = api.GetPCUs(auth,pcus)
82 def getSiteNodes(argv):
83 """Returns all site nodes for site id (loginbase)."""
86 printUsage("not enough arguments; please provide loginbase")
91 site_ids = api.GetSites(auth, {'login_base': "%s" % loginbase}, ['node_ids'])
92 if len(site_ids) == 1:
93 node_ids = site_ids[0]['node_ids']
94 nodes = api.GetNodes(auth,node_ids,['hostname'])
95 nodelist = map(lambda x: x['hostname'], nodes)
96 elif len(site_ids) == 0:
97 logger.info("getSiteNodes: can't find site %s" %loginbase)
101 def renewAllSlices (argv):
102 """Sets the expiration date of all slices to given date"""
106 # convert time string using fmt "%B %d %Y" to epoch integer
108 newexp = int(time.mktime(time.strptime(newexp,"%B %d %Y")))
109 except ValueError, e:
110 errormsg = """Expecting date to be in Month Day Year
112 new expiration date provided %s""" % newexp
116 slices = api.GetSlices(auth)
119 exp = int(slice['expires'])
120 olddate = time.asctime(time.localtime(exp))
121 slice_attributes = api.GetSliceAttributes(auth,slice['slice_attribute_ids'])
122 for slice_attribute in slice_attributes:
123 if slice_attribute['name'] == "enabled":
124 print "%s is suspended" % name
126 newdate = time.asctime(time.localtime(newexp))
127 ret = api.SliceRenew(auth,name,newexp)
129 print "failed to renew %s" %name
131 def nodeBootState(argv):
132 """Sets boot state of a node."""
136 printUsage("not enough arguments")
145 printUsage("requires admin privs")
148 node = api.GetNodes(auth, [nodename], ['node_id','boot_state'])
152 logger.info("%s boot_state=%s" %(nodename, node['boot_state']))
153 if len(argv) >=2 and not config.debug:
154 logger.info("Setting node %s boot_state=%s" %(nodename, state))
155 node_id = node['node_id']
156 api.UpdateNode(auth, node_id, {'boot_state': state})
157 except Exception, exc:
158 logger.info("nodeBootState: %s" % exc)
160 logger.info("Cant find node %s to toggle boot state" % nodename)
164 """Sends Ping Of Death to node."""
168 printUsage("not enough arguments")
173 printUsage("requires admin privs")
176 node = api.GetNodes(auth, [nodename], ['node_id'])
179 logger.info("Sending POD to %s" % nodename)
182 api.RebootNode(auth, node['node_id'])
183 except Exception, exc:
184 logger.info("nodePOD: %s" % exc)
186 logger.info("Cant find node %s to send POD." % nodename)
188 def suspendSlice(argv):
189 """Freeze specific slice."""
192 printUsage("requires admin privs")
196 logger.info("Suspending slice %s" % slice)
199 api.AddSliceAttribute(auth, slice, "enabled", "0")
200 except Exception, exc:
201 logger.info("suspendSlices: %s" % exc)
203 def suspendSlices(argv):
204 """Freeze all site slices."""
207 printUsage("requires admin privs")
210 if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
211 else: siteslices = slices(argv)
213 for slice in siteslices:
214 suspendSlice([slice])
216 def __enableSlice(slice):
217 logger.info("unfreezing slice %s" % slice['name'])
218 slice_attributes = api.GetSliceAttributes(auth,slice['slice_attribute_ids'])
219 for slice_attribute in slice_attributes:
220 if slice_attribute['name'] == "enabled":
221 api.DeleteSliceAttribute(auth, slice_attribute['slice_attribute_id'])
223 def enableSlice(arg):
224 """Enable suspended slice."""
227 printUsage("requires admin privs")
231 gSlices = {'name':slicename}
232 slice = api.GetSlices(auth,gSlices)
234 __enableSlice(slice[0])
236 logger.info("slice %s not found" % slicename)
238 def enableSlices(argv):
239 """Enable suspended site slices."""
243 printUsage("requires admin privs")
246 if argv[0].find(".") <> -1:
247 slices = api.GetSlices(auth,[siteId(argv)])
249 gSlices = {'name':"%s_*"%argv[0]}
250 slices = api.GetSlices(auth,gSlices)
255 def setSliceMax(argv):
256 """Set max_slices for Slice. Returns previous max_slices"""
259 printUsage("requires admin privs")
264 if name.find(".") <> -1:
265 site_ids = api.GetNodes(auth, [name], ['site_id'])
266 if len(site_ids) == 1:
267 site_id = [site_ids[0]['site_id']]
268 loginbase = api.GetSites (auth, site_id, ["login_base"])
270 printUsage("invalid hostname %s" % name)
273 site_ids = api.GetSites(auth, {'login_base': "%s" % name}, ['site_id'])
274 if len(site_ids) == 1:
275 siteid = site_ids[0]['site_id']
278 numslices = api.GetSites(auth, [siteid], ["max_slices"])[0]['max_slices']
280 api.UpdateSite(auth, siteid, {'max_slices': val})
281 logger.info("_SetSliceMax: %s max_slices was %d set to %d" % (loginbase,numslices,val))
283 except Exception, exc:
284 logger.info("_SetSliceMax: %s" % exc)
288 Usage: %s [-u user] [-p password] [-r role] CMD
291 -u PLC account username
292 -p PLC account password
297 def printUsage(error = None):
300 print "%s %s" %(sys.argv[0],error)
303 for name,function in funclist:
304 print "%20s\t%20s" % (name, function.__doc__)
314 (opts, argv) = getopt.getopt(sys.argv[1:], "u:p:r:h")
319 for (opt, optval) in opts:
333 password = getpass.getpass()
334 except (EOFError, KeyboardInterrupt):
338 auth['Username'] = user
339 auth['AuthMethod'] = "password"
340 auth['AuthString'] = password
343 cmd = functbl.get(argv[0], None)
348 logger.setLevel(logging.DEBUG)
349 ch = logging.StreamHandler()
350 ch.setLevel(logging.DEBUG)
351 formatter = logging.Formatter('logger - %(message)s')
352 ch.setFormatter(formatter)
353 logger.addHandler(ch)
354 result = cmd(argv[1:])
358 funclist = (("nodesDbg",nodesDbg),
362 ("siteNodes", getSiteNodes),
363 ("nodeBootState", nodeBootState),
364 ("nodePOD", nodePOD),
365 ("freezeSlice", suspendSlice),
366 ("unfreezeSlice", enableSlice),
367 ("freezeSlices", suspendSlices),
368 ("unfreezeSlices", enableSlices),
369 ("setSliceMax", setSliceMax),
370 ("renewAllSlices", renewAllSlices))
376 if __name__=="__main__":