Enhance, simplify and beautify DRAC & HPiLO support with expect scripts
Stephen Soltesz [Sun, 17 Apr 2011 00:26:16 +0000 (20:26 -0400)]
Added pcuProxy&HPiLoProxy support for when pcu is behind a firewall.
Added BasicPCUControl definition to simplify implementation.

pcucontrol/models/DRAC.py
pcucontrol/models/HPiLO.py
pcucontrol/models/HPiLOProxy.py [new file with mode: 0644]
pcucontrol/models/__init__.py
pcucontrol/models/exp/DRAC.exp [new file with mode: 0755]
pcucontrol/models/exp/HPiLO.exp [new file with mode: 0755]
pcucontrol/reboot.py
pcucontrol/support/pcuProxy.php [new file with mode: 0644]
pcucontrol/util/command.py

index 11d23f6..672d92f 100644 (file)
 from pcucontrol.reboot import *
 import time
 
-class DRAC(PCUControl):
-       supported_ports = [22,443,5869]
-       def run_drac(self, node_port, dryrun):
-               print "trying racadm_reboot..."
-               return racadm_reboot(self.host, self.username, self.password, node_port, dryrun)
-
-       def run_ssh(self, node_port, dryrun):
-               ssh_options="-o StrictHostKeyChecking=no "+\
-                           "-o PasswordAuthentication=yes "+\
-                                       "-o PubkeyAuthentication=no"
-               s = pxssh.pxssh()
-               try:
-                       if not s.login(self.host, self.username, self.password, ssh_options,
-                                               original_prompts="Dell", login_timeout=Transport.TELNET_TIMEOUT):
-                               raise ExceptionPassword("Invalid Password")
-               except pexpect.EOF:
-                       raise ExceptionPrompt("Disconnect before login prompt")
-                       
-               print "logging in... %s" % self.host
-               s.send("\r\n\r\n")
-               try:
-                       # Testing Reboot ?
-                       #index = s.expect(["DRAC 5", "[%s]#" % self.username ])
-                       # NOTE: be careful to escape any characters used by 're.compile'
-                       index = s.expect(["\$", "\[%s\]#" % self.username, "/.*>" ])
-                       print "INDEX:", index
-                       print s
-                       if dryrun:
-                               if index == 0:
-                                       s.sendline("racadm getsysinfo")
-                               elif index == 1:
-                                       s.sendline("getsysinfo")
-                               elif index == 2:
-                                       s.sendline("racadm getsysinfo")
-                       else:
-                               print "serveraction powercycle"
-                               if index == 0:
-                                       s.sendline("racadm serveraction powercycle")
-                               elif index == 1:
-                                       s.sendline("serveraction powercycle")
-                               elif index == 2:
-                                       s.sendline("racadm serveraction powercycle")
-                               
-                       # TODO:  this is really lousy.  Without the sleep, the sendlines
-                       # don't completely get through.  Even the added, expect line
-                       # returns right away without waiting for the commands above to
-                       # complete...  Therefore, this delay is guaranteed to fail in some
-                       # other context...
-                       s.send("\r\n\r\n")
-                       time.sleep(20)
-                       index = s.expect(["\$", "\[%s\]#" % self.username, "/.*>" ])
-                       print s
-                       print "INDEX 2:", index
-                       s.sendline("exit")
-
-               except pexpect.EOF:
-                       raise ExceptionPrompt("EOF before expected Prompt")
-               except pexpect.TIMEOUT:
-                       print s
-                       raise ExceptionPrompt("Timeout before expected Prompt")
-
-               s.close()
-
-               return 0
-
-### 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
-                       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 -u %s -p '%s' serveraction powercycle" % (ip, username, password)],
-                               username, password)
-               else:
-                       output = runcmd(cmd, ["-r %s -u %s -p '%s' getsysinfo" % (ip, username, password)],
-                               username, password)
-
-               print "RUNCMD: %s" % output
-               if verbose:
-                       print output
-               return 0
-
-       except Exception, err:
-               print "runcmd raised exception %s" % err
-               return str(err)
+class DRAC(BasicPCUControl):
+    supported_ports = [22,443,5869]
+    def run_drac(self, node_port, dryrun):
+        return self.run_expect_script("DRAC.exp racadm5", dryrun=dryrun, model="None")
+
+    def run_ssh(self, node_port, dryrun):
+        return self.run_expect_script("DRAC.exp ssh", dryrun=dryrun, model="None")
+
+    def pcu_run(self, node_port):
+        r = self.run_ssh(node_port, dryrun=False)
+        if "No error" in r:
+            return r
+        r2 = self.run_drac(node_port, dryrun=False)
+        if "No error" in r2:
+            return r2
+        return r + " :: " +r2
+
+    def pcu_test(self, node_port):
+        r = self.run_ssh(node_port, dryrun=True)
+        if "No error" in r:
+            return r
+        r2 = self.run_drac(node_port, dryrun=True)
+        if "No error" in r2:
+            return r2
+        return r + " :: " +r2
index 2037ab7..e0595be 100644 (file)
@@ -2,8 +2,8 @@ from pcucontrol.reboot import *
 from distutils.sysconfig import get_python_lib; 
 import subprocess
 
