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