changes for 3.0
[monitor.git] / racadm.py
1 #!/usr/bin/python
2
3 import threading
4 import socket
5 import os
6 import popen2
7 #import logger
8
9 def runcmd(command, args, username, password, timeout = None):
10
11         result = [None]
12         result_ready = threading.Condition()
13
14         def set_result(x):
15
16                 result_ready.acquire()
17                 try:
18                         result[0] = x
19                 finally:
20                         result_ready.notify()
21                         result_ready.release()
22
23         def do_command(command, username, password):
24
25                 try:
26                         # Popen4 is a popen-type class that combines stdout and stderr
27                         p = popen2.Popen4(command)
28
29                         # read all output data
30                         p.tochild.write("%s\n" % username)
31                         p.tochild.write("%s\n" % password)
32                         p.tochild.close()
33                         data = p.fromchild.read()
34
35                         while True:
36                                 # might get interrupted by a signal in poll() or waitpid()
37                                 try:
38                                         retval = p.wait()
39                                         set_result((retval, data))
40                                         break
41                                 except OSError, ex:
42                                         if ex.errno == errno.EINTR:
43                                                 continue
44                                         raise ex
45                 except Exception, ex:
46                         set_result(ex)
47
48         if args:
49                 command = " ".join([command] + args)
50
51         worker = threading.Thread(target = do_command, args = (command, username, password, ))
52         worker.setDaemon(True)
53         result_ready.acquire()
54         worker.start()
55         result_ready.wait(timeout)
56         try:
57                 if result == [None]:
58                         raise Exception, "command timed-out: '%s'" % command
59         finally:
60                 result_ready.release()
61         result = result[0]
62
63         if isinstance(result, Exception):
64                 raise result
65         else:
66                 (retval, data) = result
67                 if os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == 0:
68                         return data
69                 else:
70                         out = "system command ('%s') " % command
71                         if os.WIFEXITED(retval):
72                                 out += "failed, rc = %d" % os.WEXITSTATUS(retval)
73                         else:
74                                 out += "killed by signal %d" % os.WTERMSIG(retval)
75                         if data:
76                                 out += "; output follows:\n" + data
77                         raise Exception, out
78
79 def racadm_reboot(host, username, password, dryrun, state="powercycle"):
80
81         ip = socket.gethostbyname(host)
82         try:
83                 cmd = "/usr/sbin/racadm"
84                 os.stat(cmd)
85                 if not dryrun:
86                         output = runcmd(cmd, ["-r %s -i serveraction %s" % (ip, state)],
87                                 username, password)
88                 else:
89                         output = runcmd(cmd, ["-r %s -i getsysinfo" % ip],
90                                 username, password)
91
92                 print "RUNCMD: %s" % output
93                 return 0
94
95         except Exception, err:
96                 #logger.debug("runcmd raised exception %s" % err)
97                 print "runcmd raised exception %s" % err
98                 return -1
99
100
101 from optparse import OptionParser
102 parser = OptionParser()
103 parser.set_defaults(ip="", user="", password="", state="powercycle")
104 parser.add_option("-r", "", dest="ip", metavar="nodename.edu", 
105                                         help="A single node name to add to the nodegroup")
106 parser.add_option("-u", "", dest="user", metavar="username",
107                                         help="")
108 parser.add_option("-s", "", dest="state", metavar="powercycle",
109                                         help="")
110 parser.add_option("-p", "", dest="password", metavar="password",
111                                         help="")
112 (options, args) = parser.parse_args()
113
114 if __name__ == '__main__':
115         print options
116         if      options.ip is not "" and \
117                 options.user is not "" and \
118                 options.password is not "":
119
120                 racadm_reboot(options.ip, options.user, options.password, False, options.state)
121         else:
122                 parser.print_help()