give noop myops xmlrpc call a extra parameter to allow it to work with the
[monitor.git] / pcucontrol / reboot.py
index 5b322d3..30c7cb5 100755 (executable)
@@ -11,13 +11,13 @@ import urllib2
 import urllib
 import threading, popen2
 import array, struct
 import urllib
 import threading, popen2
 import array, struct
-from monitor.wrapper import plc
 import base64
 from subprocess import PIPE, Popen
 import pcucontrol.transports.ssh.pxssh as pxssh
 import pcucontrol.transports.ssh.pexpect as pexpect
 import socket
 import base64
 from subprocess import PIPE, Popen
 import pcucontrol.transports.ssh.pxssh as pxssh
 import pcucontrol.transports.ssh.pexpect as pexpect
 import socket
-from monitor.util import command
+
+
 
 # Use our versions of telnetlib and pyssh
 sys.path.insert(0, os.path.dirname(sys.argv[0]))
 
 # Use our versions of telnetlib and pyssh
 sys.path.insert(0, os.path.dirname(sys.argv[0]))
@@ -25,9 +25,6 @@ import pcucontrol.transports.telnetlib as telnetlib
 sys.path.insert(0, os.path.dirname(sys.argv[0]) + "/pyssh")    
 import pcucontrol.transports.pyssh as pyssh
 
 sys.path.insert(0, os.path.dirname(sys.argv[0]) + "/pyssh")    
 import pcucontrol.transports.pyssh as pyssh
 
-# Timeouts in seconds
-TELNET_TIMEOUT = 45
-
 # Event class ID from pcu events
 #NODE_POWER_CONTROL = 3
 
 # Event class ID from pcu events
 #NODE_POWER_CONTROL = 3
 
@@ -35,7 +32,6 @@ TELNET_TIMEOUT = 45
 #MONITOR_USER_ID = 11142
 
 import logging
 #MONITOR_USER_ID = 11142
 
 import logging
-logger = logging.getLogger("monitor")
 verbose = 1
 #dryrun = 0;
 
 verbose = 1
 #dryrun = 0;
 
@@ -49,16 +45,6 @@ class ExceptionReset(Exception): pass
 class ExceptionPort(Exception): pass
 class ExceptionUsername(Exception): pass
 
 class ExceptionPort(Exception): pass
 class ExceptionUsername(Exception): pass
 
-def telnet_answer(telnet, expected, buffer):
-       global verbose
-
-       output = telnet.read_until(expected, TELNET_TIMEOUT)
-       #if verbose:
-       #       logger.debug(output)
-       if output.find(expected) == -1:
-               raise ExceptionNotFound, "'%s' not found" % expected
-       else:
-               telnet.write(buffer + "\r\n")
 
 
 # PCU has model, host, preferred-port, user, passwd, 
 
 
 # PCU has model, host, preferred-port, user, passwd, 
@@ -100,25 +86,38 @@ class PCUModel(PCU):
 # This class captures the observed pcu records from FindBadPCUs.py
 class PCURecord:
        def __init__(self, pcu_record_dict):
 # This class captures the observed pcu records from FindBadPCUs.py
 class PCURecord:
        def __init__(self, pcu_record_dict):
-               for field in ['nodenames', 'portstatus', 
-                                               'dnsmatch', 
-                                               'complete_entry', ]:
+               for field in ['port_status', 
+                                               'dns_status', 
+                                               'entry_complete', ]:
                        if field in pcu_record_dict:
                                if field == "reboot":
                                        self.__setattr__("reboot_str", pcu_record_dict[field])
                                else:
                                        self.__setattr__(field, pcu_record_dict[field])
                        if field in pcu_record_dict:
                                if field == "reboot":
                                        self.__setattr__("reboot_str", pcu_record_dict[field])
                                else:
                                        self.__setattr__(field, pcu_record_dict[field])
-                       else:
-                               raise Exception("No such field %s in pcu record dict" % field)
+                       #else:
+                       #       raise Exception("No such field %s in pcu record dict" % field)
 
 class Transport:
 
 class Transport:
-       TELNET = 1
-       SSH    = 2
-       HTTP   = 3
-       IPAL   = 4
+       TELNET = "telnet"
+       SSH    = "ssh"
+       HTTP   = "http"
+       HTTPS  = "https"
+       IPAL   = "ipal"
+       DRAC   = "drac"
+       AMT    = "amt"
 
        TELNET_TIMEOUT = 120
 
 
        TELNET_TIMEOUT = 120
 
+       porttypemap = {
+                       5869 : DRAC,
+                       22 : SSH,
+                       23 : TELNET,
+                       443 : HTTPS,
+                       80 :  HTTP,
+                       9100 : IPAL,
+                       16992 : AMT,
+               }
+
        def __init__(self, type, verbose):
                self.type = type
                self.verbose = verbose
        def __init__(self, type, verbose):
                self.type = type
                self.verbose = verbose
@@ -143,6 +142,7 @@ class Transport:
                        else:
                                raise Exception("Username cannot be None for ssh transport.")
                elif self.type == self.HTTP:
                        else:
                                raise Exception("Username cannot be None for ssh transport.")
                elif self.type == self.HTTP:
+                       # NOTE: this does not work for all web-based services...
                        self.url = "http://%s:%d/" % (host,80)
                        uri = "%s:%d" % (host,80)
 
                        self.url = "http://%s:%d/" % (host,80)
                        uri = "%s:%d" % (host,80)
 
@@ -152,7 +152,6 @@ class Transport:
                        authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
 
                        transport = urllib2.build_opener(authhandler)
                        authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
 
                        transport = urllib2.build_opener(authhandler)
-
                else:
                        raise Exception("Unknown transport type: %s" % self.type)
 
                else:
                        raise Exception("Unknown transport type: %s" % self.type)
 
@@ -170,21 +169,14 @@ class Transport:
                        raise Exception("Unknown transport type %s" % self.type)
                self.transport = None
 
                        raise Exception("Unknown transport type %s" % self.type)
                self.transport = None
 
-       def sendHTTP(self, resource, data):
-               if self.verbose:
-                       print "POSTing '%s' to %s" % (data,self.url + resource)
+       def write(self, msg):
+               return self.send(msg)
 
 
-               try:
-                       f = self.transport.open(self.url + resource ,data)
-                       r = f.read()
-                       if self.verbose:
-                               print r
-
-               except urllib2.URLError,err:
-                       logger.info('Could not open http connection', err)
-                       return "http transport error"
-
-               return 0
+       def send(self, msg):
+               if self.transport == None:
+                       raise ExceptionNoTransport("transport object is type None")
+                       
+               return self.transport.write(msg)
 
        def sendPassword(self, password, prompt=None):
                if self.type == self.TELNET:
 
        def sendPassword(self, password, prompt=None):
                if self.type == self.TELNET:
@@ -199,6 +191,22 @@ class Transport:
                else:
                        raise Exception("Unknown transport type: %s" % self.type)
 
                else:
                        raise Exception("Unknown transport type: %s" % self.type)
 
+       def sendHTTP(self, resource, data):
+               if self.verbose:
+                       print "POSTing '%s' to %s" % (data,self.url + resource)
+
+               try:
+                       f = self.transport.open(self.url + resource ,data)
+                       r = f.read()
+                       if self.verbose:
+                               print r
+
+               except urllib2.URLError,err:
+                       print 'Could not open http connection', err
+                       return "http transport error"
+
+               return 0
+
        def ifThenSend(self, expected, buffer, ErrorClass=ExceptionPrompt):
 
                if self.transport != None:
        def ifThenSend(self, expected, buffer, ErrorClass=ExceptionPrompt):
 
                if self.transport != None:
