Package Products :: Package ZenModel :: Module zendmd
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenModel.zendmd

  1  #!/usr/bin/env python 
  2  ########################################################################### 
  3  # 
  4  # This program is part of Zenoss Core, an open source monitoring platform. 
  5  # Copyright (C) 2007, Zenoss Inc. 
  6  # 
  7  # This program is free software; you can redistribute it and/or modify it 
  8  # under the terms of the GNU General Public License version 2 or (at your 
  9  # option) any later version as published by the Free Software Foundation. 
 10  # 
 11  # For complete information please visit: http://www.zenoss.com/oss/ 
 12  # 
 13  ########################################################################### 
 14   
 15  import sys 
 16  import os 
 17  import os.path 
 18  import code 
 19  import atexit 
 20  import logging 
 21  from subprocess import Popen, PIPE 
 22  from optparse import OptionParser 
 23   
 24   
 25  # Parse the command line for host and port; have to do it before Zope 
 26  # configuration, because it hijacks option parsing. 
 27   
 28   
 29  parser = OptionParser(usage='usage: %prog [options] -- [ipthon_options] [ipython_args]') 
 30  parser.add_option('--host', 
 31              dest="host", default=None, 
 32              help="Hostname of ZEO server") 
 33  parser.add_option('--port', 
 34              dest="port", type="int", default=None, 
 35              help="Port of ZEO server") 
 36  parser.add_option('--script', 
 37              dest="script", default=None, 
 38              help="Name of file to execute.") 
 39  parser.add_option('--commit', 
 40              dest="commit", default=False, action="store_true", 
 41              help="Run commit() at end of script?") 
 42  parser.add_option('-n', '--no-ipython',  
 43              dest="use_ipython", default=True, action="store_false",  
 44              help="Do not embed IPython shell if IPython is found") 
 45   
 46  opts, args = parser.parse_args() 
 47   
 48  readline = rlcompleter = None 
 49  Completer = object 
 50  IPShellEmbed = None 
 51   
 52  if opts.use_ipython:     
 53      try: 
 54          import readline 
 55       
 56          try: 
 57              from IPython.Shell import IPShellEmbed 
 58          except ImportError: 
 59              IPShellEmbed = None 
 60          except AttributeError: 
 61              # Looks like we have IPython but the wrong version of readline, likely on OSX 10.6 
 62              IPShellEmbed = None 
 63          from rlcompleter import Completer 
 64      except ImportError: 
 65          pass 
 66   
 67  # Zope magic ensues! 
 68  import Zope2 
 69  CONF_FILE = os.path.join(os.environ['ZENHOME'], 'etc', 'zope.conf') 
 70  Zope2.configure(CONF_FILE) 
 71   
 72  # Now we have the right paths, so we can do the rest of the imports 
 73  from Products.CMFCore.utils import getToolByName 
 74  from AccessControl.SecurityManagement import newSecurityManager 
 75  from AccessControl.SecurityManagement import noSecurityManager 
 76  from Products.ZenUtils.Utils import zenPath, set_context 
 77  from Products.ZenModel.IpNetwork import IpNetworkPrinterFactory 
 78   
 79  _CUSTOMSTUFF = [] 
 80   
 81   
