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