Added 'FORCED' to handle some special actions
[monitor.git] / reboot.py
index 3aff77a..4610095 100755 (executable)
--- a/reboot.py
+++ b/reboot.py
@@ -33,7 +33,7 @@ TELNET_TIMEOUT = 30
 
 import logging
 logger = logging.getLogger("monitor")
-verbose = 0
+verbose = 1
 #dryrun = 0;
 
 class ExceptionNotFound(Exception): pass
@@ -108,6 +108,9 @@ def ipal_reboot(ip, password, port, dryrun):
                # Login
                telnet_answer(telnet, "Password >", password)
 
+               # XXX Some iPals require you to hit Enter a few times first
+               telnet.write("\r\n\r\n")
+
                # P# - Pulse relay
                if not dryrun:
                        telnet_answer(telnet, "Enter >", "P%d" % port)
@@ -151,12 +154,130 @@ def ipal_reboot(ip, password, port, dryrun):
                #plc_lock.release()
                return  "ipal error"
 
+def apc_reboot_original(ip, username, password, port, protocol, dryrun):
+       global verbose
+
+       transport = None
+
+       # TODO: I may need to differentiate between different models of APC
+       # hardware...
+       #       for instance, the original code didn't work for:
+       #               planetdev03.fm.intel.com
+       #                       American Power Conversion               
+       #                                       Network Management Card AOS      v3.3.0
+       #                       (c) Copyright 2005 All Rights Reserved  
+       #                                       Rack PDU APP                     v3.3.1
+
+
+       try:
+               #if "ssh" in protocol:
+               if "22" in protocol and protocol['22'] == "open":
+                       transport = pyssh.Ssh(username, ip)
+                       transport.open()
+                       # Login
+                       telnet_answer(transport, "password:", password)
+               #elif "telnet" in protocol:
+               elif "23" in protocol and protocol['23'] == "open":
+                       transport = telnetlib.Telnet(ip, timeout=TELNET_TIMEOUT)
+                       #transport = telnetlib.Telnet(ip)
+                       transport.set_debuglevel(verbose)
+                       # Login
+                       telnet_answer(transport, "User Name", username)
+                       telnet_answer(transport, "Password", password)
+               else:
+                       logger.debug("Unknown protocol %s" %protocol)
+                       raise "Closed protocol ports!"
+
+
+               # 1- Device Manager
+               # 2- Network
+               # 3- System
+               # 4- Logout
+
+               # 1- Device Manager
+               telnet_answer(transport, "\r\n> ", "1")
+
+               # 1- Phase Monitor/Configuration
+               # 2- Outlet Restriction Configuration
+               # 3- Outlet Control/Config
+               # 4- Power Supply Status
+
+               # 3- Outlet Control/Config
+               #telnet_answer(transport, "\r\n> ", "2")
+               #telnet_answer(transport, "\r\n> ", "1")
+
+               # 3- Outlet Control/Config
+               telnet_answer(transport, "\r\n> ", "3")
+
+               # 1- Outlet 1
+               # 2- Outlet 2
+               # ...
+
+               # n- Outlet n
+               telnet_answer(transport, "\r\n> ", str(port))
+               
+               # 1- Control Outlet
+               # 2- Configure Outlet
+
+               # 1- Control Outlet
+               telnet_answer(transport, "\r\n> ", "1")
+
+               # 1- Immediate On                         
+               # 2- Immediate Off                       
+               # 3- Immediate Reboot             
+               # 4- Delayed On                         
+               # 5- Delayed Off                           
+               # 6- Delayed Reboot                     
+               # 7- Cancel                                     
+
+               # 3- Immediate Reboot             
+               telnet_answer(transport, "\r\n> ", "3")
+
+               if not dryrun:
+                       telnet_answer(transport, 
+                               "Enter 'YES' to continue or <ENTER> to cancel", "YES\r\n")
+                       telnet_answer(transport, 
+                               "Press <ENTER> to continue...", "")
+
+               # Close
+               transport.close()
+               return 0
+
+       except EOFError, err:
+               if verbose:
+                       logger.debug(err)
+               if transport:
+                       transport.close()
+               return errno.ECONNRESET
+       except socket.error, err:
+               if verbose:
+                       logger.debug(err)
+               return errno.ETIMEDOUT
+
+       except Exception, err:
+               import traceback
+               traceback.print_exc()
+               if verbose:
+                       logger.debug(err)
+               if transport:
+                       transport.close()
+               return "apc error: check password"
 
 def apc_reboot(ip, username, password, port, protocol, dryrun):
        global verbose
 
        transport = None
 