@@ -216,1046 +224,115 @@ class Transport:
                        self.transport.read_until(expected, self.TELNET_TIMEOUT)
                except:
                        raise ErrorClass("Could not find '%s' within timeout" % expected)
                        self.transport.read_until(expected, self.TELNET_TIMEOUT)
                except:
                        raise ErrorClass("Could not find '%s' within timeout" % expected)
-                       
 
 
-class PCUControl(Transport,PCUModel,PCURecord):
+class PCUControl(PCUModel,PCURecord):
+
+       """ 
+               There are three cases:
+                       1) the pcu_record passed below includes port_status from an
+                               external probe.
+                       2) the external probe failed, and the values are empty
+                       3) this call is made independent of port_status.
+
+               In the first case, the first open port is used.
+               In the third case, the ports are tried in sequence.
+
+               In this way, the port_status value serves only as an optimization,
+               because closed ports are avoided.  The supported_ports value should
+               order ports by their preferred usage.
+       """
 
        supported_ports = []
 
 
        supported_ports = []
 
-       def __init__(self, plc_pcu_record, verbose, supported_ports=[]):
+       def __init__(self, plc_pcu_record, verbose, ignored=None):
                PCUModel.__init__(self, plc_pcu_record)
                PCURecord.__init__(self, plc_pcu_record)
                PCUModel.__init__(self, plc_pcu_record)
                PCURecord.__init__(self, plc_pcu_record)
-               type = None
-               if self.portstatus:
-                       if '22' in supported_ports and self.portstatus['22'] == "open":
-                               type = Transport.SSH
-                       elif '23' in supported_ports and self.portstatus['23'] == "open":
-                               type = Transport.TELNET
-                       elif '80' in supported_ports and self.portstatus['80'] == "open":
-                               type = Transport.HTTP
-                       elif '443' in supported_ports and self.portstatus['443'] == "open":
-                               type = Transport.HTTP
-                       elif '5869' in supported_ports and self.portstatus['5869'] == "open":
-                               # For DRAC cards. Racadm opens this port.
-                               type = Transport.HTTP
-                       elif '9100' in supported_ports and self.portstatus['9100'] == "open":
-                               type = Transport.IPAL
-                       elif '16992' in supported_ports and self.portstatus['16992'] == "open":
-                               type = Transport.HTTP
+
+       def reboot(self, node_port, dryrun):
+
+               port_list = []
+               # There are two sources of potential ports.  Those that are open and
+               # those that are part of the PCU's supported_ports.  
+               #  I think we should start with supported_ports and then filter that
+               #  by the open ports.
+
+               port_list = self.supported_ports
+
+               if hasattr(self, 'port_status') and self.port_status:
+                       # get out the open ports
+                       port_list = filter(lambda x: self.port_status[x] == "open" , self.port_status.keys())
+                       port_list = [ int(x) for x in port_list ]
+                       # take only the open ports that are supported_ports
+                       port_list = filter(lambda x: x in self.supported_ports, port_list)
+                       if port_list == []:
+                               raise ExceptionPort("No Open Port: No transport from open ports")
+
+               print port_list
+
+               ret = "No implementation for open ports on selected PCU model"
+               for port in port_list:
+                       if port not in Transport.porttypemap:
+                               continue
+
+                       type = Transport.porttypemap[port]
+                       self.transport = Transport(type, verbose)
+
+                       print "checking for run_%s" % type
+                       if hasattr(self, "run_%s" % type):
+                               print "found run_%s" % type
+                               fxn = getattr(self, "run_%s" % type)
+                               ret = self.catcherror(fxn, node_port, dryrun)
+                               if ret == 0: # NOTE: success!, so stop
+                                       break
                        else:
                        else:
-                               raise ExceptionPort("Unsupported Port: No transport from open ports")
-               else:
-                       raise Exception("No Portstatus: No transport because no open ports")
-               Transport.__init__(self, type, verbose)
+                               continue
+
+               return ret
 
        def run(self, node_port, dryrun):
                """ This function is to be defined by the specific PCU instance.  """
 
        def run(self, node_port, dryrun):
                """ This function is to be defined by the specific PCU instance.  """
+               raise Exception("This function is not implemented")
                pass
                pass
-               
-       def reboot(self, node_port, dryrun):
+
+       #def reboot(self, node_port, dryrun):
+
+       def catcherror(self, function, node_port, dryrun):
                try:
                try:
-                       return self.run(node_port, dryrun)
+                       return function(node_port, dryrun)
                except ExceptionNotFound, err:
                        return "error: " + str(err)
                except ExceptionPassword, err:
                except ExceptionNotFound, err:
                        return "error: " + str(err)
                except ExceptionPassword, err:
-                       return "password exception: " + str(err)
+                       return "Password exception: " + str(err)
                except ExceptionTimeout, err:
                except ExceptionTimeout, err:
-                       return "timeout exception: " + str(err)
+                       return "Timeout exception: " + str(err)
                except ExceptionUsername, err:
                except ExceptionUsername, err:
-                       return "exception: no username prompt: " + str(err)
+                       return "No username prompt: " + str(err)
                except ExceptionSequence, err:
                except ExceptionSequence, err:
-                       return "sequence error: " + str(err)
+                       return "Sequence error: " + str(err)
                except ExceptionPrompt, err:
                except ExceptionPrompt, err:
-                       return "prompt exception: " + str(err)
+                       return "Prompt exception: " + str(err)
+               except ExceptionNoTransport, err:
+                       return "No Transport: " + str(err)
                except ExceptionPort, err:
                except ExceptionPort, err:
-                       return "no ports exception: " + str(err)
+                       return "No ports exception: " + str(err)
                except socket.error, err:
                        return "socket error: timeout: " + str(err)
                except socket.error, err:
                        return "socket error: timeout: " + str(err)
+               except urllib2.HTTPError, err:
+                       return "HTTPError: " + str(err)
+               except urllib2.URLError, err:
+                       return "URLError: " + str(err)
                except EOFError, err:
                except EOFError, err:
-                       if self.verbose:
-                               logger.debug("reboot: EOF")
-                               logger.debug(err)
                        self.transport.close()
                        import traceback
                        traceback.print_exc()
                        return "EOF connection reset" + str(err)
                        self.transport.close()
                        import traceback
                        traceback.print_exc()
                        return "EOF connection reset" + str(err)