-class HPiLO(PCUControl):
-    supported_ports = [22,443]
+class HPiLO(BasicPCUControl):
+    supported_ports = [443,22]
     def run(self, node_port, dryrun):
         if self.type == Transport.SSH:
             return self.run_ssh(node_port, dryrun)
@@ -12,67 +12,26 @@ class HPiLO(PCUControl):
         else:
             raise ExceptionNoTransport("Unimplemented Transport for HPiLO %s" % self.type)
 
-    def run_ssh(self, node_port, dryrun):
-
-        self.transport.open(self.host, self.username)
-        self.transport.sendPassword(self.password)
-
-        # </>hpiLO-> 
-        self.transport.ifThenSend("</>hpiLO->", "cd system1")
-
-        # Reboot Outlet  N      (Y/N)?
-        if dryrun:
-            self.transport.ifThenSend("</system1>hpiLO->", "POWER")
-        else:
-            # Reset this machine
-            self.transport.ifThenSend("</system1>hpiLO->", "reset")
+    def pcu_run(self, node_port):
+        r = self.run_https(node_port, dryrun=False)
+        if "No error" in r:
+            return r
+        r2 = self.run_ssh(node_port, dryrun=False)
+        if "No error" in r2:
+            return r2
+        return r + " :: " +r2
+
+    def pcu_test(self, node_port):
+        r = self.run_https(node_port, dryrun=True)
+        if "No error" in r:
+            return r
+        r2 = self.run_ssh(node_port, dryrun=True)
+        if "No error" in r2:
+            return r2
+        return r + " :: " +r2
 
-        self.transport.ifThenSend("</system1>hpiLO->", "exit")
-
-        self.transport.close()
-
-        # NOTE: if an error occurs earlier, an exception should be thrown
-        return 0
+    def run_ssh(self, node_port, dryrun):
+        return self.run_expect_script("HPiLO.exp ssh", dryrun=dryrun, model="None")
         
     def run_https(self, node_port, dryrun):
-
-        locfg = command.CMD()
-
-        cmd_str = get_python_lib(1) + "/pcucontrol/models/hpilo/"
-        
-        cmd = cmd_str + "locfg.pl -s %s -f %s -u %s -p '%s' "  % (
-                    self.host, cmd_str+"iloxml/Get_Network.xml", 
-                    self.username, self.password)
-        cmd_out, cmd_err = locfg.run_noexcept(cmd)
-
-        if locfg.s.returncode != 0:
-            return cmd_out.strip() + cmd_err.strip()
-
-        if dryrun: 
-            return 0
-
-        locfg = command.CMD()
-        cmd = cmd_str + "locfg.pl -s %s -f %s -u %s -p '%s'" % (
-                    self.host, cmd_str+"iloxml/PowerOn_Server.xml", 
-                    self.username, self.password)
-        cmd_out, cmd_err = locfg.run_noexcept(cmd)
-
-        locfg = command.CMD()
-        cmd = cmd_str + "locfg.pl -s %s -f %s -u %s -p '%s'" % (
-                    self.host, cmd_str+"iloxml/Reset_Server.xml", 
-                    self.username, self.password)
-        cmd_out, cmd_err = locfg.run_noexcept(cmd)
-
-        cmd = "grep 'MESSAGE' | grep -v 'No error' | grep -v 'Server being reset.'"
-        p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, 
-                            stderr=subprocess.STDOUT, close_fds=True)
-        (grep_in, grep_out ) = (p.stdin, p.stdout)
-        grep_in.write(cmd_out)
-        grep_in.close()         # close so read does not block
-        output = grep_out.read()
-        if output.strip() != "":
-            print "grep_out: %s" % output.strip()
-            return output.strip()
-
-        # NOTE: if an error occurs earlier, an exception should be thrown
-        return 0
+        return self.run_expect_script("HPiLO.exp https", dryrun=dryrun, model="None")
diff --git a/pcucontrol/models/HPiLOProxy.py b/pcucontrol/models/HPiLOProxy.py
new file mode 100644 (file)
index 0000000..1acfb02
--- /dev/null
@@ -0,0 +1,18 @@
+from pcucontrol.reboot import *
+import subprocess
+import urllib
+
+class HPiLOProxy(BasicPCUControl):
+    supported_ports = [80]
+
+    def pcu_run(self, node_port):
+        return self.proxy(node_port, False)
+        
+    def pcu_test(self, node_port):
+        return self.proxy(node_port, True)
+
+    def proxy(self, node_port, dryrun):
+        return self.run_expect_script("HPiLO.exp proxy", 
+                                    dryrun=dryrun, 
+                                    model=self.__class__.__name__)
+
index 01d8f4b..5158cff 100644 (file)
@@ -5,6 +5,7 @@ from APCControl import *
 from IntelAMT import *
 from DRAC import *
 from HPiLO import *
