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.4 2007/02/01 14:25:56 mef Exp $
11 from emailTxt import *
16 import getpass, getopt
19 logger = logging.getLogger("monitor")
20 XMLRPC_SERVER = 'https://www.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"""
39 global api, anon, auth
41 site_id = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
43 loginbase = api.AnonAdmGetSites (anon, site_id, ["login_base"])
44 return loginbase[0]['login_base']
47 """Returns list of slices for a site."""
49 global api, anon, auth
52 printUsage("requires admin privs")
54 return api.SliceListNames (auth, loginbase)
57 """Returns dict of PCU info of a given node."""
59 global api, anon, auth
60 nodename = argv[0].lower()
62 printUsage("requires admin privs")
66 site_id = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
69 sitepcus = api.AdmGetSitePowerControlUnits(auth, site_id[0])
70 for sitepcu in sitepcus:
71 sitepcuports = api.AdmGetPowerControlUnitNodes(auth, sitepcu['pcu_id'])
72 for sitepcuport in sitepcuports:
73 node_id = [sitepcuport['node_id']]
74 node = api.AnonAdmGetNodes(anon,node_id,["hostname"])
78 hostname = node['hostname'].lower()
79 if hostname == nodename:
80 sitepcu['port_number']=sitepcuport['port_number']
83 except Exception, err:
84 logger.debug("getpcu: %s" % err)
87 logger.info("Cant find site for %s" % nodename)
90 def getSiteNodes(argv):
91 """Returns all site nodes for site id (loginbase)."""
92 global api, anon, auth
96 site_id = api.AnonAdmQuerySite(anon, {'site_loginbase': "%s" % loginbase})
97 node_ids = api.AnonAdmGetSiteNodes(anon, site_id)
98 for node in api.AnonAdmGetNodes(anon, node_ids["%s" % site_id[0]], ["hostname"]):
99 nodelist.append(node['hostname'])
100 except Exception, exc:
101 logger.info("getSiteNodes: %s" % exc)
105 def renewAllSlices (argv):
106 """Sets the expiration date of all slices to given date"""
107 global api, anon, auth
110 # convert time string using fmt "%B %d %Y" to epoch integer
112 newexp = int(time.mktime(time.strptime(newexp,"%B %d %Y")))
113 except ValueError, e:
114 errormsg = """Expecting date to be in Month Day Year
116 new expiration date provided %s""" % newexp
120 slices = api.GetSlices(auth)
123 exp = int(slice['expires'])
124 olddate = time.asctime(time.localtime(exp))
125 slice_attributes = api.GetSliceAttributes(auth,slice['slice_attribute_ids'])
126 for slice_attribute in slice_attributes:
127 if slice_attribute['name'] == "enabled":
128 print "%s is suspended" % name
131 newdate = time.asctime(time.localtime(newexp))
132 ret = api.SliceRenew(auth,name,newexp)
134 print "failed to renew %s" %name
136 def nodeBootState(argv):
137 """Sets boot state of a node."""
139 global api, anon, auth
141 printUsage("not enough arguments")
148 printUsage("requires admin privs")
151 node_id = api.AnonAdmQueryNode(anon, {'node_hostname' : nodename})
152 if len(node_id) == 1:
153 logger.info("Setting node %s to %s" %(nodename, state))
156 api.AdmUpdateNode(auth, node_id[0], {'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)
163 """Sends Ping Of Death to node."""
165 global api, anon, auth
168 printUsage("requires admin privs")
171 node_id = api.AnonAdmQueryNode(anon, {'node_hostname' : nodename})
172 if len(node_id) == 1:
173 logger.info("Sending POD to %s" % nodename)
176 api.AdmRebootNode(auth, node_id[0])
177 except Exception, exc:
178 logger.info("nodePOD: %s" % exc)
180 logger.info("Cant find node %s to send POD." % nodename)
182 def suspendSlices(argv):
183 """Freeze all site slices."""
185 global api, anon, auth
187 printUsage("requires admin privs")
190 if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
191 else: siteslices = slices(argv)
193 for slice in siteslices:
194 logger.info("Suspending slice %s" % slice)
197 api.SliceAttributeAdd(auth, slice, "plc_slice_state",
198 {"state" : "suspended"})
199 except Exception, exc:
200 logger.info("suspendSlices: %s" % exc)
203 def enableSlices(argv):
204 """Enable suspended site slices."""
206 global api, anon, auth
208 printUsage("requires admin privs")
211 if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
212 else: siteslices = slices(argv)
214 for slice in siteslices:
215 logger.info("unfreezing slice %s" % slice)
216 api.SliceAttributeDelete(auth, slice, "plc_slice_state")
219 def removeSliceCreation(argv):
220 """Removes ability to create slices. Returns previous max_slices"""
222 global api, anon, auth
224 printUsage("requires admin privs")
228 if name.find(".") <> -1:
229 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
230 loginbase = siteId(name)
232 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})
235 numslices = api.AdmGetSites(auth, siteid, ["max_slices"])[0]['max_slices']
237 logger.info("Removing slice creation for site %s" % loginbase)
240 api.AdmUpdateSite(auth, siteid[0], {'max_slices': 0})
242 except Exception, exc:
243 logger.info("removeSliceCreation: %s" % exc)
245 logger.debug("Cant find site for %s. Cannot revoke creation." % loginbase)
247 def enableSliceCreation(argv):
250 global api, anon, auth
252 printUsage("requires admin privs")
256 printUsage("requires maxslice arg")
259 maxslices = int(argv[1])
261 if name.find(".") <> -1:
262 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
263 loginbase = siteId(name)
265 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})
269 logger.info("Enabling slice creation for site %s" % loginbase)
272 api.AdmUpdateSite(auth, siteid[0], {"max_slices" : maxslices})
273 except Exception, exc:
274 logger.info("API: %s" % exc)
276 logger.debug("Cant find site for %s. Cannot enable creation." % loginbase)
281 Usage: %s [-u user] [-p password] [-r role] CMD
284 -u PLC account username
285 -p PLC account password
290 def printUsage(error = None):
293 print "%s %s" %(sys.argv[0],error)
296 for name,function in funclist:
297 print "%20s\t%20s" % (name, function.__doc__)
300 global api, auth, anon
302 anon = {"AuthMethod":"anonymous"}
308 (opts, argv) = getopt.getopt(sys.argv[1:], "u:p:r:h")
313 for (opt, optval) in opts:
327 password = getpass.getpass()
328 except (EOFError, KeyboardInterrupt):
332 auth['Username'] = user
333 auth['AuthMethod'] = "password"
334 auth['AuthString'] = password
337 cmd = functbl.get(argv[0], None)
342 logger.setLevel(logging.DEBUG)
343 ch = logging.StreamHandler()
344 ch.setLevel(logging.DEBUG)
345 formatter = logging.Formatter('logger - %(message)s')
346 ch.setFormatter(formatter)
347 logger.addHandler(ch)
348 result = cmd(argv[1:])
352 funclist = (("nodesDbg",nodesDbg),
356 ("siteNodes", getSiteNodes),
357 ("nodeBootState", nodeBootState),
358 ("nodePOD", nodePOD),
359 ("freezeSlices", suspendSlices),
360 ("unfreezeSlices", enableSlices),
361 ("disableSliceCreation",removeSliceCreation),
362 ("enableSliceCreation", enableSliceCreation),
363 ("renewAllSlices", renewAllSlices))
369 if __name__=="__main__":