+               except Exception, err:
+                       from monitor.common import email_exception
+                       email_exception(self.host)
+                       raise Exception(err)
 
 
-class IPMI(PCUControl):
-
-       supported_ports = [80,443,623]
-
-       # TODO: get exit codes to determine success or failure...
-       def run(self, node_port, dryrun):
-
-               if not dryrun:
-                       cmd = "ipmitool -I lanplus -H %s -U %s -P '%s' power cycle"
-                       p = os.popen(cmd % ( self.host, self.username, self.password) )
-                       result = p.read()
-                       print "RESULT: ", result
-               else:
-                       cmd = "ipmitool -I lanplus -H %s -U %s -P '%s' user list"
-                       p = os.popen(cmd % ( self.host, self.username, self.password) )
-                       result = p.read()
-                       print "RESULT: ", result
-
-               if "Error" in result:
-                       return result
-               else:
-                       return 0
-                       
-class IPAL(PCUControl):
-       """ 
-               This now uses a proprietary format for communicating with the PCU.  I
-               prefer it to Telnet, and Web access, since it's much lighter weight
-               and, more importantly, IT WORKS!! HHAHHHAHAHAHAHAHA!
-       """
-       supported_ports = [23,80,9100]
-
-       def format_msg(self, data, cmd):
-               esc = chr(int('1b',16))
-               return "%c%s%c%s%c" % (esc, self.password, esc, data, cmd) # esc, 'q', chr(4))
-       
-       def recv_noblock(self, s, count):
-               import errno
-
-               try:
-                       # TODO: make sleep backoff, before stopping.
-                       time.sleep(4)
-                       ret = s.recv(count, socket.MSG_DONTWAIT)
-               except socket.error, e:
-                       if e[0] == errno.EAGAIN:
-                               raise Exception(e[1])
-                       else:
-                               # TODO: not other exceptions.
-                               raise Exception(e)
-               return ret
-
-       def run(self, node_port, dryrun):
-               if self.type == Transport.IPAL:
-                       return self.run_ipal(node_port, dryrun)
-               elif self.type == Transport.TELNET:
-                       return self.run_telnet(node_port, dryrun)
-               else:
-                       raise Exception("Unimplemented Transport for IPAL")
-       
-       def run_telnet(self, node_port, dryrun):
-               # TELNET version of protocol...
-               self.open(self.host)
-               ## XXX Some iPals require you to hit Enter a few times first
-               self.ifThenSend("Password >", "\r\n\r\n", ExceptionNotFound)
-               # Login
-               self.ifThenSend("Password >", self.password, ExceptionPassword)
-               self.transport.write("\r\n\r\n")
-               if not dryrun: # P# - Pulse relay
-                       print "node_port %s" % node_port
-                       self.ifThenSend("Enter >", 
-                                                       "P7", # % node_port, 
-                                                       ExceptionNotFound)
-                       print "send newlines"
-                       self.transport.write("\r\n\r\n")
-                       print "after new lines"
-               # Get the next prompt
-               print "wait for enter"
-               self.ifElse("Enter >", ExceptionTimeout)
-               print "closing "
-               self.close()
-               return 0
-
-       def run_ipal(self, node_port, dryrun):
-               import errno
-
-               power_on = False
-
-               print "open socket"
-               s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-               try:
-                       print "connect"
-                       s.connect((self.host, 9100))
-               except socket.error, e:
-                       s.close()
-                       if e[0] == errno.ECONNREFUSED:
-                               # cannot connect to remote host
-                               raise Exception(e[1])
-                       else:
-                               # TODO: what other conditions are there?
-                               raise Exception(e)
-                               
-               # get current status
-               print "Checking status"
-               s.send(self.format_msg("", 'O'))
-               ret = self.recv_noblock(s, 8)
-               print "Current status is '%s'" % ret
-
-               if ret == '':
-                       raise Exception("Status returned 'another session already open' %s : %s" % (node_port, ret))
-                               
-               if node_port < len(ret):
-                       status = ret[node_port]
-                       if status == '1':
-                               # up
-                               power_on = True
-                       elif status == '0':
-                               # down
-                               power_on = False
-                       else:
-                               raise Exception("Unknown status for PCU socket %s : %s" % (node_port, ret))
-               else:
-                       raise Exception("Mismatch between configured port and PCU status: %s %s" % (node_port, ret))
-                       
-
-               if not dryrun:
-                       if power_on:
-                               print "Pulsing %s" % node_port
-                               s.send(self.format_msg("%s" % node_port, 'P'))
-                       else:
-                               # NOTE: turn power on ; do not pulse the port.
-                               print "Power was off, so turning on ..."
-                               s.send(self.format_msg("%s" % node_port, 'E'))
-                               #s.send(self.format_msg("%s" % node_port, 'P'))
-
-                       print "Receiving response."
-                       ret = self.recv_noblock(s, 8)
-                       print "Current status is '%s'" % ret
-
-                       if node_port < len(ret):
-                               status = ret[node_port]
-                               if status == '1':
-                                       # up
-                                       power_on = True
-                               elif status == '0':
-                                       # down
-                                       power_on = False
-                               else:
-                                       raise Exception("Unknown status for PCU socket %s : %s" % (node_port, ret))
-                       else:
-                               raise Exception("Mismatch between configured port and PCU status: %s %s" % (node_port, ret))
-
-                       if power_on:
-                               return 0
-                       else:
-                               return "Failed Power On"
-
-               s.close()
-               return 0
-
-
-class APCEurope(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               self.ifThenSend("\r\n> ", "1", ExceptionPassword)
-               self.ifThenSend("\r\n> ", "2")
-               self.ifThenSend("\r\n> ", str(node_port))
-               # 3- Immediate Reboot             
-               self.ifThenSend("\r\n> ", "3")
-
-               if not dryrun:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "YES\r\n",
-                                                       ExceptionSequence)
-               else:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "", ExceptionSequence)
-               self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
-               self.close()
-               return 0
-
-class APCBrazil(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               self.ifThenSend("\r\n> ", "1", ExceptionPassword)
-               self.ifThenSend("\r\n> ", str(node_port))
-               # 4- Immediate Reboot             
-               self.ifThenSend("\r\n> ", "4")
-
-               if not dryrun:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "YES\r\n",
-                                                       ExceptionSequence)
-               else:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "", ExceptionSequence)
-               self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
-               self.close()
-               return 0
-
-class APCBerlin(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               self.ifThenSend("\r\n> ", "1", ExceptionPassword)
-               self.ifThenSend("\r\n> ", "2")
-               self.ifThenSend("\r\n> ", "1")
-               self.ifThenSend("\r\n> ", str(node_port))
-               # 3- Immediate Reboot             
-               self.ifThenSend("\r\n> ", "3")
-
-               if not dryrun:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "YES\r\n",
-                                                       ExceptionSequence)
-               else:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "", ExceptionSequence)
-               self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
-               self.close()
-               return 0
-
-class APCFolsom(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               self.ifThenSend("\r\n> ", "1", ExceptionPassword)
-               self.ifThenSend("\r\n> ", "2")
-               self.ifThenSend("\r\n> ", "1")
-               self.ifThenSend("\r\n> ", str(node_port))
-               self.ifThenSend("\r\n> ", "1")
-
-               # 3- Immediate Reboot             
-               self.ifThenSend("\r\n> ", "3")
-
-               if not dryrun:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "YES\r\n",
-                                                       ExceptionSequence)
-               else:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "", ExceptionSequence)
-               self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
-               self.close()
-               return 0
-
-class APCMaster(PCUControl):
-       supported_ports = [22,23]
-       def run(self, node_port, dryrun):
-               print "Rebooting %s" % self.host
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               # 1- Device Manager
-               self.ifThenSend("\r\n> ", "1", ExceptionPassword)
-               # 3- Outlet Control/Config
-               self.ifThenSend("\r\n> ", "3")
-               # n- Outlet n
-               self.ifThenSend("\r\n> ", str(node_port))
-               # 1- Control Outlet
-               self.ifThenSend("\r\n> ", "1")
-               # 3- Immediate Reboot             
-               self.ifThenSend("\r\n> ", "3")
-
-               if not dryrun:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "YES\r\n",
-                                                       ExceptionSequence)
-               else:
-                       self.ifThenSend("Enter 'YES' to continue or <ENTER> to cancel", 
-                                                       "", ExceptionSequence)
-               self.ifThenSend("Press <ENTER> to continue...", "", ExceptionSequence)
-
-               self.close()
-               return 0
-
-class APC(PCUControl):
-       def __init__(self, plc_pcu_record, verbose):
-               PCUControl.__init__(self, plc_pcu_record, verbose)
-
-               self.master = APCMaster(plc_pcu_record, verbose)
-               self.folsom = APCFolsom(plc_pcu_record, verbose)
-               self.europe = APCEurope(plc_pcu_record, verbose)
-
-       def run(self, node_port, dryrun):
-               try_again = True
-               sleep_time = 1
-
-               for pcu in [self.master, self.europe, self.folsom]:
-                       if try_again:
-                               try:
-                                       print "-*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*"
-                                       try_again = False
-                                       print "sleeping 5"
-                                       time.sleep(sleep_time)
-                                       ret = pcu.reboot(node_port, dryrun)
-                               except ExceptionSequence, err:
-                                       del pcu
-                                       sleep_time = 130
-                                       try_again = True
-
-               if try_again:
-                       return "Unknown reboot sequence for APC PCU"
-               else:
-                       return ret
-
-class IntelAMT(PCUControl):
-       supported_ports = [16992]
-
-       def run(self, node_port, dryrun):
-
-               cmd = command.CMD()
-               # TODO: need to make this path universal; not relative to pwd.
-               cmd_str = "pcucontrol/models/intelamt/remoteControl"
-
-               if dryrun:
-                       # NOTE: -p checks the power state of the host.
-                       # TODO: parse the output to find out if it's ok or not.
-                       cmd_str += " -p http://%s:16992/RemoteControlService  -user admin -pass '%s' " % (self.host, self.password )
-               else:
-                       cmd_str += " -A http://%s:16992/RemoteControlService -user admin -pass '%s' " % (self.host, self.password )
-                       
-               print cmd_str
-               return cmd.system(cmd_str, self.TELNET_TIMEOUT)
-
-class DRACRacAdm(PCUControl):
-       def run(self, node_port, dryrun):
-
-               print "trying racadm_reboot..."
-               racadm_reboot(self.host, self.username, self.password, node_port, dryrun)
-
-               return 0
-
-class DRAC(PCUControl):
-       supported_ports = [22,443,5869]
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               print "logging in..."
-               self.transport.write("\r\n")
-               # Testing Reboot ?
-               if dryrun:
-                       self.ifThenSend("[%s]#" % self.username, "getsysinfo")
-               else:
-                       # Reset this machine
-                       self.ifThenSend("[%s]#" % self.username, "serveraction powercycle")
-
-               self.ifThenSend("[%s]#" % self.username, "exit")
-
-               self.close()
-               return 0
-
-class HPiLO(PCUControl):
-       supported_ports = [22,443]
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               # </>hpiLO-> 
-               self.ifThenSend("</>hpiLO->", "cd system1")
-
-               # Reboot Outlet  N        (Y/N)?
-               if dryrun:
-                       self.ifThenSend("</system1>hpiLO->", "POWER")
-               else:
-                       # Reset this machine
-                       self.ifThenSend("</system1>hpiLO->", "reset")
-
-               self.ifThenSend("</system1>hpiLO->", "exit")
-
-               self.close()
-               return 0
-
-               
-class HPiLOHttps(PCUControl):
-       supported_ports = [22,443]
-       def run(self, node_port, dryrun):
-
-               locfg = command.CMD()
-               cmd = "cmdhttps/locfg.pl -s %s -f %s -u %s -p '%s' | grep 'MESSAGE' | grep -v 'No error'" % (
-                                       self.host, "iloxml/Get_Network.xml", 
-                                       self.username, self.password)
-               sout, serr = locfg.run_noexcept(cmd)
-
-               if sout.strip() != "":
-                       print "sout: %s" % sout.strip()
-                       return sout.strip()
-
-               if not dryrun:
-                       locfg = command.CMD()
-                       cmd = "cmdhttps/locfg.pl -s %s -f %s -u %s -p '%s' | grep 'MESSAGE' | grep -v 'No error'" % (
-                                               self.host, "iloxml/Reset_Server.xml", 
-                                               self.username, self.password)
-                       sout, serr = locfg.run_noexcept(cmd)
-
-                       if sout.strip() != "":
-                               print "sout: %s" % sout.strip()
-                               #return sout.strip()
-               return 0
-
-class BayTechAU(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username, None, "Enter user name:")
-               self.sendPassword(self.password, "Enter Password:")
-
-               #self.ifThenSend("RPC-16>", "Status")
-               self.ifThenSend("RPC3-NC>", "Reboot %d" % node_port)
-
-               # Reboot Outlet  N        (Y/N)?
-               if dryrun:
-                       self.ifThenSend("(Y/N)?", "N")
-               else:
-                       self.ifThenSend("(Y/N)?", "Y")
-               self.ifThenSend("RPC3-NC>", "")
-
-               self.close()
-               return 0
-
-class BayTechGeorgeTown(PCUControl):
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username, None, "Enter user name:")
-               self.sendPassword(self.password, "Enter Password:")
-
-               #self.ifThenSend("RPC-16>", "Status")
-
-               self.ifThenSend("RPC-16>", "Reboot %d" % node_port)
-
-               # Reboot Outlet  N        (Y/N)?
-               if dryrun:
-                       self.ifThenSend("(Y/N)?", "N")
-               else:
-                       self.ifThenSend("(Y/N)?", "Y")
-               self.ifThenSend("RPC-16>", "")
-
-               self.close()
-               return 0
-
-class BayTechCtrlCUnibe(PCUControl):
-       """
-               For some reason, these units let you log in fine, but they hang
-               indefinitely, unless you send a Ctrl-C after the password.  No idea
-               why.
-       """
-       def run(self, node_port, dryrun):
-               print "BayTechCtrlC %s" % self.host
-
-               ssh_options="-o StrictHostKeyChecking=no -o PasswordAuthentication=yes -o PubkeyAuthentication=no"
-               s = pxssh.pxssh()
-               if not s.login(self.host, self.username, self.password, ssh_options):
-                       raise ExceptionPassword("Invalid Password")
-               # Otherwise, the login succeeded.
-
-               # Send a ctrl-c to the remote process.
-               print "sending ctrl-c"
-               s.send(chr(3))
-
-               # Control Outlets  (5 ,1).........5
-               try:
-                       #index = s.expect("Enter Request")
-                       index = s.expect(["Enter Request :"])
-
-                       if index == 0:
-                               print "3"
-                               s.send("3\r\n")
-                               index = s.expect(["DS-RPC>", "Enter user name:"])
-                               if index == 1:
-                                       s.send(self.username + "\r\n")
-                                       index = s.expect(["DS-RPC>"])
-
-                               if index == 0:
-                                       print "Reboot %d" % node_port
-                                       s.send("Reboot %d\r\n" % node_port)
-
-                                       time.sleep(5)
-                                       index = s.expect(["\(Y/N\)\?", "Port in use", "DS-RPC>"])
-                                       if index == 0:
-                                               if dryrun:
-                                                       print "sending N"
-                                                       s.send("N\r\n")
-                                               else:
-                                                       print "sending Y"
-                                                       s.send("Y\r\n")
-                                       elif index == 1:
-                                               raise ExceptionPrompt("PCU Reported 'Port in use.'")
-                                       elif index == 2:
-                                               raise ExceptionSequence("Issued command 'Reboot' failed.")
-
-                               time.sleep(5)
-                               index = s.expect(["DS-RPC>"])
-                               #print "got prompt back"
-
-                       s.close()
-
-               except pexpect.EOF:
-                       raise ExceptionPrompt("EOF before expected Prompt")
-               except pexpect.TIMEOUT:
-                       raise ExceptionPrompt("Timeout before expected Prompt")
-
-               return 0
-
-class BayTechCtrlC(PCUControl):
-       """
-               For some reason, these units let you log in fine, but they hang
-               indefinitely, unless you send a Ctrl-C after the password.  No idea
-               why.
-       """
-       def run(self, node_port, dryrun):
-               print "BayTechCtrlC %s" % self.host
-
-               ssh_options="-o StrictHostKeyChecking=no -o PasswordAuthentication=yes -o PubkeyAuthentication=no"
-               s = pxssh.pxssh()
-               if not s.login(self.host, self.username, self.password, ssh_options):
-                       raise ExceptionPassword("Invalid Password")
-               # Otherwise, the login succeeded.
-
-               # Send a ctrl-c to the remote process.
-               print "SENDING ctrl-c"
-               s.send(chr(3))
-
-               # Control Outlets  (5 ,1).........5
-               try:
-                       print "EXPECTING: ", "Enter Request :"
-                       index = s.expect(["Enter Request :"])
-
-                       if index == 0:
-                               print "SENDING: 5"
-                               s.send("5\r\n")
-                               print "EXPECTING: ", "DS-RPC>"
-                               index = s.expect(["DS-RPC>", "Enter user name:", "Port in use."])
-                               if index == 1:
-                                       print "sending username"
-                                       s.send(self.username + "\r\n")
-                                       index = s.expect(["DS-RPC>"])
-                               elif index == 2:
-                                       raise ExceptionPrompt("PCU Reported 'Port in use.'")
-
-                               if index == 0:
-                                       print "SENDING: Reboot %d" % node_port
-                                       s.send("Reboot %d\r\n" % node_port)
-
-                                       print "SLEEPING: 5"
-                                       time.sleep(5)
-                                       print "EXPECTING: ", "Y/N?"
-                                       index = s.expect(["\(Y/N\)\?", "Port in use", "DS-RPC>"])
-                                       if index == 0:
-                                               if dryrun:
-                                                       print "sending N"
-                                                       s.send("N\r\n")
-                                               else:
-                                                       print "SENDING: Y"
-                                                       s.send("Y\r\n")
-                                       elif index == 1:
-                                               raise ExceptionPrompt("PCU Reported 'Port in use.'")
-                                       elif index == 2:
-                                               raise ExceptionSequence("Issued command 'Reboot' failed.")
-
-                               # NOTE: for some reason, the script times out with the
-                               # following line.  In manual tests, it works correctly, but
-                               # with automated tests, evidently it fails.
-                               print "SLEEPING: 5"
-                               time.sleep(5)
-                               #print "TOTAL--", s.allstr, "--EOT"
-                               index = s.expect(["DS-RPC>"])
-                               print "got prompt back"
-
-                       s.close()
-
-               except pexpect.EOF:
-                       raise ExceptionPrompt("EOF before 'Enter Request' Prompt")
-               except pexpect.TIMEOUT:
-                       raise ExceptionPrompt("Timeout before Prompt")
-
-               return 0
-
-class BayTech(PCUControl):
-       supported_ports = [22,23]
-       def run(self, node_port, dryrun):
-               self.open(self.host, self.username)
-               self.sendPassword(self.password)
-
-               # Control Outlets  (5 ,1).........5
-               self.ifThenSend("Enter Request :", "5")
-
-               # Reboot N
-               try:
-                       self.ifThenSend("DS-RPC>", "Reboot %d" % node_port, ExceptionNotFound)
-               except ExceptionNotFound, msg:
-                       # one machine is configured to ask for a username,
-                       # even after login...
-                       print "msg: %s" % msg
-                       self.transport.write(self.username + "\r\n")
-                       time.sleep(5)
-                       self.ifThenSend("DS-RPC>", "Reboot %d" % node_port)
-
-               # Reboot Outlet  N        (Y/N)?
-               if dryrun:
-                       self.ifThenSend("(Y/N)?", "N")
-               else:
-                       self.ifThenSend("(Y/N)?", "Y")
-               time.sleep(5)
-               self.ifThenSend("DS-RPC>", "")
-
-               self.close()
-               return 0
-
-class WTIIPS4(PCUControl):
-       supported_ports = [23]
-       def run(self, node_port, dryrun):
-               self.open(self.host)
-               self.sendPassword(self.password, "Enter Password:")
-
-               self.ifThenSend("IPS> ", "/Boot %s" % node_port)
-               if not dryrun:
-                       self.ifThenSend("Sure? (Y/N): ", "N")
-               else:
-                       self.ifThenSend("Sure? (Y/N): ", "Y")
-
-               self.ifThenSend("IPS> ", "")
-
-               self.close()
-               return 0
-
-class ePowerSwitchGood(PCUControl):
-       # NOTE:
-       #               The old code used Python's HTTPPasswordMgrWithDefaultRealm()
-       #               For some reason this both doesn't work and in some cases, actually
-       #               hangs the PCU.  Definitely not what we want.
-       #               
-       #               The code below is much simpler.  Just letting things fail first,
-       #               and then, trying again with authentication string in the header.
-       #               
-       def run(self, node_port, dryrun):
-               self.transport = None
-               self.url = "http://%s:%d/" % (self.host,80)
-               uri = "%s:%d" % (self.host,80)
-
-               req = urllib2.Request(self.url)
-               try:
-                       handle = urllib2.urlopen(req)
-               except IOError, e:
-                       # NOTE: this is expected to fail initially
-                       pass
-               else:
-                       print self.url
-                       print "-----------"
-                       print handle.read()
-                       print "-----------"
-                       return "ERROR: not protected by HTTP authentication"
-
-               if not hasattr(e, 'code') or e.code != 401:
-                       return "ERROR: failed for: %s" % str(e)
-
-               base64data = base64.encodestring("%s:%s" % (self.username, self.password))[:-1]
-               # NOTE: assuming basic realm authentication.
-               authheader = "Basic %s" % base64data
-               req.add_header("Authorization", authheader)
-
-               try:
-                       f = urllib2.urlopen(req)
-               except IOError, e:
-                       # failing here means the User/passwd is wrong (hopefully)
-                       raise ExceptionPassword("Incorrect username/password")
-
-               # NOTE: after verifying that the user/password is correct, 
-               #               actually reboot the given node.
-               if not dryrun:
-                       try:
-                               data = urllib.urlencode({'P%d' % node_port : "r"})
-                               req = urllib2.Request(self.url + "cmd.html")
-                               req.add_header("Authorization", authheader)
-                               # add data to handler,
-                               f = urllib2.urlopen(req, data)
-                               if self.verbose: print f.read()
-                       except:
-                               import traceback; traceback.print_exc()
-
-                               # fetch url one more time on cmd.html, econtrol.html or whatever.
-                               # pass
-               else:
-                       if self.verbose: print f.read()
-
-               self.close()
-               return 0
-
-class CustomPCU(PCUControl):
-       def run(self, node_port, dryrun):
-               url = "https://www-itec.uni-klu.ac.at/plab-pcu/index.php" 
-
-               if not dryrun:
-                       # Turn host off, then on
-                       formstr = "plab%s=off" % node_port
-                       os.system("curl --user %s:%s --form '%s' --insecure %s" % (self.username, self.password, formstr, url))
-                       time.sleep(5)
-                       formstr = "plab%s=on" % node_port
-                       os.system("curl --user %s:%s --form '%s' --insecure %s" % (self.username, self.password, formstr, url))
-               else:
-                       os.system("curl --user %s:%s --insecure %s" % (self.username, self.password, url))
-
-
-class ePowerSwitchOld(PCUControl):
-       def run(self, node_port, dryrun):
-               self.url = "http://%s:%d/" % (self.host,80)
-               uri = "%s:%d" % (self.host,80)
-
-               # create authinfo
-               authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
-               authinfo.add_password (None, uri, self.username, self.password)
-               authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
-
-               # NOTE: it doesn't seem to matter whether this authinfo is here or not.
-               transport = urllib2.build_opener(authinfo)
-               f = transport.open(self.url)
-               if self.verbose: print f.read()
-
-               if not dryrun:
-                       transport = urllib2.build_opener(authhandler)
-                       f = transport.open(self.url + "cmd.html", "P%d=r" % node_port)
-                       if self.verbose: print f.read()
-
-               self.close()
-               return 0
-
-class ePowerSwitch(PCUControl):
-       supported_ports = [80]
-       def run(self, node_port, dryrun):
-               self.url = "http://%s:%d/" % (self.host,80)
-               uri = "%s:%d" % (self.host,80)
-
-               # TODO: I'm still not sure what the deal is here.
-               #               two independent calls appear to need to be made before the
-               #               reboot will succeed.  It doesn't seem to be possible to do
-               #               this with a single call.  I have no idea why.
-
-               # create authinfo
-               authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
-               authinfo.add_password (None, uri, self.username, self.password)
-               authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
-
-               # NOTE: it doesn't seem to matter whether this authinfo is here or not.
-               transport = urllib2.build_opener()
-               f = transport.open(self.url + "elogin.html", "pwd=%s" % self.password)
-               if self.verbose: print f.read()
-
-               if not dryrun:
-                       transport = urllib2.build_opener(authhandler)
-                       f = transport.open(self.url + "econtrol.html", "P%d=r" % node_port)
-                       if self.verbose: print f.read()
-
-               #       data= "P%d=r" % node_port
-               #self.open(self.host, self.username, self.password)
-               #self.sendHTTP("elogin.html", "pwd=%s" % self.password)
-               #self.sendHTTP("econtrol.html", data)
-               #self.sendHTTP("cmd.html", data)
-
-               self.close()
-               return 0
-               
-class ManualPCU(PCUControl):
-       supported_ports = [22,23,80,443,9100,16992]
-
-       def run(self, node_port, dryrun):
-               if not dryrun:
-                       # TODO: send email message to monitor admin requesting manual
-                       # intervention.  This should always be an option for ridiculous,
-                       # custom jobs.
-                       pass
-               return 0
-
-### rebooting european BlackBox PSE boxes
-# Thierry Parmentelat - May 11 2005
-# tested on 4-ports models known as PSE505-FR
-# uses http to POST a data 'P<port>=r'
-# relies on basic authentication within http1.0
-# first curl-based script was
-# curl --http1.0 --basic --user <username>:<password> --data P<port>=r \
-#      http://<hostname>:<http_port>/cmd.html && echo OK
-
-# log in:
-
-## BB PSMaverick
-class BlackBoxPSMaverick(PCUControl):
-       supported_ports = [80]
-
-       def run(self, node_port, dryrun):
-               if not dryrun:
-                       # send reboot signal.
-                       cmd = "curl -s --data 'P%s=r' --anyauth --user '%s:%s' http://%s/config/home_f.html" % ( node_port, self.username, self.password, self.host)
-               else:
-                       # else, just try to log in
-                       cmd = "curl -s --anyauth --user '%s:%s' http://%s/config/home_f.html" % ( self.username, self.password, self.host)
-
-               p = os.popen(cmd)
-               result = p.read()
-               print "RESULT: ", result
-
-               if len(result.split()) > 3:
-                       return 0
-               else:
-                       return result
-
-def bbpse_reboot (pcu_ip,username,password,port_in_pcu,http_port, dryrun):
-
-       global verbose
-
-       url = "http://%s:%d/cmd.html" % (pcu_ip,http_port)
-       data= "P%d=r" % port_in_pcu
-       if verbose:
-               logger.debug("POSTing '%s' on %s" % (data,url))
-
-       authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
-       uri = "%s:%d" % (pcu_ip,http_port)
-       authinfo.add_password (None, uri, username, password)
-       authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
-
-       opener = urllib2.build_opener(authhandler)
-       urllib2.install_opener(opener)
-
-       if (dryrun):
-               return 0
-
-       try:
-               f = urllib2.urlopen(url,data)
-
-               r= f.read()
-               if verbose:
-                       logger.debug(r)
-               return 0
-
-       except urllib2.URLError,err:
-               logger.info('Could not open http connection', err)
-               return "bbpse error"
-
-### rebooting x10toggle based systems addressed by port
-# Marc E. Fiuczynski - May 31 2005
-# tested on 4-ports models known as PSE505-FR
-# uses ssh and password to login to an account
-# that will cause the system to be powercycled.
-
-def x10toggle_reboot(ip, username, password, port, dryrun):
-       global verbose
-
-       ssh = None
-       try:
-               ssh = pyssh.Ssh(username, ip)
-               ssh.open()
-
-               # Login
-               telnet_answer(ssh, "password:", password)
-
-               if not dryrun:
-                       # Reboot
-                       telnet_answer(ssh, "x10toggle>", "A%d" % port)
-
-               # Close
-               output = ssh.close()
-               if verbose:
-                       logger.debug(output)
-               return 0
-
-       except Exception, err:
-               if verbose:
-                       logger.debug(err)
-               if ssh:
-                       output = ssh.close()
-                       if verbose:
-                               logger.debug(output)
-               return errno.ETIMEDOUT
-
-### rebooting Dell systems via RAC card
-# Marc E. Fiuczynski - June 01 2005
-# tested with David Lowenthal's itchy/scratchy nodes at UGA
-#
-
-def runcmd(command, args, username, password, timeout = None):
-
-       result = [None]
-       result_ready = threading.Condition()
-
-       def set_result(x):
-
-               result_ready.acquire()
-               try:
-                       result[0] = x
-               finally:
-                       result_ready.notify()
-                       result_ready.release()
-
-       def do_command(command, username, password):
-
-               try:
-                       # Popen4 is a popen-type class that combines stdout and stderr
-                       p = popen2.Popen4(command)
-
-                       # read all output data
-                       p.tochild.write("%s\n" % username)
-                       p.tochild.write("%s\n" % password)
-                       p.tochild.close()
-                       data = p.fromchild.read()
-
-                       while True:
-                               # might get interrupted by a signal in poll() or waitpid()
-                               try:
-                                       retval = p.wait()
-                                       set_result((retval, data))
-                                       break
-                               except OSError, ex:
-                                       if ex.errno == errno.EINTR:
-                                               continue
-                                       raise ex
-               except Exception, ex:
-                       set_result(ex)
-
-       if args:
-               command = " ".join([command] + args)
-
-       worker = threading.Thread(target = do_command, args = (command, username, password, ))
-       worker.setDaemon(True)
-       result_ready.acquire()
-       worker.start()
-       result_ready.wait(timeout)
-       try:
-               if result == [None]:
-                       raise Exception, "command timed-out: '%s'" % command
-       finally:
-               result_ready.release()
-       result = result[0]
-
-       if isinstance(result, Exception):
-               raise result
-       else:
-               (retval, data) = result
-               if os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == 0:
-                       return data
-               else:
-                       out = "system command ('%s') " % command
-                       if os.WIFEXITED(retval):
-                               out += "failed, rc = %d" % os.WEXITSTATUS(retval)
-                       else:
-                               out += "killed by signal %d" % os.WTERMSIG(retval)
-                       if data:
-                               out += "; output follows:\n" + data
-                       raise Exception, out
-
-def racadm_reboot(host, username, password, port, dryrun):
-       global verbose
-
-       ip = socket.gethostbyname(host)
-       try:
-               cmd = "/usr/sbin/racadm"
-               os.stat(cmd)
-               if not dryrun:
-                       output = runcmd(cmd, ["-r %s -i serveraction powercycle" % ip],
-                               username, password)
-               else:
-                       output = runcmd(cmd, ["-r %s -i getsysinfo" % ip],
-                               username, password)
-
-               print "RUNCMD: %s" % output
-               if verbose:
-                       logger.debug(output)
-               return 0
-
-       except Exception, err:
-               logger.debug("runcmd raised exception %s" % err)
-               if verbose:
-                       logger.debug(err)
-               return -1
+from pcucontrol.util import command
+from pcucontrol.models import *
 
 def pcu_name(pcu):
        if pcu['hostname'] is not None and pcu['hostname'] is not "":
 
 def pcu_name(pcu):
        if pcu['hostname'] is not None and pcu['hostname'] is not "":
