1
2
3
4
5
6
7
8
9
10
11
12 __doc__ = """RunCommand
13 Run an event command on the local device or on the remote collector.
14 Assumes that SSH keys have been set up to all remote collectors.
15
16 Example usage:
17
18 dcsh -collector=xxx 'zencommand run'
19
20 The actual command to run *MUST* be in quotes!
21 """
22
23 import logging
24 log = logging.getLogger('zen.runCommand')
25
26 import os
27 from subprocess import Popen, PIPE
28 import StringIO
29 import signal
30
31 import Globals
32 from Products.ZenUtils.ZenScriptBase import ZenScriptBase
33 from Products.ZenUtils.Utils import zenPath
34
35
43
44
48
50 ZenScriptBase.buildOptions(self)
51 self.parser.add_option('--collector', dest='collector',
52 help="Name of specific collector on which to run the command")
53 self.parser.add_option('--timeout', dest='timeout',
54 default=60, type="int",
55 help="Kill the process after this many seconds.")
56 self.parser.add_option('-n', '--useprefix', action='store_false',
57 dest='useprefix', default=True,
58 help="Prefix the collector name for remote servers")
59
67
69 if self.options.collector:
70 try:
71 collectors = [self.dmd.Monitors.Performance._getOb(
72 self.options.collector)]
73 except AttributeError:
74 log.critical("No collector named %s could be found. Exiting",
75 self.options.collector)
76 return
77 else:
78 collectors = self.dmd.Monitors.Performance.objectValues(
79 spec="PerformanceConf")
80
81 return [collectorStats(x.id, getattr(x, 'hostname', x.id)) \
82 for x in collectors]
83
85 header = """
86 Collector StdOut/Stderr"""
87 delimLen = 65
88 print header
89 print '-' * delimLen
90
91 collectorNames = dict(zip(map(lambda x: x.id, collectors), collectors))
92 for name in sorted(collectorNames.keys()):
93 collector = collectorNames[name]
94 print "%s %s %s" % (name, collector.stdout, collector.stderr)
95 print '-' * delimLen
96
98 def killTimedOutProc(signum, frame):
99 log.error("Killing process id %s ...", proc.pid)
100 try:
101 os.kill(proc.pid, signal.SIGKILL)
102 except OSError:
103 pass
104
105 if collector.id == 'localhost' or not self.options.useprefix:
106 remote_command = self.args[0]
107 else:
108 remote_command = '%s_%s' % (collector.id, self.args[0])
109
110 if collector.hostname == 'localhost':
111 collectorCommand = [remote_command]
112 else:
113 collectorCommand = ['ssh', collector.hostname, remote_command]
114
115 collectorCommand = ' '.join(collectorCommand)
116 log.debug("Runing command '%s' on collector %s (%s)",
117 collectorCommand, collector.id, collector.hostname)
118 proc = Popen(collectorCommand, stdout=PIPE, stderr=PIPE, shell=True)
119 signal.signal(signal.SIGALRM, killTimedOutProc)
120 signal.alarm(self.options.timeout)
121 collector.stdout, collector.stderr = proc.communicate()
122 proc.wait()
123 signal.alarm(0)
124
125
126 if __name__ == '__main__':
127 zrc = RunCommand()
128 zrc.run()
129