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 try:
25 import readline
26
27 try:
28 from IPython.Shell import IPShellEmbed
29 except ImportError:
30 IPShellEmbed = None
31 except AttributeError:
32
33 IPShellEmbed = None
34 from rlcompleter import Completer
35 except ImportError:
36 readline = rlcompleter = None
37 Completer = object
38 IPShellEmbed = None
39
40
41
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
58 import Zope2
59 CONF_FILE = os.path.join(os.environ['ZENHOME'], 'etc', 'zope.conf')
60 Zope2.configure(CONF_FILE)
61
62
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
73
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
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
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
105
106
107
108 login('admin')
109
110
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
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 = ''
335
336
347
369
370
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
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
417
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
448 myconsole = HistoryConsole(locals=vars)
449 myconsole.interact(_banner)
450