1
2
3
4
5
6
7
8
9
10
11
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
26
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
62 IPShellEmbed = None
63 from rlcompleter import Completer
64 except ImportError:
65 pass
66
67
68 import Zope2
69 CONF_FILE = os.path.join(os.environ['ZENHOME'], 'etc', 'zope.conf')
70 Zope2.configure(CONF_FILE)
71
72
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
83
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
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
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
115
116
117
118 login('admin')
119
120
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
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 = ''
353
354
365
387
388
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
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
435
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
467 myconsole = HistoryConsole(locals=vars)
468 myconsole.interact(_banner)
469