PCU Class objects broken out into individual files.
[monitor.git] / pcucontrol / models / DRAC.py
1 from pcucontrol.reboot import *
2
3 class DRAC(PCUControl):
4         supported_ports = [22,443,5869]
5         def run_drac(self, node_port, dryrun):
6                 print "trying racadm_reboot..."
7                 return racadm_reboot(self.host, self.username, self.password, node_port, dryrun)
8
9         def run_ssh(self, node_port, dryrun):
10                 ssh_options="-o StrictHostKeyChecking=no "+\
11                             "-o PasswordAuthentication=yes "+\
12                                         "-o PubkeyAuthentication=no"
13                 s = pxssh.pxssh()
14                 if not s.login(self.host, self.username, self.password, ssh_options,
15                                                 original_prompts="Dell", login_timeout=Transport.TELNET_TIMEOUT):
16                         raise ExceptionPassword("Invalid Password")
17
18                 print "logging in..."
19                 s.send("\r\n\r\n")
20                 try:
21                         # Testing Reboot ?
22                         #index = s.expect(["DRAC 5", "[%s]#" % self.username ])
23                         # NOTE: be careful to escape any characters used by 're.compile'
24                         index = s.expect(["\$", "\[%s\]#" % self.username ])
25                         print "INDEX:", index
26                         if dryrun:
27                                 if index == 0:
28                                         s.send("racadm getsysinfo")
29                                 elif index == 1:
30                                         s.send("getsysinfo")
31                         else:
32                                 if index == 0:
33                                         s.send("racadm serveraction powercycle")
34                                 elif index == 1:
35                                         s.send("serveraction powercycle")
36                                 
37                         s.send("exit")
38
39                 except pexpect.EOF:
40                         raise ExceptionPrompt("EOF before expected Prompt")
41                 except pexpect.TIMEOUT:
42                         print s
43                         raise ExceptionPrompt("Timeout before expected Prompt")
44
45                 s.close()
46
47                 return 0
48
49 class DRACDefault(PCUControl):
50         supported_ports = [22,443,5869]
51         def run_ssh(self, node_port, dryrun):
52                 self.transport.open(self.host, self.username)
53                 self.transport.sendPassword(self.password)
54
55                 print "logging in..."
56                 self.transport.write("\r\n")
57                 # Testing Reboot ?
58                 if dryrun:
59                         self.transport.ifThenSend("[%s]#" % self.username, "getsysinfo")
60                 else:
61                         # Reset this machine
62                         self.transport.ifThenSend("[%s]#" % self.username, "serveraction powercycle")
63
64                 self.transport.ifThenSend("[%s]#" % self.username, "exit")
65
66                 self.transport.close()
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                         logger.debug(output)
160                 return 0
161
162         except Exception, err:
163                 logger.debug("runcmd raised exception %s" % err)
164                 if verbose:
165                         logger.debug(err)
166                 return err