check if maxslices arg is pased to enableSliceCreation
[monitor.git] / plc.py
1 #!/bin/env python
2 #
3 # Helper functions that minipulate the PLC api.
4
5 # Faiyaz Ahmed <faiyaza@cs.princeton.edu>
6 # Copyright (C) 2006, 2007 The Trustees of Princeton University
7 #
8 # $Id: plc.py,v 1.2 2007/01/24 19:29:44 mef Exp $
9 #
10
11 from emailTxt import *
12 import xml, xmlrpclib
13 import logging
14 import time
15 import config
16 import getpass, getopt
17 import sys
18
19 logger = logging.getLogger("monitor")
20 XMLRPC_SERVER = 'https://www.planet-lab.org/PLCAPI/'
21 api = xmlrpclib.Server(XMLRPC_SERVER, verbose=False)
22 anon = None
23 auth = None
24
25 def nodesDbg(argv):
26         """Returns list of nodes in dbg as reported by PLC"""
27
28         global api, anon, auth
29         dbgNodes = []
30         allnodes = api.AnonAdmGetNodes(anon, [], ['hostname','boot_state'])
31         for node in allnodes:
32                 if node['boot_state'] == 'dbg': dbgNodes.append(node['hostname'])
33         logger.info("%s nodes in debug according to PLC." %len(dbgNodes))
34         return dbgNodes
35
36
37 def siteId(argv):
38         """Returns loginbase for given nodename"""
39
40         global api, anon, auth
41         nodename = argv[0]
42         site_id = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
43         if len(site_id) == 1:
44                 loginbase = api.AnonAdmGetSites (anon, site_id, ["login_base"])
45                 return loginbase[0]['login_base']
46
47 def slices(argv):
48         """Returns list of slices for a site."""
49
50         global api, anon, auth
51         loginbase = argv[0]
52         if auth is None:
53                 printUsage("requires admin privs")
54                 sys.exit(1)
55         return api.SliceListNames (auth, loginbase)
56
57 def getpcu(argv):
58         """Returns dict of PCU info of a given node."""
59
60         global api, anon, auth
61         nodename = argv[0].lower()
62         if auth is None:
63                 printUsage("requires admin privs")
64                 sys.exit(1)
65
66         nodes = []
67         site_id = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
68         if len(site_id) == 1:
69                 try:
70                         sitepcus = api.AdmGetSitePowerControlUnits(auth, site_id[0])
71                         for sitepcu in sitepcus:
72                                 sitepcuports = api.AdmGetPowerControlUnitNodes(auth, sitepcu['pcu_id'])
73                                 for sitepcuport in sitepcuports:
74                                         node_id = [sitepcuport['node_id']]
75                                         node = api.AnonAdmGetNodes(anon,node_id,["hostname"])
76                                         if len(node)==0:
77                                                 continue
78                                         node = node[0]
79                                         hostname = node['hostname'].lower()
80                                         if hostname == nodename:
81                                                 sitepcu['port_number']=sitepcuport['port_number']
82                                                 return sitepcu
83
84                 except Exception, err:
85                         logger.debug("getpcu: %s" % err)
86                         return
87         else:
88                 logger.info("Cant find site for %s" % nodename)
89
90
91 def getSiteNodes(argv):
92         """Returns all site nodes for site id (loginbase)."""
93         global api, anon, auth
94         loginbase = argv[0]
95         nodelist = []
96         try:
97                 site_id = api.AnonAdmQuerySite(anon, {'site_loginbase': "%s" % loginbase})
98                 node_ids = api.AnonAdmGetSiteNodes(anon, site_id)
99                 for node in api.AnonAdmGetNodes(anon, node_ids["%s" % site_id[0]], ["hostname"]):
100                         nodelist.append(node['hostname'])
101         except Exception, exc:
102                 logger.info("getSiteNodes:  %s" % exc)
103         nodelist.sort()
104         return nodelist
105
106 def nodeBootState(argv):
107         """Sets boot state of a node."""
108
109         global api, anon, auth
110         if len(argv) <> 2:
111                 printUsage("not enough arguments")
112                 sys.exit(1)
113                 
114         nodename = argv[0]
115         state = argv[1]
116         
117         if auth is None:
118                 printUsage("requires admin privs")
119                 sys.exit(1)
120
121         node_id = api.AnonAdmQueryNode(anon, {'node_hostname' : nodename})
122         if len(node_id) == 1:
123                 logger.info("Setting node %s to %s" %(nodename, state))
124                 try:
125                         if not config.debug:
126                                 api.AdmUpdateNode(auth, node_id[0], {'boot_state': state})
127                 except Exception, exc:
128                         logger.info("nodeBootState:  %s" % exc)
129         else:
130                 logger.info("Cant find node %s to toggle boot state" % nodename)
131
132 def nodePOD(argv):
133         """Sends Ping Of Death to node."""
134
135         global api, anon, auth
136         nodename = argv[0]
137         if auth is None:
138                 printUsage("requires admin privs")
139                 sys.exit(1)
140
141         node_id = api.AnonAdmQueryNode(anon, {'node_hostname' : nodename})
142         if len(node_id) == 1:
143                 logger.info("Sending POD to %s" % nodename)
144                 try:
145                         if not config.debug:
146                                 api.AdmRebootNode(auth, node_id[0])
147                 except Exception, exc:
148                         logger.info("nodePOD:  %s" % exc)
149         else:
150                 logger.info("Cant find node %s to send POD." % nodename)
151
152 def suspendSlices(argv):
153         """Freeze all site slices."""
154
155         global api, anon, auth
156         if auth is None:
157                 printUsage("requires admin privs")
158                 sys.exit(1)
159
160         if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
161         else: siteslices = slices(argv)
162
163         for slice in siteslices:
164                 logger.info("Suspending slice %s" % slice)
165                 try:
166                         if not config.debug:
167                                 api.SliceAttributeAdd(auth, slice, "plc_slice_state", 
168                                 {"state" : "suspended"})
169                 except Exception, exc:
170                         logger.info("suspendSlices:  %s" % exc)
171
172
173 def enableSlices(argv):
174         """Enable suspended site slices."""
175
176         global api, anon, auth
177         if auth is None:
178                 printUsage("requires admin privs")
179                 sys.exit(1)
180
181         api = xmlrpclib.Server(XMLRPC_SERVER, verbose=False)
182
183         if argv[0].find(".") <> -1: siteslices = slices([siteId(argv)])
184         else: siteslices = slices(argv)
185
186         for slice in siteslices:
187                 logger.info("unfreezing slice %s" % slice)
188                 api.SliceAttributeDelete(auth, slice, "plc_slice_state")
189
190
191 def removeSliceCreation(argv):
192         """Removes ability to create slices. Returns previous max_slices"""
193
194         global api, anon, auth
195         if auth is None:
196                 printUsage("requires admin privs")
197                 sys.exit(1)
198
199         name = argv[0]
200         if name.find(".") <> -1:
201                 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
202                 loginbase = siteId(name)
203         else:
204                 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})          
205                 loginbase = name
206
207         numslices = api.AdmGetSites(auth, siteid, ["max_slices"])[0]['max_slices']
208         if len(siteid) == 1:
209                 logger.info("Removing slice creation for site %s" % loginbase)
210                 try:
211                         if not config.debug:
212                                 api.AdmUpdateSite(auth, siteid[0], {'max_slices': 0})
213                         return numslices
214                 except Exception, exc:
215                         logger.info("removeSliceCreation:  %s" % exc)
216         else:
217                 logger.debug("Cant find site for %s.  Cannot revoke creation." % loginbase)
218
219 def enableSliceCreation(argv):
220         """QED"""
221
222         global api, anon, auth
223         if auth is None:
224                 printUsage("requires admin privs")
225                 sys.exit(1)
226
227         if len(argv) <= 2:
228                 printUsage("requires maxslice arg")
229                 sys.exit(1)
230
231         maxslices = int(argv[1])
232         name = argv[0]
233         if name.find(".") <> -1:
234                 siteid = api.AnonAdmQuerySite (anon, {"node_hostname": name})
235                 loginbase = siteId(name)
236         else:
237                 siteid = api.AnonAdmQuerySite (anon, {"site_loginbase": name})          
238                 loginbase = name
239
240         if len(siteid) == 1:
241                 logger.info("Enabling slice creation for site %s" % loginbase)
242                 try:
243                         if not config.debug:
244                                 api.AdmUpdateSite(auth, siteid[0], {"max_slices" : maxslices})
245                 except Exception, exc:
246                         logger.info("API:  %s" % exc)
247         else:
248                 logger.debug("Cant find site for %s.  Cannot enable creation." % loginbase)
249
250
251
252 USAGE = """
253 Usage: %s [-u user] [-p password] [-r role] CMD
254
255 Options:
256 -u      PLC account username
257 -p      PLC account password
258 -r      PLC account role
259 -h      This message
260 """ % sys.argv[0]
261
262 def printUsage(error = None):
263         global funclist
264         if error <> None:
265                 print "%s %s" %(sys.argv[0],error)
266         print USAGE
267         print "CMD:"
268         for name,function in funclist:
269                 print "%20s\t%20s" % (name, function.__doc__)
270         
271 def main():
272         global api, auth, anon
273
274         anon = {"AuthMethod":"anonymous"}
275         auth = None
276         user = None
277         password = None
278         role = 'admin'
279
280         (opts, argv) = getopt.getopt(sys.argv[1:], "u:p:r:h")
281         if len(argv)==0:
282                 printUsage()
283                 sys.exit(1)
284
285         for (opt, optval) in opts:
286                 if opt == '-u':
287                         user = optval
288                 elif opt == '-p':
289                         password = optval
290                 elif opt == '-r':
291                         role = optval
292                 elif opt == '-h':
293                         print USAGE
294                         sys.exit(0)
295
296         if user <> None:
297                 if password is None:
298                         try:
299                                 password = getpass.getpass()
300                         except (EOFError, KeyboardInterrupt):
301                                 print( "" )
302                                 sys.exit(1)
303                 auth = {}
304                 auth['Username'] = user
305                 auth['AuthMethod'] = "password"
306                 auth['AuthString'] = password
307                 auth['Role'] = role
308
309         cmd = functbl.get(argv[0], None)
310         if cmd is None:
311                 printUsage()
312                 sys.exit(1)
313
314         logger.setLevel(logging.DEBUG)
315         ch = logging.StreamHandler()
316         ch.setLevel(logging.DEBUG)
317         formatter = logging.Formatter('logger - %(message)s')
318         ch.setFormatter(formatter)
319         logger.addHandler(ch)
320         result = cmd(argv[1:])
321         print result
322
323 funclist = (("nodesDbg",nodesDbg),
324             ("siteId", siteId),
325             ("slices", slices),
326             ("pcu", getpcu),
327             ("siteNodes", getSiteNodes),
328             ("nodeBootState", nodeBootState),
329             ("nodePOD", nodePOD),
330             ("freezeSlices", suspendSlices),
331             ("unfreezeSlices", enableSlices),
332             ("disableSliceCreation",removeSliceCreation),
333             ("enableSliceCreation", enableSliceCreation))
334
335 functbl = {}
336 for f in funclist:
337         functbl[f[0]]=f[1]
338
339 if __name__=="__main__":
340         import reboot
341         main()