82 -def set_db_config(host=None, port=None):
83 # Modify the database configuration manually 84 from App.config import getConfiguration 85 serverconfig = getConfiguration().databases[1].config.storage.config 86 xhost, xport = serverconfig.server[0].address 87 if host: xhost = host 88 if port: xport = port 89 serverconfig.server[0].address = (xhost, xport)
90 91
92 -def _customStuff():
93 """ 94 Everything available in the console is defined here. 95 """ 96 97 import socket 98 from transaction import commit 99 from pprint import pprint 100 from Products.Zuul import getFacade, listFacades 101 102 # Connect to the database, set everything up 103 app = Zope2.app() 104 app = set_context(app) 105 106 def login(username='admin'): 107 utool = getToolByName(app, 'acl_users') 108 user = utool.getUserById(username) 109 if user is None: 110 user = app.zport.acl_users.getUserById(username) 111 user = user.__of__(utool) 112 newSecurityManager(None, user) 113 from AccessControl.Implementation import setImplementation
114 #Chip's pitched battle against segfault. 115 #import pdb;pdb.set_trace() 116 #setImplementation('PYTHON') 117 118 login('admin') 119 120 # Useful references 121 zport = app.zport 122 dmd = zport.dmd 123 sync = zport._p_jar.sync 124 find = dmd.Devices.findDevice 125 devices = dmd.Devices 126 me = find(socket.getfqdn()) 127 shell_stdout = [] 128 shell_stderr = [] 129 130 def reindex(): 131 sync() 132 dmd.Devices.reIndex() 133 dmd.Events.reIndex() 134 dmd.Manufacturers.reIndex() 135 dmd.Networks.reIndex() 136 commit() 137 138 def logout(): 139 noSecurityManager() 140 141 def zhelp(): 142 cmds = filter(lambda x: not x.startswith("_"), _CUSTOMSTUFF) 143 cmds.sort() 144 for cmd in cmds: print cmd 145 146 def grepdir(obj, regex=""): 147 if regex: 148 import re 149 pattern = re.compile(regex) 150 for key in dir(obj): 151 if pattern.search(key): 152 print key 153 154 def lookupGuid(guid): 155 """ 156 Given a guid this returns the object that it identifies 157 """ 158 from Products.ZenUtils.guid.interfaces import IGUIDManager 159 manager = IGUIDManager(dmd) 160 return manager.getObject(guid) 161 162 def version(): 163 for info in zport.About.getAllVersions(): 164 print "%10s: %s" % (info['header'], info['data']) 165 print "%10s: %s" % ("DMD", dmd.version) 166 167 def printNets(net=dmd.Networks, format="text", out=sys.stdout): 168 """ 169 Print out the IpNetwork and IpAddress hierarchy under net. To print 170 out everything call printNets(dmd.Networks). format can be text, 171 python, or xml. 172 """ 173 factory = IpNetworkPrinterFactory() 174 printer = factory.createIpNetworkPrinter(format, out) 175 printer.printIpNetwork(net) 176 177 178 def cleandir(obj): 179 portaldir = set(dir(dmd)) 180 objdir = set(dir(obj)) 181 appdir = set(dir(app)) 182 result = list(objdir - portaldir - appdir) 183 result.sort() 184 pprint(result) 185 186 def history(start=None, end=None, lines=30, 187 number=False): 188 """ 189 Display the history starting from entry 'start' to 190 entry 'end'. Only available on platforms where the 191 readline module can be imported. 192 193 History starts from 0 and goes to a large number. 194 The history file is $ZENHOME/.pyhistory by default. 195 196 @parameter start: Line number to start printing 197 @type start: integer 198 @parameter end: Line number to finish printing 199 @type end: integer 200 @parameter lines: number of lines to show if no end 201 @type lines: integer 202 @parameter number: show the line numbers? 203 @type number: boolean 204 """ 205 if readline is not None: 206 maxHistLength = readline.get_current_history_length() 207 if start is None: 208 start = maxHistLength 209 if end is None: 210 end = maxHistLength - lines 211 if start < end: 212 end, start = start, end 213 for i in range(end, start): 214 if number: 215 print i, readline.get_history_item(i) 216 else: 217 print readline.get_history_item(i) 218 219 def setLogLevel(level=10): 220 """ 221 Change the logging level to allow for more insight into the 222 in-flight mechanics of Zenoss. 223 224 @parameter level: logging level at which messages display (eg logging.INFO) 225 @type level: integer 226 """ 227 log = logging.getLogger() 228 log.setLevel(level) 229 for handler in log.handlers: 230 if isinstance(handler, logging.StreamHandler): 231 handler.setLevel(level) 232 233 def sh(cmd, interactive=True): 234 """ 235 Execute a shell command. If interactive is False, then 236 direct the contents of stdout into shell_stdout and the 237 output of stderr into shell_stderr. 238 239 @parameter cmd: shell command to execute 240 @type cmd: string 241 @parameter interactive: show outut to the screen or not 242 @type interactive: boolean 243 """ 244 if interactive: 245 proc = Popen(cmd, shell=True) 246 else: 247 proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True) 248 output, errors = proc.communicate() 249 proc.wait() 250 if not interactive: 251 output = output.split('\n')[:-1] 252 errors = errors.split('\n')[:-1] 253 _CUSTOMSTUFF['shell_stdout'] = output 254 _CUSTOMSTUFF['shell_stderr'] = errors 255 return output, errors 256 257 def edit(file=None, start=None, end=None, lines=30): 258 """ 259 Use the value of the EDITOR environment variable to 260 edit a file. Defaults to the original Unix IDE -- vi. 261 262 @parameter file: name of file to edit -- defaults to a temp file 263 @type file: string 264 @parameter start: Line number to start printing 265 @type start: integer 266 @parameter end: Line number to finish printing 267 @type end: integer 268 @parameter lines: number of lines to show if no end 269 @type lines: integer 270 """ 271 editor = os.environ.get('EDITOR', 'vi') 272 isNewFile = True 273 isTmpName = False 274 if file == None: 275 isTmpName = True 276 file = os.tempnam() 277 fp = open(file, 'w') 278 elif os.path.exists(file): 279 isNewFile = False 280 else: 281 fp = open(file, 'w') 282 283 if isNewFile and readline is not None: 284 maxHistLength = readline.get_current_history_length() 285 if start is None: 286 start = maxHistLength 287 if end is None: 288 end = maxHistLength - lines 289 if start < end: 290 end, start = start, end 291 for i in range(end, start): 292 fp.write(readline.get_history_item(i) + '\n') 293 fp.close() 294 295 sh('%s %s' % (editor, file)) 296 execfile(file, globals(), _CUSTOMSTUFF) 297 if isTmpName: 298 os.unlink(file) 299 300 _CUSTOMSTUFF = locals() 301 return _CUSTOMSTUFF 302 303
304 -class ZenCompleter(Completer):
305 """ 306 Provides the abiility to specify *just* the zendmd-specific 307 stuff when you first enter and hit tab-tab, and also the 308 ability to remove junk that we don't need to see. 309 """ 310 ignored_names = [ 311 "COPY", "DELETE", "HEAD", "HistoricalRevisions", 312 "LOCK", "MKCOL", "MOVE", "OPTIONS", 313 "Open", "PROPFIND", "PROPPATCH", 314 "PUT", "REQUEST", "SQLConnectionIDs", 315 "SiteRootAdd", "TRACE", "UNLOCK", 316 "ac_inherited_permissions", 317 "access_debug_info", 318 "bobobase_modification_time", 319 "manage_historyCompare", 320 "manage_historyCopy", 321 "manage_addDTMLDocument", 322 "manage_addDTMLMethod", 323 "manage_clone", 324 "manage_copyObjects", 325 "manage_copyright", 326 "manage_cutObjects", 327 "manage_historicalComparison", 328 "validClipData", 329 "manage_CopyContainerAllItems", 330 "manage_CopyContainerFirstItem", 331 "manage_DAVget", 332 "manage_FTPlist", 333 "manage_UndoForm", 334 "manage_access", 335 ] 336 ignored_prefixes = [ 337 '_', 'wl_', 'cb_', 'acl', 'http__', 'dav_', 338 'manage_before', 'manage_after', 339 'manage_acquired', 340 ] 341 342 current_prompt = ''
343 - def complete(self, text, state):
344 # Don't show all objects if we're typing in code 345 if self.current_prompt == sys.ps2: 346 if state == 0: 347 if text == '': 348 return ' ' 349 else: 350 return None 351 352 return Completer.complete(self, text, state)
353 354
355 - def global_matches(self, text):
356 """ 357 Compute matches when text is a simple name. 358 """ 359 matches = [] 360 for name in self.namespace: 361 if name.startswith(text): 362 matches.append(name) 363 364 return matches
365
366 - def attr_matches(self, text):
367 """ 368 Compute matches when text contains a dot. 369 """ 370 matches = [] 371 for name in Completer.attr_matches(self, text): 372 if name.endswith("__roles__"): 373 continue 374 component = name.split('.')[-1] 375 if component in self.ignored_names: 376 continue 377 ignore = False 378 for prefix in self.ignored_prefixes: 379 if component.startswith(prefix): 380 ignore = True 381 break 382 383 if not ignore: 384 matches.append(name) 385 386 return matches
387 #return filter(lambda x: not x.endswith("__roles__"), 388 #Completer.attr_matches(self, text)) 389 390 391
392 -class HistoryConsole(code.InteractiveConsole):
393 """ 394 Subclass the default InteractiveConsole to get readline history 395 """
396 - def __init__(self, locals=None, filename="<console>", 397 histfile=zenPath('.pyhistory')):
398 code.InteractiveConsole.__init__(self, locals, filename) 399 self.completer = None 400 if readline is not None: 401 self.completer = ZenCompleter(locals) 402 readline.set_completer(self.completer.complete) 403 readline.parse_and_bind("tab: complete") 404 self.init_history(histfile)
405 406
407 - def init_history(self, histfile):
408 if hasattr(readline, "read_history_file"): 409 try: 410 readline.read_history_file(histfile) 411 except IOError: 412 pass 413 atexit.register(self.save_history, histfile)
414
415 - def save_history(self, histfile):
416 readline.write_history_file(histfile)
417
418 - def raw_input(self, prompt=""):
419 if self.completer: 420 self.completer.current_prompt = prompt 421 return code.InteractiveConsole.raw_input(self, prompt)
422
423 - def runsource(self, source, filename):
424 if source and source[0] == '!': 425 self.locals['sh'](source[1:]) 426 return False 427 elif source and source[0] == '|': 428 self.locals['sh'](source[1:], interactive=False) 429 return False 430 return code.InteractiveConsole.runsource(self, source, filename)
431 432 433 if __name__=="__main__": 434 # Do we want to connect to a database other than the one specified in 435 # zope.conf? 436 if opts.host or opts.port: 437 set_db_config(opts.host, opts.port) 438 439 vars = _customStuff() 440 if opts.script: 441 if not os.path.exists(opts.script): 442 print "Unable to open script file '%s' -- exiting" % opts.script 443 sys.exit(1) 444 execfile(opts.script, globals(), vars) 445 if opts.commit: 446 from transaction import commit 447 commit() 448 sys.exit(0) 449 450 _banner = ("Welcome to the Zenoss dmd command shell!\n" 451 "'dmd' is bound to the DataRoot. 'zhelp()' to get a list of " 452 "commands.") 453 454 if IPShellEmbed: 455 sys.argv[1:] = args 456 ipshell = IPShellEmbed(banner=_banner) 457 ipshell(local_ns=vars) 458 else: 459 if readline is not None: 460 _banner = '\n'.join( [ _banner, 461 "Use TAB-TAB to see a list of zendmd related commands.", 462 "Tab completion also works for objects -- hit tab after" 463 " an object name and '.'", " (eg dmd. + tab-key)."]) 464 465 466 # Start up the console 467 myconsole = HistoryConsole(locals=vars) 468 myconsole.interact(_banner) 469