@@ -1265,255 +342,133 @@ def pcu_name(pcu):
        else:
                return None
 
        else:
                return None
 
-#import database
-from monitor import database
-fb = None
-
-def get_pcu_values(pcu_id):
-       global fb
-       if fb == None:
-               # this shouldn't be loaded each time...
-               fb = database.dbLoad("findbadpcus")
-               
-       try:
-               values = fb['nodes']["id_%s" % pcu_id]['values']
-       except:
-               values = None
-
-       return values
-
-def reboot(nodename):
-       return reboot_policy(nodename, True, False)
-       
-def reboot_policy(nodename, continue_probe, dryrun):
-       global verbose
-
-       pcu = plc.getpcu(nodename)
-       if not pcu:
-               logger.debug("no pcu for %s" % hostname)
-               print "no pcu for %s" % hostname
-               return False # "%s has no pcu" % nodename
-
-       values = get_pcu_values(pcu['pcu_id'])
-       if values == None:
-               logger.debug("No values for pcu probe %s" % hostname)
-               print "No values for pcu probe %s" % hostname
-               return False #"no info for pcu_id %s" % pcu['pcu_id']
-       
-       # Try the PCU first
-       logger.debug("Trying PCU %s %s" % (pcu['hostname'], pcu['model']))
-
-       ret = reboot_test(nodename, values, continue_probe, verbose, dryrun)
-
-       if ret != 0:
-               print ret
-               return False
-       else:
-               print "return true"
-               return True
-
 class Unknown(PCUControl):
        supported_ports = [22,23,80,443,5869,9100,16992]
 
 def model_to_object(modelname):
 class Unknown(PCUControl):
        supported_ports = [22,23,80,443,5869,9100,16992]
 
 def model_to_object(modelname):
