Changed 'import auth' statements to use plc.py or monitorconfig.py
[monitor.git] / plc.py
1 #
2 # plc.py
3 #
4 # Helper functions that minipulate the PLC api.
5
6 # Faiyaz Ahmed <faiyaza@cs.princeton.edu
7 #
8 # $Id: plc.py,v 1.18 2007/08/29 17:26:50 soltesz Exp $
9 #
10
11 import xml, xmlrpclib
12 import logging
13 import time
14 import traceback
15 try:
16         from config import config
17         config = config()
18         debug = config.debug
19 except:
20         debug = False
21 logger = logging.getLogger("monitor")
22         
23 class Auth:
24         def __init__(self):
25                 self.auth = {'AuthMethod': "anonymous"}
26
27 # NOTE: this host is used by default when there are no auth files.
28 XMLRPC_SERVER="https://boot.planet-lab.org/PLCAPI/"
29
30 # NOTE: by default, use anonymous access, but if auth files are 
31 #       configured, use them, with their auth definitions.
32 auth = Auth()
33 try:
34         import monitorconfig
35         auth.auth = monitorconfig.API_AUTH
36         auth.server = monitorconfig.API_SERVER
37 except:
38         try:
39                 import auth
40                 auth.server = auth.plc
41         except:
42                 auth.server = XMLRPC_SERVER
43
44 api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
45
46 class PLC:
47         def __init__(self, auth, url):
48                 self.auth = auth
49                 self.url = url
50                 self.api = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
51
52         def __getattr__(self, name):
53                 method = getattr(self.api, name)
54                 if method is None:
55                         raise AssertionError("method does not exist")
56
57                 return lambda *params : method(self.auth, *params)
58
59         def __repr__(self):
60                 return self.api.__repr__()
61
62 def getAPI(url):
63         return xmlrpclib.Server(url, verbose=False, allow_none=True)
64
65 def getAuthAPI():
66         return PLC(monitorconfig.API_AUTH, monitorconfig.API_SERVER)
67
68 '''
69 Returns list of nodes in dbg as reported by PLC
70 '''
71 def nodesDbg():
72         dbgNodes = []
73         api = xmlrpclib.Server(auth.server, verbose=False)
74         anon = {'AuthMethod': "anonymous"}
75         for node in api.GetNodes(anon, {"boot_state":"dbg"},["hostname"]):
76                 dbgNodes.append(node['hostname'])
77         logger.info("%s nodes in debug according to PLC." %len(dbgNodes))
78         return dbgNodes
79
80
81 '''
82 Returns loginbase for given nodename
83 '''
84 def siteId(nodename):
85         api = xmlrpclib.Server(auth.server, verbose=False)
86         anon = {'AuthMethod': "anonymous"}
87         site_id = api.GetNodes (anon, {"hostname": nodename}, ['site_id'])
88         if len(site_id) == 1:
89                 loginbase = api.GetSites (anon, site_id[0], ["login_base"])
90                 return loginbase[0]['login_base']
91
92 '''
93 Returns list of slices for a site.
94 '''
95 def slices(loginbase):
96         siteslices = []
97         api = xmlrpclib.Server(auth.server, verbose=False)
98         sliceids = api.GetSites (auth.auth, {"login_base" : loginbase}, ["slice_ids"])[0]['slice_ids']
99         for slice in api.GetSlices(auth.auth, {"slice_id" : sliceids}, ["name"]):
100                 siteslices.append(slice['name'])
101         return siteslices
102
103 '''
104 Returns dict of PCU info of a given node.
105 '''
106 def getpcu(nodename):
107         api = xmlrpclib.Server(auth.server, verbose=False)
108         anon = {'AuthMethod': "anonymous"}
109         nodeinfo = api.GetNodes(auth.auth, {"hostname": nodename}, ["pcu_ids", "ports"])[0]
110         if nodeinfo['pcu_ids']:
111                 sitepcu = api.GetPCUs(auth.auth, nodeinfo['pcu_ids'])[0]
112                 sitepcu[nodename] = nodeinfo["ports"][0]
113                 return sitepcu
114         else:
115                 logger.info("%s doesn't have PCU" % nodename)
116                 return False
117
118 def GetPCUs(filter=None, fields=None):
119         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
120         pcu_list = api.GetPCUs(auth.auth, filter, fields)
121         return pcu_list 
122
123 '''
124 Returns all site nodes for site id (loginbase).
125 '''
126 def getSiteNodes(loginbase, fields=None):
127         api = xmlrpclib.Server(auth.server, verbose=False)
128         nodelist = []
129         anon = {'AuthMethod': "anonymous"}
130         try:
131                 nodeids = api.GetSites(anon, {"login_base": loginbase}, fields)[0]['node_ids']
132                 for node in api.GetNodes(anon, {"node_id": nodeids}, ['hostname']):
133                         nodelist.append(node['hostname'])
134         except Exception, exc:
135                 logger.info("getSiteNodes:  %s" % exc)
136                 print "getSiteNodes:  %s" % exc
137         return nodelist
138
139 def getPersons(filter=None, fields=None):
140         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
141         persons = []
142         try:
143                 persons = api.GetPersons(auth.auth, filter, fields)
144         except Exception, exc:
145                 print "getPersons:  %s" % exc
146                 logger.info("getPersons:  %s" % exc)
147         return persons
148
149 def getSites(filter=None, fields=None):
150         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
151         sites = []
152         anon = {'AuthMethod': "anonymous"}
153         try:
154                 #sites = api.GetSites(anon, filter, fields)
155                 sites = api.GetSites(auth.auth, filter, fields)
156         except Exception, exc:
157                 traceback.print_exc()
158                 print "getSites:  %s" % exc
159                 logger.info("getSites:  %s" % exc)
160         return sites
161
162 def getSiteNodes2(loginbase):
163         api = xmlrpclib.Server(auth.server, verbose=False)
164         nodelist = []
165         anon = {'AuthMethod': "anonymous"}
166         try:
167                 nodeids = api.GetSites(anon, {"login_base": loginbase})[0]['node_ids']
168                 nodelist += getNodes({'node_id':nodeids})
169         except Exception, exc:
170                 logger.info("getSiteNodes2:  %s" % exc)
171         return nodelist
172
173 def getNodeNetworks(filter=None):
174         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
175         nodenetworks = api.GetNodeNetworks(auth.auth, filter, None)
176         return nodenetworks
177
178 def getNodes(filter=None, fields=None):
179         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
180         nodes = api.GetNodes(auth.auth, filter, fields) 
181                         #['boot_state', 'hostname', 
182                         #'site_id', 'date_created', 'node_id', 'version', 'nodenetwork_ids',
183                         #'last_updated', 'peer_node_id', 'ssh_rsa_key' ])
184         return nodes
185
186 '''
187 Sets boot state of a node.
188 '''
189 def nodeBootState(nodename, state):
190         api = xmlrpclib.Server(auth.server, verbose=False)
191         try:
192                 return api.UpdateNode(auth.auth, nodename, {'boot_state': state})
193         except Exception, exc:
194                 logger.info("nodeBootState:  %s" % exc)
195
196 def updateNodeKey(nodename, key):
197         api = xmlrpclib.Server(auth.server, verbose=False)
198         try:
199                 return api.UpdateNode(auth.auth, nodename, {'key': key})
200         except Exception, exc:
201                 logger.info("updateNodeKey:  %s" % exc)
202
203 '''
204 Sends Ping Of Death to node.
205 '''
206 def nodePOD(nodename):
207         api = xmlrpclib.Server(auth.server, verbose=False)
208         logger.info("Sending POD to %s" % nodename)
209         try:
210                 if not debug:
211                         return api.RebootNode(auth.auth, nodename)
212         except Exception, exc:
213                         logger.info("nodePOD:  %s" % exc)
214
215 '''
216 Freeze all site slices.
217 '''
218 def suspendSlices(nodename):
219         api = xmlrpclib.Server(auth.server, verbose=False)
220         for slice in slices(siteId(nodename)):
221                 logger.info("Suspending slice %s" % slice)
222                 try:
223                         if not debug:
224                                 api.AddSliceAttribute(auth.auth, slice, "enabled", "0")
225                 except Exception, exc:
226                         logger.info("suspendSlices:  %s" % exc)
227
228 def enableSlices(nodename):
229         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
230         for slice in slices(siteId(nodename)):
231                 logger.info("Enabling slices %s" % slice)
232                 try:
233                         if not debug:
234                                 slice_list = api.GetSlices(auth.auth, {'name': slice}, None)
235                                 if len(slice_list) == 0:
236                                         return
237                                 slice_id = slice_list[0]['slice_id']
238                                 l_attr = api.GetSliceAttributes(auth.auth, {'slice_id': slice_id}, None)
239                                 for attr in l_attr:
240                                         if "enabled" == attr['name'] and attr['value'] == "0":
241                                                 logger.info("Deleted enable=0 attribute from slice %s" % slice)
242                                                 api.DeleteSliceAttribute(auth.auth, attr['slice_attribute_id'])
243                 except Exception, exc:
244                         logger.info("enableSlices: %s" % exc)
245                         print "exception: %s" % exc
246
247 #I'm commenting this because this really should be a manual process.  
248 #'''
249 #Enable suspended site slices.
250 #'''
251 #def enableSlices(nodename, slicelist):
252 #       api = xmlrpclib.Server(auth.server, verbose=False)
253 #       for slice in  slices(siteId(nodename)):
254 #               logger.info("Suspending slice %s" % slice)
255 #               api.SliceAttributeAdd(auth.auth, slice, "plc_slice_state", {"state" : "suspended"})
256 #
257 def enableSliceCreation(nodename):
258         api = xmlrpclib.Server(auth.server, verbose=False, allow_none=True)
259         try:
260                 loginbase = siteId(nodename)
261                 logger.info("Enabling slice creation for site %s" % loginbase)
262                 if not debug:
263                         logger.info("\tcalling UpdateSite(%s, enabled=True)" % loginbase)
264                         api.UpdateSite(auth.auth, loginbase, {'enabled': True})
265         except Exception, exc:
266                 print "ERROR: enableSliceCreation:  %s" % exc
267                 logger.info("ERROR: enableSliceCreation:  %s" % exc)
268
269 '''
270 Removes ability to create slices. Returns previous max_slices
271 '''
272 def removeSliceCreation(nodename):
273         print "removeSliceCreation(%s)" % nodename
274         api = xmlrpclib.Server(auth.server, verbose=False)
275         try:
276                 loginbase = siteId(nodename)
277                 #numslices = api.GetSites(auth.auth, {"login_base": loginbase}, 
278                 #               ["max_slices"])[0]['max_slices']
279                 logger.info("Removing slice creation for site %s" % loginbase)
280                 if not debug:
281                         #api.UpdateSite(auth.auth, loginbase, {'max_slices': 0})
282                         api.UpdateSite(auth.auth, loginbase, {'enabled': False})
283         except Exception, exc:
284                 logger.info("removeSliceCreation:  %s" % exc)
285
286 '''
287 QED
288 '''
289 #def enableSliceCreation(nodename, maxslices):
290 #       api = xmlrpclib.Server(auth.server, verbose=False)
291 #       anon = {'AuthMethod': "anonymous"}
292 #       siteid = api.AnonAdmQuerySite (anon, {"node_hostname": nodename})
293 #       if len(siteid) == 1:
294 #               logger.info("Enabling slice creation for site %s" % siteId(nodename))
295 #               try:
296 #                       if not debug:
297 #                               api.AdmUpdateSite(auth.auth, siteid[0], {"max_slices" : maxslices})
298 #               except Exception, exc:
299 #                       logger.info("API:  %s" % exc)
300 #       else:
301 #               logger.debug("Cant find site for %s.  Cannot enable creation." % nodename)
302
303 def main():
304         logger.setLevel(logging.DEBUG)
305         ch = logging.StreamHandler()
306         ch.setLevel(logging.DEBUG)
307         formatter = logging.Formatter('logger - %(message)s')
308         ch.setFormatter(formatter)
309         logger.addHandler(ch)
310         #print getpcu("kupl2.ittc.ku.edu")
311         #print getpcu("planetlab1.cse.msu.edu")
312         #print getpcu("alice.cs.princeton.edu")
313         #print nodesDbg()
314         #nodeBootState("alice.cs.princeton.edu", "boot")
315         #freezeSite("alice.cs.princeton.edu")
316         print removeSliceCreation("alice.cs.princeton.edu")
317         #enableSliceCreation("alice.cs.princeton.edu", 1024)
318         #print getSiteNodes("princeton")
319         #print siteId("alice.cs.princeton.edu")
320         #print nodePOD("alice.cs.princeton.edu")
321         #print slices("princeton")
322
323 if __name__=="__main__":
324         main()