+from HPiLOProxy import *
 from BayTech import *
 from WTIIPS4 import *
 from ePowerSwitch import *
diff --git a/pcucontrol/models/exp/DRAC.exp b/pcucontrol/models/exp/DRAC.exp
new file mode 100755 (executable)
index 0000000..efa4562
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/expect
+
+set timeout 20
+set method [lindex $argv 0]
+set host [lindex $argv 1]
+set user [lindex $argv 2]
+set password [lindex $argv 3]
+set dryrun [lindex $argv 4]
+set model [lindex $argv 5]
+
+log_user 0
+if { "$dryrun" == "True" } {
+    set reset_msg "Test: No error"
+} else {
+    set reset_msg "Reset: No error"
+}
+
+
+if { "$method" == "ssh" } {
+    send_user "spawn ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=yes -o PubkeyAuthentication=no $user@$host\n"
+    set cont 0
+    for { set retry 0 } { $retry < 2 } { incr retry 1 } {
+
+        # NOTE: For unknown reason, some DRAC modules work only with
+        #       stderr redirected to stdout, others only work without it.
+        if { $retry == 0 } {
+            spawn ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=yes -o PubkeyAuthentication=no $user@$host 2>&1
+        } else {
+            spawn ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=yes -o PubkeyAuthentication=no $user@$host 
+        }
+
+        expect {
+            "Are you sure you want to continue connecting (yes/no)? " { send "yes\n" ; exp_continue }
+            "password: " { send "$password\n" ; exp_continue }
+            "Permission denied" { send_user "DRAC ssh: username/password: $expect_out(0,string)"; exit }
+            "Could not resolve hostname" { send_user "DRAC ssh: $expect_out(0,string)"; exit }
+            -re "Received disconnect.*" { send_user "DRAC ssh: $expect_out(0,string)"; exit}
+            -re "\\$|/.*>|\[$user\]#" { send "\r"; } 
+            eof { set cont 1 }
+        }
+        if { $cont == 0 } { break; }
+
+    }
+
+    if { "$dryrun" == "True" } {
+        expect {
+            -re "\\$|/.*>" { send "racadm getsysinfo\r"; } 
+            -re "\[$user\]#" { send "getsysinfo\r" }
+        }
+    } else {
+        expect {
+            -re "\\$|/.*>" { send "racadm serveraction powercycle\r"; } 
+            -re "\[$user\]#" { send "serveraction powercycle\r" }
+        }
+    }
+    expect -re "\\$|/.*>|\[$user\]#" { send "exit\r"; } 
+
+    expect eof { send_user "$reset_msg\n" }
+
+} else { 
+    if { [string match "*racadm*" $method] } {
+        if { "$dryrun" == "True" } {
+            set rac_cmd "getsysinfo"
+        } else {
+            set rac_cmd "serveraction powercycle"
+        }
+        send_user "/opt/dell/srvadmin/bin/$method -r $host -u $user -p '$password' $rac_cmd\n";
+        set cont 0
+        for { set retry 0 } { $retry < 2 } { incr retry 1 } {
+
+            # NOTE: For unknown reason, placing the pasword 
+            #       on the cmdline causes racadm to fail.
+            # NOTE: For unknown reason, some DRAC modules work only with
+            #       stderr redirected to stdout, others only work without it.
+            if { $retry == 0 } {
+                set x [ spawn /opt/dell/srvadmin/bin/$method -i -r $host $rac_cmd 2>&1 ]
+            } else {
+                set x [ spawn /opt/dell/srvadmin/bin/$method -i -r $host $rac_cmd  ]
+            }
+
+            expect {
+                -re "ERROR:.*" { send_user "DRAC: $expect_out(0,string)"; exit }
+                -re "UserName:|username:" { send "$user\r" ; exp_continue };
+                -re "Password:|password:" { send "$password\r" };
+            }
+
+            expect {
+                -re "Authentication failed.*" { send_user "DRAC: $expect_out(0,string)"; exit }
+                -re "This.*not support remote RACADM" { send_user "DRAC: $expect_out(0,string)" ; exit }
+                -re "ERROR: The syntax of the command specified is not correct." { set cont 1 }
+                -re "RAC Information:" { sleep .1; }
+                #-re "ERROR:.*" { send_user "DRAC: $expect_out(0,string)"; exit }
+            }
+            if { $cont == 0 } { break; }
+        }
+        # If one of these are present, then the status information has been returned.
+        # otherwise an expect error will be thrown, signaling the caller.
+        expect {
+            -re "Power Status.*" { sleep .1; } 
+            -re "RAC Firmware.*" { sleep .1; }
+        } 
+        expect eof { send_user "$reset_msg\n" }
+    }
+}
diff --git a/pcucontrol/models/exp/HPiLO.exp b/pcucontrol/models/exp/HPiLO.exp
new file mode 100755 (executable)
index 0000000..ec064a5
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/expect
+
+set timeout 60
+set method [lindex $argv 0]
+set host [lindex $argv 1]
+set user [lindex $argv 2]
+set password [lindex $argv 3]
+set dryrun [lindex $argv 4]
+set model [lindex $argv 5]
+
+log_user 0
+
+if { "$method" == "https" } {
+    if { "$dryrun" == "True" } {
+        set file $path/iloxml/Get_Network.xml
+    } else {
+        #set file $path/iloxml/Reset_Server.xml
+        set file $path/iloxml/Get_Network.xml
+    }
+    spawn "$path/locfg.pl" -s $host -u $user -p '$password' -f $file
+} elseif { "$method" == "ssh" } {
+    if { "$dryrun" == "True" } {
+        set reset_cmd "POWER\r"
+        set reset_msg "Test: No error"
+    } else {
+        #set reset_cmd "reset\r"
+        set reset_cmd "POWER\r"
+        set reset_msg "Reset: No error"
+    }
+    spawn ssh $user@$host
+} elseif { "$method" == "proxy" } {
+    set url "http://www.cs.princeton.edu/~soltesz/pcuProxy.php"
+    set query "username=$user&password=$password&hostname=$host&model=$model&dryrun=$dryrun"
+    spawn curl -s "$url?$query"
+}
+
+if { "$method" == "proxy" || "$method" == "https" }  {
+    # Check for any one of the following patterns, then print it and stop.
+    expect {
+        "MESSAGE='Server being reset.'" { send_user "Reset: No error" }
+        "MESSAGE='Host power is already ON.'" { send_user "$expect_out(0,string)"}
+        "MESSAGE='Host power is already OFF.'" { send_user "$expect_out(0,string)"}
+        "MESSAGE='Login credentials rejected.'" { send_user "$expect_out(0,string)"}
+        "<GET_NETWORK_SETTINGS>" { send_user "Test: No error"}
+        -re "ERROR:.*" { send_user "$expect_out(0,string)" }
+        eof { send_user "Reached EOF without status report: $expect_out(buffer)" }
+    }
+} elseif { "$method" == "ssh" } {
+
+    expect {
+        "Are you sure you want to continue connecting (yes/no)? " { send "yes\n" ; exp_continue }
+        "password: " { send "$password\n" ; exp_continue }
+        "Permission denied" { send_user "HPiLO username/password: $expect_out(0,string)"; exit }
+        "Could not resolve hostname" { send_user "HPiLO hostname: $expect_out(0,string)"; exit }
+        "</>hpiLO-> " { send "cd system1\r" }
+    }
+
+    expect "</system1>hpiLO-> " { send $reset_cmd }
+    expect "</system1>hpiLO-> " { send "exit\r" }
+    expect eof { send_user $reset_msg }
+
+}
index 122edbb..a6e1934 100755 (executable)
@@ -12,6 +12,7 @@ import urllib
 import array, struct
 import base64
 from subprocess import PIPE, Popen
