Add a retry to the apc_reboot() for which there are different models.
[monitor.git] / reboot.py
1 #!/usr/bin/python
2 #
3 # Reboot specified nodes
4 #
5
6 import getpass, getopt
7 import os, sys
8 import xml, xmlrpclib
9 import errno, time, traceback
10 import urllib2
11 import threading, popen2
12 import array, struct
13 #from socket import *
14 import socket
15 import plc
16
17 plc_lock = threading.Lock()
18
19 # Use our versions of telnetlib and pyssh
20 sys.path.insert(0, os.path.dirname(sys.argv[0]))
21 import telnetlib
22 sys.path.insert(0, os.path.dirname(sys.argv[0]) + "/pyssh")    
23 import pyssh
24
25 # Timeouts in seconds
26 TELNET_TIMEOUT = 30
27
28 # Event class ID from pcu events
29 #NODE_POWER_CONTROL = 3
30
31 # Monitor user ID
32 #MONITOR_USER_ID = 11142
33
34 import logging
35 logger = logging.getLogger("monitor")
36 verbose = 1
37 #dryrun = 0;
38
39 class ExceptionNotFound(Exception): pass
40 class ExceptionPassword(Exception): pass
41 class ExceptionTimeout(Exception): pass
42 class ExceptionPrompt(Exception): pass
43 class ExceptionPort(Exception): pass
44
45 def telnet_answer(telnet, expected, buffer):
46         global verbose
47
48         output = telnet.read_until(expected, TELNET_TIMEOUT)
49         #if verbose:
50         #       logger.debug(output)
51         if output.find(expected) == -1:
52                 raise ExceptionNotFound, "'%s' not found" % expected
53         else:
54                 telnet.write(buffer + "\r\n")
55
56
57 # PCU has model, host, preferred-port, user, passwd, 
58
59 class PCUExpect:
60         def __init__(self, protocol, verbose, dryrun):
61                 self.verbose = verbose
62                 self.protocol = protocol
63                 self.dryrun = dryrun
64
65         def telnet_answer(telnet, expected, buffer):
66                 global verbose
67
68                 output = telnet.read_until(expected, TELNET_TIMEOUT)
69                 #if verbose:
70                 #       logger.debug(output)
71                 if output.find(expected) == -1:
72                         raise ExceptionNotFound, "'%s' not found" % expected
73                 else:
74                         telnet.write(buffer + "\r\n")
75         
76         def _run(self, host, user, passwd, node_port, protocols):
77                 self.run()
78
79         def run(self):
80                 pass
81                 
82         
83
84 def ipal_reboot(ip, password, port, dryrun):
85         global verbose
86         global plc_lock
87
88
89         telnet = None
90
91         try:
92                 #plc_lock.acquire()
93                 #print "lock acquired"
94
95                 #try:
96                         #telnet = telnetlib.Telnet(ip) # , timeout=TELNET_TIMEOUT)
97                 telnet = telnetlib.Telnet(ip, timeout=TELNET_TIMEOUT)
98                 #except:
99                 #       import traceback
100                 #       traceback.print_exc()
101
102
103                 telnet.set_debuglevel(verbose)
104
105                 # XXX Some iPals require you to hit Enter a few times first
106                 telnet_answer(telnet, "Password >", "\r\n\r\n")
107
108                 # Login
109                 telnet_answer(telnet, "Password >", password)
110
111                 # XXX Some iPals require you to hit Enter a few times first
112                 telnet.write("\r\n\r\n")
113
114                 # P# - Pulse relay
115                 if not dryrun:
116                         telnet_answer(telnet, "Enter >", "P%d" % port)
117
118                 telnet.read_until("Enter >", TELNET_TIMEOUT)
119
120                 # Close
121                 telnet.close()
122
123                 #print "lock released"
124                 #plc_lock.release()
125                 return 0
126
127         except EOFError, err:
128                 if verbose:
129                         logger.debug("ipal_reboot: EOF")
130                         logger.debug(err)
131                 telnet.close()
132                 import traceback
133                 traceback.print_exc()
134                 #print "lock released"
135                 #plc_lock.release()
136                 return errno.ECONNRESET
137         except socket.error, err:
138                 logger.debug("ipal_reboot: Socket Error")
139                 logger.debug(err)
140                 import traceback
141                 traceback.print_exc()
142
143                 return errno.ETIMEDOUT
144                 
145         except Exception, err:
146                 if verbose:
147                         logger.debug("ipal_reboot: Exception")
148                         logger.debug(err)
149                 if telnet:
150                         telnet.close()
151                 import traceback
152                 traceback.print_exc()
153                 #print "lock released"
154                 #plc_lock.release()
155                 return  "ipal error"
156
157 def apc_reboot_original(ip, username, password, port, protocol, dryrun):
158         global verbose
159
160         transport = None
161
162         # TODO: I may need to differentiate between different models of APC
163         # hardware...
164         #       for instance, the original code didn't work for:
165         #               planetdev03.fm.intel.com
166         #                       American Power Conversion               
167         #                                       Network Management Card AOS      v3.3.0
168         #                       (c) Copyright 2005 All Rights Reserved  
169         #                                       Rack PDU APP                     v3.3.1
170
171
172         try:
173                 #if "ssh" in protocol:
174                 if "22" in protocol and protocol['22'] == "open":
175                         transport = pyssh.Ssh(username, ip)
176                         transport.open()
177                         # Login
178                         telnet_answer(transport, "password:", password)
179                 #elif "telnet" in protocol:
180                 elif "23" in protocol and protocol['23'] == "open":
181                         transport = telnetlib.Telnet(ip, timeout=TELNET_TIMEOUT)
182                         #transport = telnetlib.Telnet(ip)
183                         transport.set_debuglevel(verbose)
184                         # Login
185                         telnet_answer(transport, "User Name", username)
186                         telnet_answer(transport, "Password", password)
187                 else:
188                         logger.debug("Unknown protocol %s" %protocol)
189                         raise "Closed protocol ports!"
190
191
192                 # 1- Device Manager
193                 # 2- Network
194                 # 3- System
195                 # 4- Logout
196
197                 # 1- Device Manager
198                 telnet_answer(transport, "\r\n> ", "1")
199
200                 # 1- Phase Monitor/Configuration
201                 # 2- Outlet Restriction Configuration
202                 # 3- Outlet Control/Config
203                 # 4- Power Supply Status
204
205                 # 3- Outlet Control/Config
206                 #telnet_answer(transport, "\r\n> ", "2")
207                 #telnet_answer(transport, "\r\n> ", "1")
208
209                 # 3- Outlet Control/Config
210                 telnet_answer(transport, "\r\n> ", "3")
211
212                 # 1- Outlet 1
213                 # 2- Outlet 2
214                 # ...
215
216                 # n- Outlet n
217                 telnet_answer(transport, "\r\n> ", str(port))
218                 
219                 # 1- Control Outlet
220                 # 2- Configure Outlet
221
222                 # 1- Control Outlet
223                 telnet_answer(transport, "\r\n> ", "1")
224
225                 # 1- Immediate On                         
226                 # 2- Immediate Off                       
227                 # 3- Immediate Reboot             
228                 # 4- Delayed On                         
229                 # 5- Delayed Off                           
230                 # 6- Delayed Reboot                     
231                 # 7- Cancel                                     
232
233                 # 3- Immediate Reboot             
234                 telnet_answer(transport, "\r\n> ", "3")
235
236                 if not dryrun:
237                         telnet_answer(transport, 
238                                 "Enter 'YES' to continue or <ENTER> to cancel", "YES\r\n")
239                         telnet_answer(transport, 
240                                 "Press <ENTER> to continue...", "")
241
242                 # Close
243                 transport.close()
244                 return 0
245
246         except EOFError, err:
247                 if verbose:
248                         logger.debug(err)
249                 if transport:
250                         transport.close()
251                 return errno.ECONNRESET
252         except socket.error, err:
253                 if verbose:
254                         logger.debug(err)
255                 return errno.ETIMEDOUT
256
257         except Exception, err:
258                 import traceback
259                 traceback.print_exc()
260                 if verbose:
261                         logger.debug(err)
262                 if transport:
263                         transport.close()
264                 return "apc error: check password"
265
266 def apc_reboot(ip, username, password, port, protocol, dryrun):
267         global verbose
268
269         transport = None
270
271         # TODO: I may need to differentiate between different models of APC
272         # hardware...
273         #       for instance, the original code didn't work for:
274         #               planetdev03.fm.intel.com
275         #                       American Power Conversion               
276         #                                       Network Management Card AOS      v3.3.0
277         #                       (c) Copyright 2005 All Rights Reserved  
278         #                                       Rack PDU APP                     v3.3.1
279
280
281         try:
282                 #if "ssh" in protocol:
283                 if "22" in protocol and protocol['22'] == "open":
284                         transport = pyssh.Ssh(username, ip)
285                         transport.open()
286                         # Login
287                         telnet_answer(transport, "password:", password)
288                 #elif "telnet" in protocol:
289                 elif "23" in protocol and protocol['23'] == "open":
290                         transport = telnetlib.Telnet(ip, timeout=TELNET_TIMEOUT)
291                         #transport = telnetlib.Telnet(ip)
292                         transport.set_debuglevel(verbose)
293                         # Login
294                         telnet_answer(transport, "User Name", username)
295                         telnet_answer(transport, "Password", password)
296                 else:
297                         logger.debug("Unknown protocol %s" %protocol)
298                         raise "Closed protocol ports!"
299
300
301                 # 1- Device Manager
302                 # 2- Network
303                 # 3- System
304                 # 4- Logout
305
306                 # 1- Device Manager
307                 telnet_answer(transport, "\r\n> ", "1")
308
309                 # 1- Phase Monitor/Configuration
310                 # 2- Outlet Restriction Configuration
311                 # 3- Outlet Control/Config
312                 # 4- Power Supply Status
313
314                 # 3- Outlet Control/Config
315                 telnet_answer(transport, "\r\n> ", "2")
316                 telnet_answer(transport, "\r\n> ", "1")
317
318                 # 3- Outlet Control/Config
319                 #telnet_answer(transport, "\r\n> ", "3")
320
321                 # 1- Outlet 1
322                 # 2- Outlet 2
323                 # ...
324
325                 # n- Outlet n
326                 telnet_answer(transport, "\r\n> ", str(port))
327                 
328                 # 1- Control Outlet
329                 # 2- Configure Outlet
330
331                 # 1- Control Outlet
332                 telnet_answer(transport, "\r\n> ", "1")
333
334                 # 1- Immediate On                         
335                 # 2- Immediate Off                       
336                 # 3- Immediate Reboot             
337                 # 4- Delayed On                         
338                 # 5- Delayed Off                           
339                 # 6- Delayed Reboot                     
340                 # 7- Cancel                                     
341
342                 # 3- Immediate Reboot             
343                 telnet_answer(transport, "\r\n> ", "3")
344
345                 if not dryrun:
346                         telnet_answer(transport, 
347                                 "Enter 'YES' to continue or <ENTER> to cancel", "YES\r\n")
348                         telnet_answer(transport, 
349                                 "Press <ENTER> to continue...", "")
350
351                 # Close
352                 transport.close()
353                 return 0
354
355         except EOFError, err:
356                 if verbose:
357                         logger.debug(err)
358                 if transport:
359                         transport.close()
360                 return errno.ECONNRESET
361         except socket.error, err:
362                 if verbose:
363                         logger.debug(err)
364                 return errno.ETIMEDOUT
365
366         except Exception, err:
367                 import traceback
368                 traceback.print_exc()
369                 if verbose:
370                         logger.debug(err)
371                 if transport:
372                         transport.close()
373                 return apc_reboot_original(ip, username, password, port, protocol, dryrun)
374
375 def drac_reboot(ip, username, password, dryrun):
376         global verbose
377         ssh = None
378         try:
379                 ssh = pyssh.Ssh(username, ip)
380                 ssh.set_debuglevel(verbose)
381                 ssh.open()
382                 # Login
383                 print "password"
384                 telnet_answer(ssh, "password:", password)
385
386                 # Testing Reboot ?
387                 print "reset or power"
388                 if dryrun:
389                         telnet_answer(ssh, "[%s]#" % username, "getsysinfo")
390                 else:
391                         # Reset this machine
392                         telnet_answer(ssh, "[%s]#" % username, "serveraction powercycle")
393
394                 print "exit"
395                 telnet_answer(ssh, "[%s]#" % username, "exit")
396
397                 # Close
398                 print "close"
399                 output = ssh.close()
400                 return 0
401
402         except socket.error, err:
403                 print "exception"
404                 import traceback
405                 traceback.print_exc()
406                 if verbose:
407                         logger.debug(err)
408                 if ssh:
409                         output = ssh.close()
410                         if verbose:
411                                 logger.debug(err)
412                 return errno.ETIMEDOUT
413         except Exception, err:
414                 print "exception"
415                 import traceback
416                 traceback.print_exc()
417                 if verbose:
418                         logger.debug(err)
419                 if ssh:
420                         output = ssh.close()
421                         if verbose:
422                                 logger.debug(err)
423                 return "drac error: check password"
424
425 def ilo_reboot(ip, username, password, dryrun):
426         global verbose
427
428         ssh = None
429
430         try:
431                 ssh = pyssh.Ssh(username, ip)
432                 ssh.set_debuglevel(verbose)
433                 ssh.open()
434                 # Login
435                 print "password"
436                 telnet_answer(ssh, "password:", password)
437
438                 # User:vici logged-in to ILOUSE701N7N4.CS.Princeton.EDU(128.112.154.171)
439                 # iLO Advanced 1.26 at 10:01:40 Nov 17 2006
440                 # Server Name: USE701N7N400
441                 # Server Power: On
442                 # 
443                 # </>hpiLO-> 
444                 print "cd system1"
445                 telnet_answer(ssh, "</>hpiLO->", "cd system1")
446
447                 # Reboot Outlet  N        (Y/N)?
448                 print "reset or power"
449                 if dryrun:
450                         telnet_answer(ssh, "</system1>hpiLO->", "POWER")
451                 else:
452                         # Reset this machine
453                         telnet_answer(ssh, "</system1>hpiLO->", "reset")
454
455                 print "exit"
456                 telnet_answer(ssh, "</system1>hpiLO->", "exit")
457
458                 # Close
459                 print "close"
460                 output = ssh.close()
461                 return 0
462
463         except socket.error, err:
464                 print "exception"
465                 import traceback
466                 traceback.print_exc()
467                 if verbose:
468                         logger.debug(err)
469                 if ssh:
470                         output = ssh.close()
471                         if verbose:
472                                 logger.debug(err)
473                 return errno.ETIMEDOUT
474         except Exception, err:
475                 print "exception"
476                 import traceback
477                 traceback.print_exc()
478                 if verbose:
479                         logger.debug(err)
480                 if ssh:
481                         output = ssh.close()
482                         if verbose:
483                                 logger.debug(err)
484                 return "ilo error: check password"
485
486 def baytech_reboot(ip, username, password, port, dryrun):
487         global verbose
488
489         ssh = None
490
491         #verbose = 1 
492         try:
493                 ssh = pyssh.Ssh(username, ip)
494                 ssh.set_debuglevel(verbose)
495                 ssh.open()
496
497                 # Login
498                 telnet_answer(ssh, "password:", password)
499
500                 # PL1 comm output  (2 ,1).........1
501                 # PL2 comm output  (2 ,2).........2
502                 # PL3 comm output  (2 ,3).........3
503                 # no machine       (2 ,4).........4
504                 # Control Outlets  (5 ,1).........5
505                 # Logout..........................T
506
507                 # Control Outlets  (5 ,1).........5
508                 telnet_answer(ssh, "Enter Request :", "5")
509
510                 # Reboot N
511                 try:
512                         telnet_answer(ssh, "DS-RPC>", "Reboot %d" % port)
513                 except ExceptionNotFound, msg:
514                         # one machine is configured to ask for a username,
515                         # even after login...
516                         print "msg: %s" % msg
517                         ssh.write(username + "\r\n")
518                         telnet_answer(ssh, "DS-RPC>", "Reboot %d" % port)
519                         
520
521                 # Reboot Outlet  N        (Y/N)?
522                 if dryrun:
523                         telnet_answer(ssh, "(Y/N)?", "N")
524                 else:
525                         telnet_answer(ssh, "(Y/N)?", "Y")
526                 telnet_answer(ssh, "DS-RPC>", "")
527
528                 # Close
529                 output = ssh.close()
530                 return 0
531
532         except socket.error, err:
533                 print "exception"
534                 import traceback
535                 traceback.print_exc()
536                 if verbose:
537                         logger.debug(err)
538                 if ssh:
539                         output = ssh.close()
540                         if verbose:
541                                 logger.debug(err)
542                 return errno.ETIMEDOUT
543         except Exception, err:
544                 print "exception"
545                 import traceback
546                 traceback.print_exc()
547                 if verbose:
548                         logger.debug(err)
549                 if ssh:
550                         output = ssh.close()
551                         if verbose:
552                                 logger.debug(err)
553                 return "baytech error: check password"
554
555 ### rebooting european BlackBox PSE boxes
556 # Thierry Parmentelat - May 11 2005
557 # tested on 4-ports models known as PSE505-FR
558 # uses http to POST a data 'P<port>=r'
559 # relies on basic authentication within http1.0
560 # first curl-based script was
561 # curl --http1.0 --basic --user <username>:<password> --data P<port>=r \
562 #       http://<hostname>:<http_port>/cmd.html && echo OK
563
564 def bbpse_reboot (pcu_ip,username,password,port_in_pcu,http_port, dryrun):
565
566         global verbose
567
568         url = "http://%s:%d/cmd.html" % (pcu_ip,http_port)
569         data= "P%d=r" % port_in_pcu
570         if verbose:
571                 logger.debug("POSTing '%s' on %s" % (data,url))
572
573         authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
574         uri = "%s:%d" % (pcu_ip,http_port)
575         authinfo.add_password (None, uri, username, password)
576         authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
577
578         opener = urllib2.build_opener(authhandler)
579         urllib2.install_opener(opener)
580
581         if (dryrun):
582                 return 0
583
584         try:
585                 f = urllib2.urlopen(url,data)
586
587                 r= f.read()
588                 if verbose:
589                         logger.debug(r)
590                 return 0
591
592         except urllib2.URLError,err:
593                 logger.info('Could not open http connection', err)
594                 return "bbpse error"
595
596 ### rebooting x10toggle based systems addressed by port
597 # Marc E. Fiuczynski - May 31 2005
598 # tested on 4-ports models known as PSE505-FR
599 # uses ssh and password to login to an account
600 # that will cause the system to be powercycled.
601
602 def x10toggle_reboot(ip, username, password, port, dryrun):
603         global verbose
604
605         ssh = None
606         try:
607                 ssh = pyssh.Ssh(username, ip)
608                 ssh.open()
609
610                 # Login
611                 telnet_answer(ssh, "password:", password)
612
613                 if not dryrun:
614                         # Reboot
615                         telnet_answer(ssh, "x10toggle>", "A%d" % port)
616
617                 # Close
618                 output = ssh.close()
619                 if verbose:
620                         logger.debug(output)
621                 return 0
622
623         except Exception, err:
624                 if verbose:
625                         logger.debug(err)
626                 if ssh:
627                         output = ssh.close()
628                         if verbose:
629                                 logger.debug(output)
630                 return errno.ETIMEDOUT
631
632 ### rebooting Dell systems via RAC card
633 # Marc E. Fiuczynski - June 01 2005
634 # tested with David Lowenthal's itchy/scratchy nodes at UGA
635 #
636
637 def runcmd(command, args, username, password, timeout = None):
638
639         result = [None]
640         result_ready = threading.Condition()
641
642         def set_result(x):
643
644                 result_ready.acquire()
645                 try:
646                         result[0] = x
647                 finally:
648                         result_ready.notify()
649                         result_ready.release()
650
651         def do_command(command, username, password):
652
653                 try:
654                         # Popen4 is a popen-type class that combines stdout and stderr
655                         p = popen2.Popen4(command)
656
657                         # read all output data
658                         p.tochild.write("%s\n" % username)
659                         p.tochild.write("%s\n" % password)
660                         p.tochild.close()
661                         data = p.fromchild.read()
662
663                         while True:
664                                 # might get interrupted by a signal in poll() or waitpid()
665                                 try:
666                                         retval = p.wait()
667                                         set_result((retval, data))
668                                         break
669                                 except OSError, ex:
670                                         if ex.errno == errno.EINTR:
671                                                 continue
672                                         raise ex
673                 except Exception, ex:
674                         set_result(ex)
675
676         if args:
677                 command = " ".join([command] + args)
678
679         worker = threading.Thread(target = do_command, args = (command, username, password, ))
680         worker.setDaemon(True)
681         result_ready.acquire()
682         worker.start()
683         result_ready.wait(timeout)
684         try:
685                 if result == [None]:
686                         raise Exception, "command timed-out: '%s'" % command
687         finally:
688                 result_ready.release()
689         result = result[0]
690
691         if isinstance(result, Exception):
692                 raise result
693         else:
694                 (retval, data) = result
695                 if os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == 0:
696                         return data
697                 else:
698                         out = "system command ('%s') " % command
699                         if os.WIFEXITED(retval):
700                                 out += "failed, rc = %d" % os.WEXITSTATUS(retval)
701                         else:
702                                 out += "killed by signal %d" % os.WTERMSIG(retval)
703                         if data:
704                                 out += "; output follows:\n" + data
705                         raise Exception, out
706
707 def racadm_reboot(ip, username, password, port, dryrun):
708         global verbose
709
710         try:
711                 cmd = "/usr/sbin/racadm"
712                 os.stat(cmd)
713                 if not dryrun:
714                         output = runcmd(cmd, ["-r %s -i serveraction powercycle" % ip],
715                                 username, password)
716                 else:
717                         output = "dryrun of racadm command"
718
719                 logger.debug("runcmd returned without output %s" % output)
720                 if verbose:
721                         logger.debug(output)
722                 return 0
723
724         except Exception, err:
725                 logger.debug("runcmd raised exception %s" % err)
726                 if verbose:
727                         logger.debug(err)
728                 return errno.ETIMEDOUT
729
730 def pcu_name(pcu):
731         if pcu['hostname'] is not None and pcu['hostname'] is not "":
732                 return pcu['hostname']
733         elif pcu['ip'] is not None and pcu['ip'] is not "":
734                 return pcu['ip']
735         else:
736                 return None
737
738 def get_pcu_values(pcu_id):
739         # TODO: obviously, this shouldn't be loaded each time...
740         import soltesz
741         fb =soltesz.dbLoad("findbadpcus")
742
743         try:
744                 values = fb['nodes']["id_%s" % pcu_id]['values']
745         except:
746                 values = None
747
748         return values
749
750 def check_open_port(values, port_list):
751         ret = False
752
753         if 'portstatus' in values:
754                 for port in port_list:
755                         if      port in values['portstatus'] and \
756                                 values['portstatus'][port] == "open":
757
758                                 ret = True
759         
760         return ret
761         
762
763 def reboot_new(nodename, continue_probe, dryrun):
764
765         pcu = plc.getpcu(nodename)
766         if not pcu:
767                 return False
768
769         values = get_pcu_values(pcu['pcu_id'])
770         if values == None:
771                 return False
772         
773         # Try the PCU first
774         logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
775
776         # DataProbe iPal (many sites)
777         if  continue_probe and values['model'].find("Dataprobe IP-41x/IP-81x") >= 0:
778                 if check_open_port(values, ['23']): 
779                         rb_ret = ipal_reboot(pcu_name(values),
780                                                                         values['password'],
781                                                                         pcu[nodename],
782                                                                         dryrun)
783                 else:
784                         rb_ret = "Unsupported_Port"
785                         
786
787         # APC Masterswitch (Berkeley)
788         elif continue_probe and values['model'].find("APC AP79xx/Masterswitch") >= 0:
789                 if check_open_port(values, ['22', '23']): 
790                         rb_ret = apc_reboot(pcu_name(values),
791                                                                         values['username'],
792                                                                         values['password'], 
793                                                                         pcu[nodename],
794                                                                         values['portstatus'], 
795                                                                         dryrun)
796                 else:
797                         rb_ret = "Unsupported_Port"
798         # BayTech DS4-RPC
799         elif continue_probe and values['model'].find("Baytech DS4-RPC") >= 0:
800                 if check_open_port(values, ['22']): 
801                         rb_ret = baytech_reboot(pcu_name(values),
802                                                                            values['username'],
803                                                                            values['password'], 
804                                                                            pcu[nodename],
805                                                                            dryrun)
806                 else:
807                         rb_ret = "Unsupported_Port"
808                         
809
810         # iLO
811         elif continue_probe and values['model'].find("HP iLO") >= 0:
812                 if check_open_port(values, ['22']): 
813                         rb_ret = ilo_reboot(pcu_name(values),
814                                                                            values['username'],
815                                                                            values['password'], 
816                                                                            dryrun)
817                 else:
818                         rb_ret = "Unsupported_Port"
819                         
820         # DRAC ssh
821         elif continue_probe and values['model'].find("Dell RAC") >= 0:
822                 if check_open_port(values, ['22']): 
823                         rb_ret = drac_reboot(pcu_name(values),
824                                                                            values['username'],
825                                                                            values['password'], 
826                                                                            dryrun)
827                 else:
828                         rb_ret = "Unsupported_Port"
829                         
830
831         # BlackBox PSExxx-xx (e.g. PSE505-FR)
832         elif continue_probe and \
833                 (values['model'].find("BlackBox PS5xx") >= 0 or
834                  values['model'].find("ePowerSwitch 1/4/8x") >=0 ):
835                 if check_open_port(values, ['80']): 
836                         rb_ret = bbpse_reboot(pcu_name(values),
837                                                         values['username'], 
838                                                         values['password'], 
839                                                         pcu[nodename],
840                                                         80,
841                                                         dryrun)
842                 else:
843                         rb_ret = "Unsupported_PCU"
844                         
845         # x10toggle
846         elif    continue_probe and values['protocol'] == "ssh" and \
847                         values['model'] == "x10toggle":
848                 rb_ret = x10toggle_reboot(pcu_name(values),
849                                                                                 values['username'],
850                                                                                 values['password'], 
851                                                                                 pcu[nodename],
852                                                                                 dryrun)
853         # ????
854         elif continue_probe and values['protocol'] == "racadm" and \
855                         values['model'] == "RAC":
856                 rb_ret = racadm_reboot(pcu_name(values),
857                                                                           values['username'],
858                                                                           values['password'],
859                                                                           pcu[nodename],
860                                                                           dryrun)
861         elif continue_probe:
862                 rb_ret = "Unsupported_PCU"
863
864         elif continue_probe == False:
865                 if 'portstatus' in values:
866                         rb_ret = "NetDown"
867                 else:
868                         rb_ret = "Not_Run"
869         else:
870                 rb_ret = -1
871         
872         if rb_ret != 0:
873                 return False
874         else:
875                 return True
876
877
878 # Returns true if rebooted via PCU
879 def reboot(nodename, dryrun):
880         pcu = plc.getpcu(nodename)
881         if not pcu:
882                 plc.nodePOD(nodename)
883                 return False
884         # Try the PCU first
885         logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
886
887         # APC Masterswitch (Berkeley)
888         if pcu['model'] == "APC Masterswitch":
889                 err = apc_reboot(pcu['ip'], pcu['username'],pcu['password'], 
890                                 pcu[nodename], pcu['protocol'], dryrun)
891
892         # DataProbe iPal (many sites)
893         elif pcu['protocol'] == "telnet" and pcu['model'].find("IP-4") >= 0:
894                 err = ipal_reboot(pcu['ip'],pcu['password'], pcu[nodename], dryrun)
895
896         # BayTech DS4-RPC
897         elif pcu['protocol'] == "ssh" and \
898         (pcu['model'].find("Baytech") >= 0 or pcu['model'].find("DS4") >= 0):
899                 err = baytech_reboot(pcu['ip'], pcu['username'],pcu['password'], pcu[nodename], dryrun)
900
901         # BlackBox PSExxx-xx (e.g. PSE505-FR)
902         elif pcu['protocol'] == "http" and (pcu['model'] == "bbpse"):
903                 err = bbpse_reboot(pcu['ip'], pcu['username'], pcu['password'], pcu[nodename],80, dryrun)
904
905         # x10toggle
906         elif pcu['protocol'] == "ssh" and (pcu['model'] == "x10toggle"):
907                 err = x10toggle_reboot(pcu['ip'], pcu['username'],pcu['password'], pcu[nodename], dryrun)
908
909         # 
910         elif pcu['protocol'] == "racadm" and (pcu['model'] == "RAC"):
911                 err = racadm_reboot(pcu['ip'], pcu['username'],pcu['password'], pcu_[nodename], dryrun)
912
913         # Unknown or unsupported
914         else:
915                 err = errno.EPROTONOSUPPORT
916                 return False
917         return True 
918
919 #def get_suggested(suggestion_id,db):
920 #
921 #       sql= """select node_id,pcu_id from nodes where suggestion = %d """\
922 #                       % (suggestion_id)
923 #       try:
924 #               nodes = db.query(sql).dictresult()
925 #       except pg.ProgrammingError, err:
926 #               print( "Database error for query: %s\n%s" % (sql,err) )
927 #               sys.exit(1)
928 #       return nodes
929
930 #def get_pcu_info(node_id,pcu_id,db):
931 #       sql= """select port_number from pcu_ports where node_id = %d and pcu_id = %d """\
932 #                       % (node_id,pcu_id)
933 #       try:
934 #          port_number = db.query(sql).dictresult()
935 #       except pg.ProgrammingError, err:
936 #               print( "Database error for query: %s\n%s" % (sql,err) )
937 #               sys.exit(1)
938 #       
939 #       sql= """select * from pcu where pcu_id = %d """\
940 #                       % (pcu_id)
941 #       try:
942 #               pcu = db.query(sql).dictresult()
943 #       except pg.ProgrammingError, err:
944 #               print( "Database error for query: %s\n%s" % (sql,err) )
945 #               sys.exit(1)
946 #
947 #       result = {'node_id':node_id,'pcu_id':pcu_id,'port_number':port_number[0]['port_number'], 
948 #                         'ip':pcu[0]['ip'],'username':pcu[0]['username'],'password':pcu[0]['password'],\
949 #                         'model':pcu[0]['model'],'protocol':pcu[0]['protocol'],'hostname':pcu[0]['hostname']}
950 #
951 #       return result
952
953 #def add_plc_event(node_id,err,db):
954 #       site_id = plc_db_utils.get_site_from_node_id(node_id,db)
955 #       message = "PCU reboot by monitor-msgs@planet-lab.org: %s" % os.strerror(err)
956 #
957 #       sql = """insert into events (event_class_id,message,person_id,node_id,site_id) values """\
958 #                 """(%d,'%s',%d,%d,%d)""" % (NODE_POWER_CONTROL,message,MONITOR_USER_ID,node_id,site_id)
959 #       print sql
960 #
961 #       try:
962 #               db.query(sql)
963 #       except pg.ProgrammingError, err:
964 #               print( "Database error for: %s\n%s" % (sql,err) )
965 #               sys.exit(1)
966
967
968 def main():
969         logger.setLevel(logging.DEBUG)
970         ch = logging.StreamHandler()
971         ch.setLevel(logging.DEBUG)
972         formatter = logging.Formatter('LOGGER - %(message)s')
973         ch.setFormatter(formatter)
974         logger.addHandler(ch)
975
976
977         try:
978                 reboot("planetlab2.cs.uchicago.edu")
979                 reboot("alice.cs.princeton.edu")
980         except Exception, err:
981                 print err
982         # used later for pretty printing
983 #       pp = pprint.PrettyPrinter(indent=2)
984
985 #       user = "Monitor"
986 #       password = None
987
988 #       plc_db = plc_dbs.open_plc_db_write()
989 #       mon_db = plc_dbs.open_mon_db()
990
991         # 5 = needs script reboot - fix this later
992 #       nodes = get_suggested(5,mon_db)
993
994 #       for row in nodes:
995                 
996 #               pcu = get_pcu_info(row['node_id'],row['pcu_id'],plc_db)
997 #               add_plc_event(row['node_id'],err,plc_db)
998
999 if __name__ == '__main__':
1000         import plc
1001         logger = logging.getLogger("monitor")
1002         main()