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  #  
  4  # Copyright (C) Zenoss, Inc. 2010, all rights reserved. 
  5  #  
  6  # This content is made available according to terms specified in 
  7  # License.zenoss under the directory where your Zenoss product is installed. 
  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   
36 -class collectorStats:
37 - def __init__(self, id, hostname):
38 self.id = id 39 self.hostname = hostname 40 self.succeeded = False 41 self.stdout = '' 42 self.stderr = ''
43 44
45 -class RunCommand(ZenScriptBase):
46 - def __init__(self):
47 ZenScriptBase.__init__(self, connect=True)
48
49 - def buildOptions(self):
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
60 - def run(self):
61 collectors = self._getCollectors() 62 if collectors is None: 63 return 64 for collector in collectors: 65 self._runCommandOnCollector(collector) 66 self.report(collectors)
67
68 - def _getCollectors(self):
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
84 - def report(self, collectors):
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
97 - def _runCommandOnCollector(self, collector):
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) # Disable the alarm
124 125 126 if __name__ == '__main__': 127 zrc = RunCommand() 128 zrc.run() 129