+from distutils.sysconfig import get_python_lib; 
 import subprocess
 import pcucontrol.transports.ssh.pxssh as pxssh
 import pcucontrol.transports.ssh.pexpect as pexpect
@@ -51,430 +52,479 @@ class ExceptionUsername(Exception): pass
 
 # This is an object derived directly form the PLCAPI DB fields
 class PCU(object):
-       def __init__(self, plc_pcu_dict):
-               for field in ['username', 'password', 'site_id', 
-                                               'hostname', 'ip', 
-                                               'pcu_id', 'model', 
-                                               'node_ids', 'ports', ]:
-                       if field in plc_pcu_dict:
-                               if type(u"") == type(plc_pcu_dict[field]):
-                                       # NOTE: if is a unicode string, convert it.
-                                       self.__setattr__(field, str(plc_pcu_dict[field]))
-                               else:
-                                       self.__setattr__(field, plc_pcu_dict[field])
-                       else:
-                               raise Exception("No such field %s in PCU object" % field)
+    def __init__(self, plc_pcu_dict):
+        for field in ['username', 'password', 'site_id', 
+                        'hostname', 'ip', 
+                        'pcu_id', 'model', 
+                        'node_ids', 'ports', ]:
+            if field in plc_pcu_dict:
+                if type(u"") == type(plc_pcu_dict[field]):
+                    # NOTE: if is a unicode string, convert it.
+                    self.__setattr__(field, str(plc_pcu_dict[field]))
+                else:
+                    self.__setattr__(field, plc_pcu_dict[field])
+            else:
+                raise Exception("No such field %s in PCU object" % field)
 
 # These are the convenience functions build around the PCU object.
 class PCUModel(PCU):
