712cf19eb1a3fb4df845a42247e87ae44c4e49ce
[monitor.git] / pcucontrol / models / DRAC.py
1 from pcucontrol.reboot import *
2 import time
3
4 class DRAC(PCUControl):
5         supported_ports = [22,443,5869]
6         def run_drac(self, node_port, dryrun):
7                 print "trying racadm_reboot..."
8                 return racadm_reboot(self.host, self.username, self.password, node_port, dryrun)
9
10         def run_ssh(self, node_port, dryrun):
11                 ssh_options="-o StrictHostKeyChecking=no "+\
12                             "-o PasswordAuthentication=yes "+\
13                                         "-o PubkeyAuthentication=no"
14                 s = pxssh.pxssh()
15                 try:
16                         if not s.login(self.host, self.username, self.password, ssh_options,
17                                                 original_prompts="Dell", login_timeout=Transport.TELNET_TIMEOUT):
18                                 raise ExceptionPassword("Invalid Password")
19                 except pexpect.EOF:
20                         raise ExceptionPrompt("Disconnect before login prompt")
21                         
22                 print "logging in... %s" % self.host
23                 s.send("\r\n\r\n")
24                 try:
25                         # Testing Reboot ?
26                         #index = s.expect(["DRAC 5", "[%s]#" % self.username ])
27                         # NOTE: be careful to escape any characters used by 're.compile'
28                         index = s.expect(["\$", "\[%s\]#" % self.username ])
29                         print "INDEX:", index
30                         print s
31                         if dryrun:
32                                 if index == 0:
33                                         s.sendline("racadm getsysinfo")
34                                 elif index == 1:
35                                         s.sendline("getsysinfo")
36                         else:
37                                 print "serveraction powercycle"
38                                 if index == 0:
39                                         s.sendline("racadm serveraction powercycle")
40                                 elif index == 1:
41                                         s.sendline("serveraction powercycle")
42                                 
43                         # TODO:  this is really lousy.  Without the sleep, the sendlines
44                         # don't completely get through.  Even the added, expect line
45                         # returns right away without waiting for the commands above to
46                         # complete...  Therefore, this delay is guaranteed to fail in some
47                         # other context...
48                         s.send("\r\n\r\n")
49                         time.sleep(20)
50                         index = s.expect(["\$", "\[%s\]#" % self.username ])
51                         print s
52                         print "INDEX 2:", index
53                         s.sendline("exit")
54
55                 except pexpect.EOF:
56                         raise ExceptionPrompt("EOF before expected Prompt")
57                 except pexpect.TIMEOUT:
58                         print s
59                         raise ExceptionPrompt("Timeout before expected Prompt")
60
61                 s.close()
62
63                 return 0
64
65 ### rebooting Dell systems via RAC card
66 # Marc E. Fiuczynski - June 01 2005
67 # tested with David Lowenthal's itchy/scratchy nodes at UGA
68 #
69 def runcmd(command, args, username, password, timeout = None):
70
71         result = [None]
72         result_ready = threading.Condition()
73
74         def set_result(x):
75
76                 result_ready.acquire()
77                 try:
78                         result[0] = x
79                 finally:
80                         result_ready.notify()
81                         result_ready.release()
82
83         def do_command(command, username, password):
84
85                 try:
86                         # Popen4 is a popen-type class that combines stdout and stderr
87                         p = popen2.Popen4(command)
88
89                         # read all output data
90                         p.tochild.write("%s\n" % username)
91                         p.tochild.write("%s\n" % password)
92                         p.tochild.close()
93                         data = p.fromchild.read()
94
95                         while True:
96                                 # might get interrupted by a signal in poll() or waitpid()
97                                 try:
98                                         retval = p.wait()
99                                         set_result((retval, data))
100                                         break
101                                 except OSError, ex:
102                                         if ex.errno == errno.EINTR:
103                                                 continue
104                                         raise ex
105                 except Exception, ex:
106                         set_result(ex)
107
108         if args:
109                 command = " ".join([command] + args)
110
111         worker = threading.Thread(target = do_command, args = (command, username, password, ))
112         worker.setDaemon(True)
113         result_ready.acquire()
114         worker.start()
115         result_ready.wait(timeout)
116         try:
117                 if result == [None]:
118                         raise Exception, "command timed-out: '%s'" % command
119         finally:
120                 result_ready.release()
121         result = result[0]
122
123         if isinstance(result, Exception):
124                 raise result
125         else:
126                 (retval, data) = result
127                 if os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == 0:
128                         return data
129                 else:
130                         out = "system command ('%s') " % command
131                         if os.WIFEXITED(retval):
132                                 out += "failed, rc = %d" % os.WEXITSTATUS(retval)
133                         else:
134                                 out += "killed by signal %d" % os.WTERMSIG(retval)
135                         if data:
136                                 out += "; output follows:\n" + data
137                         raise Exception, out
138
139 def racadm_reboot(host, username, password, port, dryrun):
140         global verbose
141
142         ip = socket.gethostbyname(host)
143         try:
144                 cmd = "/usr/sbin/racadm"
145                 os.stat(cmd)
146                 if not dryrun:
147                         output = runcmd(cmd, ["-r %s -i serveraction powercycle" % ip],
148                                 username, password)
149                 else:
150                         output = runcmd(cmd, ["-r %s -i getsysinfo" % ip],
151                                 username, password)
152
153                 print "RUNCMD: %s" % output
154                 if verbose:
155                         print output
156                 return 0
157
158         except Exception, err:
159                 print "runcmd raised exception %s" % err
160                 return str(err)