+       # TODO: I may need to differentiate between different models of APC
+       # hardware...
+       #       for instance, the original code didn't work for:
+       #               planetdev03.fm.intel.com
+       #                       American Power Conversion               
+       #                                       Network Management Card AOS      v3.3.0
+       #                       (c) Copyright 2005 All Rights Reserved  
+       #                                       Rack PDU APP                     v3.3.1
+
+
        try:
                #if "ssh" in protocol:
                if "22" in protocol and protocol['22'] == "open":
@@ -191,7 +312,11 @@ def apc_reboot(ip, username, password, port, protocol, dryrun):
                # 4- Power Supply Status
 
                # 3- Outlet Control/Config
-               telnet_answer(transport, "\r\n> ", "3")
+               telnet_answer(transport, "\r\n> ", "2")
+               telnet_answer(transport, "\r\n> ", "1")
+
+               # 3- Outlet Control/Config
+               #telnet_answer(transport, "\r\n> ", "3")
 
                # 1- Outlet 1
                # 2- Outlet 2
@@ -245,7 +370,7 @@ def apc_reboot(ip, username, password, port, protocol, dryrun):
                        logger.debug(err)
                if transport:
                        transport.close()
-               return "apc error"
+               return apc_reboot_original(ip, username, password, port, protocol, dryrun)
 
 def drac_reboot(ip, username, password, dryrun):
        global verbose
@@ -295,7 +420,7 @@ def drac_reboot(ip, username, password, dryrun):
                        output = ssh.close()
                        if verbose:
                                logger.debug(err)
-               return "drac error"
+               return "drac error: check password"
 
 def ilo_reboot(ip, username, password, dryrun):
        global verbose
@@ -356,7 +481,7 @@ def ilo_reboot(ip, username, password, dryrun):
                        output = ssh.close()
                        if verbose:
                                logger.debug(err)
-               return "ilo error"
+               return "ilo error: check password"
 
 def baytech_reboot(ip, username, password, port, dryrun):
        global verbose
@@ -425,7 +550,7 @@ def baytech_reboot(ip, username, password, port, dryrun):
                        output = ssh.close()
                        if verbose:
                                logger.debug(err)
-               return "baytech error"
+               return "baytech error: check password"
 
 ### rebooting european BlackBox PSE boxes
 # Thierry Parmentelat - May 11 2005
@@ -602,6 +727,154 @@ def racadm_reboot(ip, username, password, port, dryrun):
                        logger.debug(err)
                return errno.ETIMEDOUT
 