-       def __init__(self, plc_pcu_dict):
-               PCU.__init__(self, plc_pcu_dict)
-               self.host = self.pcu_name()
-
-       def pcu_name(self):
-               if self.hostname is not None and self.hostname is not "":
-                       return self.hostname
-               elif self.ip is not None and self.ip is not "":
-                       return self.ip
-               else:
-                       return None
-
-       def nodeidToPort(self, node_id):
-               if node_id in self.node_ids:
-                       for i in range(0, len(self.node_ids)):
-                               if node_id == self.node_ids[i]:
-                                       return self.ports[i]
-
-               raise Exception("No such Node ID: %d" % node_id)
+    def __init__(self, plc_pcu_dict):
+        PCU.__init__(self, plc_pcu_dict)
+        self.host = self.pcu_name()
+
+    def pcu_name(self):
+        if self.hostname is not None and self.hostname is not "":
+            return self.hostname
+        elif self.ip is not None and self.ip is not "":
+            return self.ip
+        else:
+            return None
+
+    def nodeidToPort(self, node_id):
+        if node_id in self.node_ids:
+            for i in range(0, len(self.node_ids)):
+                if node_id == self.node_ids[i]:
+                    return self.ports[i]
+
+        raise Exception("No such Node ID: %d" % node_id)
+
+    def catcherror(self, function, node_port):
+        try:
+            return function(node_port)
+        except ExceptionNotFound, err:
+            return "Not found: " + str(err)
+        except ExceptionPassword, err:
+            return "Password exception: " + str(err)
+        except ExceptionTimeout, err:
+            return "Timeout exception: " + str(err)
+        except ExceptionUsername, err:
+            return "No username prompt: " + str(err)
+        except ExceptionSequence, err:
+            return "Sequence error: " + str(err)
+        except ExceptionPrompt, err:
+            return "Prompt exception: " + str(err)
+        except ExceptionNoTransport, err:
+            return "No Transport: " + str(err)
+        except ExceptionPort, err:
+            return "No ports exception: " + 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:
+            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)
 
 # This class captures the observed pcu records from FindBadPCUs.py
 class PCURecord:
-       def __init__(self, pcu_record_dict):
-               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])
-                       #else:
-                       #       raise Exception("No such field %s in pcu record dict" % field)
+    def __init__(self, pcu_record_dict):
+        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])
+            #else:
+            #    raise Exception("No such field %s in pcu record dict" % field)
 
 class Transport:
