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