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

Source Code for Module Products.ZenModel.zendmd

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