+       if modelname is None:
+               return ManualPCU 
        if "AMT" in modelname:
                return IntelAMT
        if "AMT" in modelname:
                return IntelAMT
-       elif "DS4-RPC" in modelname:
+       elif "BayTech" in modelname:
                return BayTech
                return BayTech
-       elif "ilo2" in modelname:
+       elif "HPiLO" in modelname:
                return HPiLO
                return HPiLO
-       elif "IP-41x" in modelname:
+       elif "IPAL" in modelname:
                return IPAL
                return IPAL
-       elif "AP79xx" in modelname or "Masterswitch" in modelname:
-               return APCMaster
+       elif "APC" in modelname:
+               return APCControl
        elif "DRAC" in modelname:
                return DRAC
        elif "WTI" in modelname:
                return WTIIPS4
        elif "ePowerSwitch" in modelname:
        elif "DRAC" in modelname:
                return DRAC
        elif "WTI" in modelname:
                return WTIIPS4
        elif "ePowerSwitch" in modelname:
-               return ePowerSwitch
-       elif "ipmi" in modelname:
-               return IPMI
-       elif "bbsemaverick" in modelname:
+               return ePowerSwitchNew
+       elif "IPMI" in modelname:
+               return OpenIPMI
+       elif "BlackBoxPSMaverick" in modelname:
                return BlackBoxPSMaverick
                return BlackBoxPSMaverick
