Package Products :: Package ZenUtils :: Module RunCommand
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenUtils.RunCommand

  1  #!/usr/bin/env python 
  2  ############################################################################# 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2010, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 or (at your 
  8  # option) any later version as published by the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  ############################################################################# 
 12   
 13  __doc__ = """RunCommand 
 14  Run an event command on the local device or on the remote collector. 
 15  Assumes that SSH keys have been set up to all remote collectors. 
 16   
 17    Example usage: 
 18   
 19  dcsh -collector=xxx 'zencommand run' 
 20   
 21    The actual command to run *MUST* be in quotes! 
 22  """ 
 23   
 24  import logging 
 25  log = logging.getLogger('zen.runCommand') 
 26   
 27  import os 
 28  from subprocess import Popen, PIPE 
 29  import StringIO 
 30  import signal 
 31   
 32  import Globals 
 33  from Products.ZenUtils.ZenScriptBase import ZenScriptBase 
 34  from Products.ZenUtils.Utils import zenPath 
 35   
 36   
37 -class collectorStats:
38 - def __init__(self, id, hostname):
39 self.id = id 40 self.hostname = hostname 41 self.succeeded = False 42 self.stdout = '' 43 self.stderr = ''
44 45
46 -class RunCommand(ZenScriptBase):
47 - def __init__(self):
48 ZenScriptBase.__init__(self, connect=True)
49
50 - def buildOptions(self):
51 ZenScriptBase.buildOptions(self) 52 self.parser.add_option('--collector', dest='collector', 53 help="Name of specific collector on which to run the command") 54 self.parser.add_option('--timeout', dest='timeout', 55 default=60, type="int", 56 help="Kill the process after this many seconds.") 57 self.parser.add_option('-n', '--useprefix', action='store_false', 58 dest='useprefix', default=True, 59 help="Prefix the collector name for remote servers")
60
61 - def run(self):
62 collectors = self._getCollectors() 63 if collectors is None: 64 return 65 for collector in collectors: 66 self._runCommandOnCollector(collector) 67 self.report(collectors)
68
69 - def _getCollectors(self):
70 if self.options.collector: 71 try: 72 collectors = [self.dmd.Monitors.Performance._getOb( 73 self.options.collector)] 74 except AttributeError: 75 log.critical("No collector named %s could be found. Exiting", 76 self.options.collector) 77 return 78 else: 79 collectors = self.dmd.Monitors.Performance.objectValues( 80 spec="PerformanceConf") 81 82 return [collectorStats(x.id, getattr(x, 'hostname', x.id)) \ 83 for x in collectors]
84
85 - def report(self, collectors):
86 header = """ 87 Collector StdOut/Stderr""" 88 delimLen = 65 89 print header 90 print '-' * delimLen 91 92 collectorNames = dict(zip(map(lambda x: x.id, collectors), collectors)) 93 for name in sorted(collectorNames.keys()): 94 collector = collectorNames[name] 95 print "%s %s %s" % (name, collector.stdout, collector.stderr) 96 print '-' * delimLen
97
98 - def _runCommandOnCollector(self, collector):
99 def killTimedOutProc(signum, frame): 100 log.error("Killing process id %s ...", proc.pid) 101 try: 102 os.kill(proc.pid, signal.SIGKILL) 103 except OSError: 104 pass
105 106 if collector.hostname == 'localhost': 107 collectorCommand = self.args 108 else: 109 # Quick check to see if we can SSH to the collector. 110 #p1 = Popen(["echo", "0"], stdout=PIPE) 111 #p2 = Popen(["nc", "-w", "4", collector.hostname, "22"], 112 # stdin=p1.stdout, stdout=PIPE, stderr=PIPE) 113 114 #if os.waitpid(p2.pid, 0)[1] != 0: 115 # log.warn("Unable to SSH to collector %s (%s)", 116 # collector.id, collector.hostname) 117 # return 118 119 cmd = self.args[0] 120 if self.options.useprefix: 121 cmd = '%s_%s' % (collector.id, cmd) 122 collectorCommand = ['ssh', collector.hostname, cmd] 123 124 collectorCommand = ' '.join(collectorCommand) 125 log.debug("Runing command '%s' on collector %s (%s)", 126 collectorCommand, collector.id, collector.hostname) 127 proc = Popen(collectorCommand, stdout=PIPE, stderr=PIPE, shell=True) 128 signal.signal(signal.SIGALRM, killTimedOutProc) 129 signal.alarm(self.options.timeout) 130 collector.stdout, collector.stderr = proc.communicate() 131 proc.wait() 132 signal.alarm(0) # Disable the alarm
133 134 135 if __name__ == '__main__': 136 zrc = RunCommand() 137 zrc.run() 138