-       TELNET = "telnet"
-       SSH    = "ssh"
-       HTTP   = "http"
-       HTTPS  = "https"
-       IPAL   = "ipal"
-        IPMI   = "ipmi"
-       DRAC   = "drac"
-       AMT    = "amt"
-
-       TELNET_TIMEOUT = 120
-
-       porttypemap = {
-                       5869 : DRAC,
-                       22 : SSH,
-                       23 : TELNET,
-                       443 : HTTPS,
-                       80 :  HTTP,
-                       9100 : IPAL,
-                        623 : IPMI,
-                       16992 : AMT,
-               }
-
-       def __init__(self, type, verbose):
-               self.type = type
-               self.verbose = verbose
-               self.transport = None
-
-       def open(self, host, username=None, password=None, prompt="User Name"):
-               transport = None
-
-               if self.type == self.TELNET:
-                       transport = telnetlib.Telnet(host, timeout=self.TELNET_TIMEOUT)
-                       transport.set_debuglevel(self.verbose)
-                       if username is not None:
-                               self.transport = transport
-                               self.ifThenSend(prompt, username, ExceptionUsername)
-
-               elif self.type == self.SSH:
-                       if username is not None:
-                               transport = pyssh.Ssh(username, host)
-                               transport.set_debuglevel(self.verbose)
-                               transport.open()
-                               # TODO: have an ssh set_debuglevel() also...
-                       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)
-
-                       # create authinfo
-                       authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
-                       authinfo.add_password (None, uri, username, password)
-                       authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
-
-                       transport = urllib2.build_opener(authhandler)
-               else:
-                       raise Exception("Unknown transport type: %s" % self.type)
-
-               self.transport = transport
-               return True
-
-       def close(self):
-               if self.type == self.TELNET:
-                       self.transport.close() 
-               elif self.type == self.SSH:
-                       self.transport.close() 
-               elif self.type == self.HTTP:
-                       pass
-               else:
-                       raise Exception("Unknown transport type %s" % self.type)
-               self.transport = None
-
-       def write(self, msg):
-               return self.send(msg)
-
-       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:
-                       if prompt == None:
-                               self.ifThenSend("Password", password, ExceptionPassword)
-                       else:
-                               self.ifThenSend(prompt, password, ExceptionPassword)
-               elif self.type == self.SSH:
-                       self.ifThenSend("password:", password, ExceptionPassword)
-               elif self.type == self.HTTP:
-                       pass
-               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:
-                       output = self.transport.read_until(expected, self.TELNET_TIMEOUT)
-                       if output.find(expected) == -1:
-                               print "OUTPUT: --%s--" % output
-                               raise ErrorClass, "'%s' not found: Got: %s" % (expected, output)
-                       else:
-                               self.transport.write(buffer + "\r\n")
-               else:
-                       raise ExceptionNoTransport("transport object is type None")
-
-       def ifElse(self, expected, ErrorClass):
-               try:
-                       self.transport.read_until(expected, self.TELNET_TIMEOUT)
-               except:
-                       raise ErrorClass("Could not find '%s' within timeout" % expected)
+    TELNET = "telnet"
+    SSH    = "ssh"
+    HTTP   = "http"
+    HTTPS  = "https"
+    IPAL   = "ipal"
+    IPMI   = "ipmi"
+    DRAC   = "drac"
+    AMT    = "amt"
+
+    TELNET_TIMEOUT = 120
+
+    porttypemap = {
+            5869 : DRAC,
+            22 : SSH,
+            23 : TELNET,
+            443 : HTTPS,
+            80 :  HTTP,
+            9100 : IPAL,
+             623 : IPMI,
+            16992 : AMT,
+        }
+
+    def __init__(self, type, verbose):
+        self.type = type
+        self.verbose = verbose
+        self.transport = None
+
+    def open(self, host, username=None, password=None, prompt="User Name"):
+        transport = None
+
+        if self.type == self.TELNET:
+            transport = telnetlib.Telnet(host, timeout=self.TELNET_TIMEOUT)
+            transport.set_debuglevel(self.verbose)
+            if username is not None:
+                self.transport = transport
+                self.ifThenSend(prompt, username, ExceptionUsername)
+
+        elif self.type == self.SSH:
+            if username is not None:
+                transport = pyssh.Ssh(username, host)
+                transport.set_debuglevel(self.verbose)
+                transport.open()
+                # TODO: have an ssh set_debuglevel() also...
+            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)
+
+            # create authinfo
+            authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm()
+            authinfo.add_password (None, uri, username, password)
+            authhandler = urllib2.HTTPBasicAuthHandler( authinfo )
+
+            transport = urllib2.build_opener(authhandler)
+        else:
+            raise Exception("Unknown transport type: %s" % self.type)
+
+        self.transport = transport
+        return True
+
+    def close(self):
+        if self.type == self.TELNET:
+            self.transport.close() 
+        elif self.type == self.SSH:
+            self.transport.close() 
+        elif self.type == self.HTTP:
+            pass
+        else:
+            raise Exception("Unknown transport type %s" % self.type)
+        self.transport = None
+
+    def write(self, msg):
+        return self.send(msg)
+
+    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:
+            if prompt == None:
+                self.ifThenSend("Password", password, ExceptionPassword)
+            else:
+                self.ifThenSend(prompt, password, ExceptionPassword)
+        elif self.type == self.SSH:
+            self.ifThenSend("password:", password, ExceptionPassword)
+        elif self.type == self.HTTP:
+            pass
+        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:
+            output = self.transport.read_until(expected, self.TELNET_TIMEOUT)
+            if output.find(expected) == -1:
+                print "OUTPUT: --%s--" % output
+                raise ErrorClass, "'%s' not found: Got: %s" % (expected, output)
+            else:
+                self.transport.write(buffer + "\r\n")
+        else:
+            raise ExceptionNoTransport("transport object is type None")
+
+    def ifElse(self, expected, ErrorClass):
+        try:
+            self.transport.read_until(expected, self.TELNET_TIMEOUT)
+        except:
+            raise ErrorClass("Could not find '%s' within timeout" % expected)
 
 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 = []