+       elif "PM211MIP" in modelname:
+               return PM211MIP
+       elif "ManualPCU" in modelname:
+               return ManualPCU 
        else:
        else:
+               print "UNKNOWN model %s"%modelname
                return Unknown
 
                return Unknown
 
-def reboot_test(nodename, values, continue_probe, verbose, dryrun):
+def reboot_api(node, pcu):
        rb_ret = ""
        rb_ret = ""
-       if 'plc_pcu_stats' in values:
-               values.update(values['plc_pcu_stats'])
 
        try:
 
        try:
-               # DataProbe iPal (many sites)
-               if  continue_probe and values['model'].find("IP-41x_IP-81x") >= 0:
-                       ipal = IPAL(values, verbose, ['23', '80', '9100'])
-                       rb_ret = ipal.reboot(values[nodename], dryrun)
-                               
-               # APC Masterswitch (Berkeley)
-               elif continue_probe and ( values['model'].find("AP79xx") >= 0 or \
-                                                                 values['model'].find("Masterswitch") >= 0 ):
-                       print values
-
-                       # TODO: make a more robust version of APC
-                       if values['pcu_id'] in [1102,1163,1055,1111,1231,1113,1127,1128,1148]:
-                               apc = APCEurope(values, verbose, ['22', '23'])
-                               rb_ret = apc.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [1110,86]:
-                               apc = APCBrazil(values, verbose, ['22', '23'])
-                               rb_ret = apc.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [1221,1225,1220,1192]:
-                               apc = APCBerlin(values, verbose, ['22', '23'])
-                               rb_ret = apc.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [1173,1240,47,1363,1405,1401,1372,1371]:
-                               apc = APCFolsom(values, verbose, ['22', '23'])
-                               rb_ret = apc.reboot(values[nodename], dryrun)
-
-                       else:
-                               apc = APCMaster(values, verbose, ['22', '23'])
-                               rb_ret = apc.reboot(values[nodename], dryrun)
-
-               # BayTech DS4-RPC
-               elif continue_probe and values['model'].find("DS4-RPC") >= 0:
-                       if values['pcu_id'] in [1056,1237,1052,1209,1002,1008,1041,1013,1022]:
-                               # These  require a 'ctrl-c' to be sent... 
-                               baytech = BayTechCtrlC(values, verbose, ['22', '23'])
-                               rb_ret = baytech.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [93]:
-                               baytech = BayTechAU(values, verbose, ['22', '23'])
-                               rb_ret = baytech.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [1057]:
-                               # These  require a 'ctrl-c' to be sent... 
-                               baytech = BayTechCtrlCUnibe(values, verbose, ['22', '23'])
-                               rb_ret = baytech.reboot(values[nodename], dryrun)
-
-                       elif values['pcu_id'] in [1012]:
-                               # This pcu sometimes doesn't present the 'Username' prompt,
-                               # unless you immediately try again...
-                               try:
-                                       baytech = BayTechGeorgeTown(values, verbose, ['22', '23'])
-                                       rb_ret = baytech.reboot(values[nodename], dryrun)
-                               except:
-                                       baytech = BayTechGeorgeTown(values, verbose, ['22', '23'])
-                                       rb_ret = baytech.reboot(values[nodename], dryrun)
-                       else:
-                               baytech = BayTech(values, verbose, ['22', '23'])
-                               rb_ret = baytech.reboot(values[nodename], dryrun)
-
-               # iLO
-               elif continue_probe and values['model'].find("ilo") >= 0:
-                       try:
-                               hpilo = HPiLO(values, verbose, ['22'])
-                               rb_ret = hpilo.reboot(0, dryrun)
-                               if rb_ret != 0:
-                                       hpilo = HPiLOHttps(values, verbose, ['443'])
-                                       rb_ret = hpilo.reboot(0, dryrun)
-                       except:
-                               hpilo = HPiLOHttps(values, verbose, ['443'])
-                               rb_ret = hpilo.reboot(0, dryrun)
-
-               # DRAC ssh
-               elif continue_probe and values['model'].find("DRAC") >= 0:
-                       # TODO: I don't think DRACRacAdm will throw an exception for the
-                       # default method to catch...
-                       try:
-                               drac = DRACRacAdm(values, verbose, ['443', '5869'])
-                               rb_ret = drac.reboot(0, dryrun)
-                       except:
-                               drac = DRAC(values, verbose, ['22'])
-                               rb_ret = drac.reboot(0, dryrun)
-
-               elif continue_probe and values['model'].find("WTI IPS-4") >= 0:
-                               wti = WTIIPS4(values, verbose, ['23'])
-                               rb_ret = wti.reboot(values[nodename], dryrun)
-
-               elif continue_probe and values['model'].find("AMT") >= 0:
-                               amt = IntelAMT(values, verbose, ['16992'])
-                               rb_ret = amt.reboot(values[nodename], dryrun)
-
-               elif continue_probe and values['model'].find("bbsemaverick") >=0:
-                       print "TRYING BlackBoxPSMaverick"
-                       bbe = BlackBoxPSMaverick(values, verbose, ['80'])
-                       rb_ret = bbe.reboot(values[nodename], dryrun)
-
-               elif continue_probe and values['model'].find("ipmi") >=0:
-
-                       print "TRYING IPMI"
-                       ipmi = IPMI(values, verbose, ['80', '443', '623'])
-                       rb_ret = ipmi.reboot(values[nodename], dryrun)
-
-               elif continue_probe and values['model'].find("ePowerSwitch") >=0:
-                       # TODO: allow a different port than http 80.
-                       if values['pcu_id'] in [1089, 1071, 1046, 1035, 1118]:
-                               eps = ePowerSwitchGood(values, verbose, ['80'])
-                       elif values['pcu_id'] in [1003]:
-                               # OLD EPOWER
-                               print "OLD EPOWER"
-                               eps = ePowerSwitch(values, verbose, ['80'])
-                       else:
-                               eps = ePowerSwitchGood(values, verbose, ['80'])
-
-                       rb_ret = eps.reboot(values[nodename], dryrun)
-               elif continue_probe and values['pcu_id'] in [1122]:
-                       custom = CustomPCU(values, verbose, ['80', '443'])
-                       custom.reboot(values[nodename], dryrun)
+               modelname = pcu['model']
+               if modelname:
+                       # get object instance 
+                       instance = eval('%s(pcu, verbose)' % modelname)
+                       # get pcu port 
+                       i = pcu['node_ids'].index(node['node_id'])
+                       p = pcu['ports'][i]
+                       # reboot
+                       rb_ret = instance.reboot(p, False)
+               else:
+                       rb_ret =  "No modelname in PCU record."
+               # TODO: how to handle the weird, georgetown pcus, the drac faults, and ilo faults
+       except Exception, err:
+               rb_ret = "Exception Model(%s): " % modelname 
+               rb_ret += str(err)
 
 
-               elif continue_probe:
-                       rb_ret = "Unsupported_PCU"
+       return rb_ret
 
 
-               elif continue_probe == False:
-                       if 'portstatus' in values:
-                               rb_ret = "NetDown"
-                       else:
-                               rb_ret = "Not_Run"
-               else:
-                       rb_ret = -1
+def convert_oldmodelname_to_newmodelname(oldmodelname, pcu_id):
+       newmodelname = None
+       update = {      'AP79xx' : 'APCControl13p13',
+                               'Masterswitch' : 'APCControl13p13',
+                               'DS4-RPC' : 'BayTech',
+                               'IP-41x_IP-81x' : 'IPAL',
+                               'DRAC3' : 'DRAC',
+                               'DRAC4' : 'DRAC',
+                               'ePowerSwitch' : 'ePowerSwitchOld',
+                               'ilo2' : 'HPiLO',
+                               'ilo1' : 'HPiLO',
+                               'PM211-MIP' : 'PM211MIP',
+                               'AMT2.5' : 'IntelAMT',
+                               'AMT3.0' : 'IntelAMT',
+                               'WTI_IPS-4' : 'WTIIPS4',
+                               'unknown'  : 'ManualPCU',
+                               'DRAC5' : 'DRAC',
+                               'ipmi'  : 'OpenIPMI',
+                               'bbsemaverick' : 'BlackBoxPSMaverick',
+                               'manualadmin'  : 'ManualPCU',
+       }
+
+       if oldmodelname in update:
+               newmodelname = update[oldmodelname]
+       else:
+               newmodelname = oldmodelname
+
+       if pcu_id in [1102,1163,1055,1111,1231,1113,1127,1128,1148]:
+               newmodelname = 'APCControl12p3'
+       elif pcu_id in [1110,86]:
+               newmodelname = 'APCControl1p4'
+       elif pcu_id in [1221,1225,1220,1192]:
+               newmodelname = 'APCControl121p3'
+       elif pcu_id in [1173,1240,47,1363,1405,1401,1372,1371]:
+               newmodelname = 'APCControl121p1'
+       elif pcu_id in [1056,1237,1052,1209,1002,1008,1013,1022]:
+               newmodelname = 'BayTechCtrlC'
+       elif pcu_id in [93]:
+               newmodelname = 'BayTechRPC3NC'
+       elif pcu_id in [1057]:
+               newmodelname = 'BayTechCtrlCUnibe'
+       elif pcu_id in [1012]:
+               newmodelname = 'BayTechRPC16'
+       elif pcu_id in [1089, 1071, 1046, 1035, 1118]:
+               newmodelname = 'ePowerSwitchNew'
+
+       return newmodelname
+
+def reboot_test_new(nodename, values, verbose, dryrun):
+       rb_ret = ""
+       if 'plc_pcu_stats' in values:
+               values.update(values['plc_pcu_stats'])
 
 
+       try:
+               #modelname = convert_oldmodelname_to_newmodelname(values['model'], values['pcu_id'])
+               modelname = values['model']
+               if modelname:
+                       object = eval('%s(values, verbose)' % modelname)
+                       rb_ret = object.reboot(values[nodename], dryrun)
+               else:
+                       rb_ret =  "Not_Run"
+               # TODO: how to handle the weird, georgetown pcus, the drac faults, and ilo faults
        except ExceptionPort, err:
                rb_ret = str(err)
        except ExceptionPort, err:
                rb_ret = str(err)
+       except NameError, err:
+               rb_ret = str(err)
 
        return rb_ret
 
        return rb_ret
-       # ????
-       #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)
 
 def main():
 
 def main():
-       logger.setLevel(logging.DEBUG)
-       ch = logging.StreamHandler()
-       ch.setLevel(logging.DEBUG)
-       formatter = logging.Formatter('LOGGER - %(message)s')
-       ch.setFormatter(formatter)
-       logger.addHandler(ch)
-
-       try:
-               if "test" in sys.argv:
-                       dryrun = True
-               else:
-                       dryrun = False
-
-               for node in sys.argv[1:]:
-                       if node == "test": continue
-
-                       print "Rebooting %s" % node
-                       if reboot_policy(node, True, dryrun):
-                               print "success"
-                       else:
-                               print "failed"
-       except Exception, err:
-               import traceback; traceback.print_exc()
-               print err
+       print "this does not work."
 
 if __name__ == '__main__':
 
 if __name__ == '__main__':
-       import plc
-       logger = logging.getLogger("monitor")
        main()
        main()