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