+def pcu_name(pcu):
+       if pcu['hostname'] is not None and pcu['hostname'] is not "":
+               return pcu['hostname']
+       elif pcu['ip'] is not None and pcu['ip'] is not "":
+               return pcu['ip']
+       else:
+               return None
+
+def get_pcu_values(pcu_id):
+       # TODO: obviously, this shouldn't be loaded each time...
+       import soltesz
+       fb =soltesz.dbLoad("findbadpcus")
+
+       try:
+               values = fb['nodes']["id_%s" % pcu_id]['values']
+       except:
+               values = None
+
+       return values
+
+def check_open_port(values, port_list):
+       ret = False
+
+       if 'portstatus' in values:
+               for port in port_list:
+                       if      port in values['portstatus'] and \
+                               values['portstatus'][port] == "open":
+
+                               ret = True
+       
+       return ret
+       
+
+def reboot_new(nodename, continue_probe, dryrun):
+
+       pcu = plc.getpcu(nodename)
+       if not pcu:
+               return False
+
+       values = get_pcu_values(pcu['pcu_id'])
+       if values == None:
+               return False
+       
+       # Try the PCU first
+       logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
+
+       # DataProbe iPal (many sites)
+       if  continue_probe and values['model'].find("Dataprobe IP-41x/IP-81x") >= 0:
+               if check_open_port(values, ['23']): 
+                       rb_ret = ipal_reboot(pcu_name(values),
+                                                                       values['password'],
+                                                                       pcu[nodename],
+                                                                       dryrun)
+               else:
+                       rb_ret = "Unsupported_Port"
+                       
+
+       # APC Masterswitch (Berkeley)
+       elif continue_probe and values['model'].find("APC AP79xx/Masterswitch") >= 0:
+               if check_open_port(values, ['22', '23']): 
+                       rb_ret = apc_reboot(pcu_name(values),
+                                                                       values['username'],
+                                                                       values['password'], 
+                                                                       pcu[nodename],
+                                                                       values['portstatus'], 
+                                                                       dryrun)
+               else:
+                       rb_ret = "Unsupported_Port"
+       # BayTech DS4-RPC
+       elif continue_probe and values['model'].find("Baytech DS4-RPC") >= 0:
+               if check_open_port(values, ['22']): 
+                       rb_ret = baytech_reboot(pcu_name(values),
+                                                                          values['username'],
+                                                                          values['password'], 
+                                                                          pcu[nodename],
+                                                                          dryrun)
+               else:
+                       rb_ret = "Unsupported_Port"
+                       
+
+       # iLO
+       elif continue_probe and values['model'].find("HP iLO") >= 0:
+               if check_open_port(values, ['22']): 
+                       rb_ret = ilo_reboot(pcu_name(values),
+                                                                          values['username'],
+                                                                          values['password'], 
+                                                                          dryrun)
+               else:
+                       rb_ret = "Unsupported_Port"
+                       
+       # DRAC ssh
+       elif continue_probe and values['model'].find("Dell RAC") >= 0:
+               if check_open_port(values, ['22']): 
+                       rb_ret = drac_reboot(pcu_name(values),
+                                                                          values['username'],
+                                                                          values['password'], 
+                                                                          dryrun)
+               else:
+                       rb_ret = "Unsupported_Port"
+                       
+
+       # BlackBox PSExxx-xx (e.g. PSE505-FR)
+       elif continue_probe and \
+               (values['model'].find("BlackBox PS5xx") >= 0 or
+                values['model'].find("ePowerSwitch 1/4/8x") >=0 ):
+               if check_open_port(values, ['80']): 
+                       rb_ret = bbpse_reboot(pcu_name(values),
+                                                       values['username'], 
+                                                       values['password'], 
+                                                       pcu[nodename],
+                                                       80,
+                                                       dryrun)
+               else:
+                       rb_ret = "Unsupported_PCU"
+                       
+       # x10toggle
+       elif    continue_probe and values['protocol'] == "ssh" and \
+                       values['model'] == "x10toggle":
+               rb_ret = x10toggle_reboot(pcu_name(values),
+                                                                               values['username'],
+                                                                               values['password'], 
+                                                                               pcu[nodename],
+                                                                               dryrun)
+       # ????
+       elif continue_probe and values['protocol'] == "racadm" and \
+                       values['model'] == "RAC":
+               rb_ret = racadm_reboot(pcu_name(values),
+                                                                         values['username'],
+                                                                         values['password'],
+                                                                         pcu[nodename],
+                                                                         dryrun)
+       elif continue_probe:
+               rb_ret = "Unsupported_PCU"
+
+       elif continue_probe == False:
+               if 'portstatus' in values:
+                       rb_ret = "NetDown"
+               else:
+                       rb_ret = "Not_Run"
+       else:
+               rb_ret = -1
+       
+       if rb_ret != 0:
+               return False
+       else:
+               return True
+
+
 # Returns true if rebooted via PCU
 def reboot(nodename, dryrun):
        pcu = plc.getpcu(nodename)