-
-       def __init__(self, plc_pcu_record, verbose, ignored=None):
-               PCUModel.__init__(self, plc_pcu_record)
-               PCURecord.__init__(self, plc_pcu_record)
-
-       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:
-                               continue
-
-               return ret
-
-       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
-
-       #def reboot(self, node_port, dryrun):
-
-       def catcherror(self, function, node_port, dryrun):
-               try:
-                       return function(node_port, dryrun)
-               except ExceptionNotFound, err:
-                       return "error: " + str(err)
-               except ExceptionPassword, err:
-                       return "Password exception: " + str(err)
-               except ExceptionTimeout, err:
-                       return "Timeout exception: " + str(err)
-               except ExceptionUsername, err:
-                       return "No username prompt: " + str(err)
-               except ExceptionSequence, err:
-                       return "Sequence error: " + str(err)
-               except ExceptionPrompt, err:
-                       return "Prompt exception: " + str(err)
-               except ExceptionNoTransport, err:
-                       return "No Transport: " + str(err)
-               except ExceptionPort, err:
-                       return "No ports exception: " + 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:
-                       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)
+    """ 
+        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 = []
+
+    def __init__(self, plc_pcu_record, verbose, ignored=None):
+        PCUModel.__init__(self, plc_pcu_record)
+        PCURecord.__init__(self, plc_pcu_record)
+
+    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:
+                continue
+
+        return ret
+
+    def run(self, node_port, dryrun):
+        """ This function is to be defined by the specific PCU instance.  """
+        raise Exception("This function is not implemented")
+
+
+class BasicPCUControl(PCUModel):
+
+    """ 
+        This is the basic pcucontrol super class on which the classes in
+        pcucontrol/models/* are based.
+
+        Each model implements a specific 'run' function that can use any
+        mechanism available to reboot the given PCU using, hostname, password,
+        username, and dryrun.
+
+        This is best suited for nodes with built-in PCUs, iLO, AMT, DRAC, etc.
+    """
+
+    supported_ports = []
+    install_path = get_python_lib(1) + "/pcucontrol/"
+
+    def __init__(self, plc_pcu_record, ignored=None):
+        PCUModel.__init__(self, plc_pcu_record)
+
+    def run_expect_script(self, scriptname, **args):
+        locfg = command.CMD()
+
+        cmd_str = get_python_lib(1) + "/pcucontrol/models/exp/"
+        cmd = cmd_str + "%s %s %s '%s' %s %s "  % (
+                    scriptname, self.host, self.username, 
+                    self.password, args['dryrun'], args['model'])
+        cmd_out, cmd_err = locfg.run_noexcept(cmd)
+        return cmd_out.strip() + cmd_err.strip()
+
+    def reboot(self, node_port, dryrun):
+        if dryrun:
+            looking_for_fxn = 'pcu_test'
+        else:
+            looking_for_fxn = 'pcu_run'
+
+        # verify that the function exists.
+        if not hasattr(self, looking_for_fxn):
+            raise Exception("This model (%s) does not implement %s" % (self.model, looking_for_fxn))
+
+        print "found function %s in model %s" % (looking_for_fxn, self.model)
+        reboot_fxn = getattr(self, looking_for_fxn)
+        ret = self.catcherror(reboot_fxn, node_port)
+
+        return ret
+
+    def run(self, node_port, dryrun):
+        """ This function is to be defined by the specific PCU instance.  """
+        raise Exception("This function is not implemented")
+
 
 from pcucontrol.util import command
 from pcucontrol.models import *
 
 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
+    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
 
 class Unknown(PCUControl):
-       supported_ports = [22,23,80,443,5869,9100,16992]
+    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
-       elif "BayTech" in modelname:
-               return BayTech
-       elif "HPiLO" in modelname:
-               return HPiLO
-       elif "IPAL" in modelname:
-               return IPAL
-       elif "APC" in modelname:
-               return APCControl
-       elif "DRAC" in modelname:
-               return DRAC
-       elif "WTI" in modelname:
-               return WTIIPS4
-       elif "ePowerSwitch" in modelname:
-               return ePowerSwitchNew
-       elif "IPMI" in modelname:
-               return OpenIPMI
-       elif "BlackBoxPSMaverick" in modelname:
-               return BlackBoxPSMaverick
-       elif "PM211MIP" in modelname:
-               return PM211MIP
-       elif "ManualPCU" in modelname:
-               return ManualPCU 
-       else:
-               print "UNKNOWN model %s"%modelname
-               return Unknown
+    if modelname is None:
+        return ManualPCU 
+    if "AMT" in modelname:
+        return IntelAMT
+    elif "BayTech" in modelname:
+        return BayTech
+    elif "HPiLO" in modelname:
+        return HPiLO
+    elif "IPAL" in modelname:
+        return IPAL
+    elif "APC" in modelname:
+        return APCControl
+    elif "DRAC" in modelname:
+        return DRAC
+    elif "WTI" in modelname:
+        return WTIIPS4
+    elif "ePowerSwitch" in modelname:
+        return ePowerSwitchNew
+    elif "IPMI" in modelname:
+        return OpenIPMI
+    elif "BlackBoxPSMaverick" in modelname:
+        return BlackBoxPSMaverick
+    elif "PM211MIP" in modelname:
+        return PM211MIP
+    elif "ManualPCU" in modelname:
+        return ManualPCU 
+    else:
+        print "UNKNOWN model %s"%modelname
+        return Unknown
 
 def reboot_api(node, pcu, testrun=False):
-       rb_ret = ""
-
-       try:
-               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, testrun)
-               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)
-
-       return rb_ret
+    rb_ret = ""
+
+    try:
+        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, testrun)
+        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)
+
+    return rb_ret
 
 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
+    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 NameError, err:
-               rb_ret = str(err)
-
-       return rb_ret
+    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 NameError, err:
+        rb_ret = str(err)
+
+    return rb_ret
 
 def main():
-       print "this does not work."
+    print "this does not work."
 
 if __name__ == '__main__':
-       main()
+    main()
diff --git a/pcucontrol/support/pcuProxy.php b/pcucontrol/support/pcuProxy.php
new file mode 100644 (file)
index 0000000..3cfcc47
--- /dev/null
@@ -0,0 +1,62 @@
+<?php 
+
+function logit($string){
+               $f = fopen("output.log", 'a');
+               fwrite($f, $string);
+               fclose($f);
+}
+
+function run_hp_script($script, $host, $username, $password)
+{
+       $cmd = "hpilo/locfg.pl -s $host -f $script -u $username -p '$password' 2>&1"; 
+       logit("cmd: " . $cmd);
+       return system($cmd);
+
+               $f = fopen("output.log", 'a');
+               fwrite($f, print_r($_REQUEST, TRUE));
+               fclose($f);
+
+}
+
+       if ( isset($_REQUEST['hostname']) && 
+                isset($_REQUEST['username']) && 
+                isset($_REQUEST['password']) &&
+                isset($_REQUEST['model']) )
+       {
+               $host=$_REQUEST['hostname'];
+               $username=$_REQUEST['username'];
+               $password=$_REQUEST['password'];
+               $model=$_REQUEST['model'];
+               if ( isset($_REQUEST['dryrun']) ) 
+               {
+                       $dryrun = $_REQUEST['dryrun'];
+                       settype($dryrun, "boolean");
+               } else {
+                       $dryrun = TRUE;
+               }
+
+               logit(print_r($_REQUEST, TRUE));
+
+               if (strcmp($model,"HPiLOProxy") == 0) {
+                       if ( $dryrun ) 
+                       {
+                               run_hp_script("hpilo/iloxml/Get_Network.xml", $host, $username, $password);
+                       } else {
+                               run_hp_script("hpilo/iloxml/PowerOn_Server.xml", $host, $username, $password);
+                               echo run_hp_script("hpilo/iloxml/Reset_Server.xml", $host, $username, $password);
+                       }
+               } elseif ( strcmp($model,"OpenIPMIProxy") == 0 )
+               {
+                       # cmd = "ipmitool -I lanplus -H $host -U $username -P '$password' user list"
+                       # cmd = "ipmitool -I lanplus -H $host -U $username -P '$password' power cycle"
+                       echo system("which ipmitool 2>&1");
+               } else 
+               {
+                       echo "what do you want me to do with this?";
+               }
+
+       } else {
+               echo "Please provide hostname, username, and password";
+       }
+
+?>
index 42e00a9..74b5fae 100644 (file)
@@ -91,7 +91,11 @@ class CMD:
 
        def run(self, cmd, timeout=COMMAND_TIMEOUT*2):
 
-               s = Sopen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
+               s = Sopen(cmd, shell=True, 
+                    stdin=subprocess.PIPE, 
+                    stdout=subprocess.PIPE, 
+                    stderr=subprocess.PIPE, 
+                    close_fds=True)
                self.s = s
                (f_in, f_out, f_err) = (s.stdin, s.stdout, s.stderr)
                lout, lin, lerr = select([f_out], [], [f_err], timeout)