diff --git a/confluent_client/bin/nodeconsole b/confluent_client/bin/nodeconsole index 3b5afa51..f90127fc 100755 --- a/confluent_client/bin/nodeconsole +++ b/confluent_client/bin/nodeconsole @@ -58,7 +58,14 @@ argparser.add_option('-w','--windowed', action='store_true', default=False, '--shell-type login". If the NODECONSOLE_WINDOWED_COMMAND ' 'environment variable isn\'t set, xterm will be used by' 'default.') + (options, args) = argparser.parse_args() + +pass_through_args = [] +if len(args) > 1: + pass_through_args = args[1:] + args = args[:1] + if len(args) != 1: argparser.print_help() sys.exit(1) @@ -71,14 +78,59 @@ if options.log: sys.exit(1) logreader.replay_to_console(logname) sys.exit(0) -#added functionality for wcons + +def handle_geometry(envlist, sizegeometry, side_pad=0, top_pad=0, first=False): + if '-geometry' in envlist: + g_index = envlist.index('-geometry') + elif '-g' in envlist: + g_index = envlist.index('-g') + else: + g_index = 0 + if g_index: + if first: + envlist[g_index+1] = '{0}+{1}+{2}'.format(envlist[g_index+1],side_pad, top_pad) + else: + envlist[g_index+1] = '{0}+{1}+{2}'.format(sizegeometry,side_pad, top_pad) + else: + envlist.insert(1, '-geometry') + envlist.insert(2, '{0}+{1}+{2}'.format(sizegeometry,side_pad, top_pad)) + g_index = 1 + return envlist + +#added functionality for wcons if options.windowed: + result=subprocess.Popen(['xwininfo', '-root'], stdout=subprocess.PIPE) + rootinfo=result.communicate()[0] + result.wait() + for line in rootinfo.decode('utf-8').split('\n'): + if 'Width' in line: + screenwidth = int(line.split(':')[1]) + if 'Height' in line: + screenheight = int(line.split(':')[1]) + envstring=os.environ.get('NODECONSOLE_WINDOWED_COMMAND') if not envstring: - envlist=["xterm", "-e"] + sizegeometry='100x31' + corrected_x, corrected_y = (13,84) + envlist = handle_geometry(['xterm'] + pass_through_args + ['-e'],sizegeometry, first=True) else: envlist=os.environ.get('NODECONSOLE_WINDOWED_COMMAND').split(' ') + if envlist[0] == 'xterm': + if '-geometry' in envlist: + g_index = envlist.index('-geometry') + elif '-g' in envlist: + g_index = envlist.index('-g') + else: + g_index = 0 + if g_index: + envlist[g_index+1] = envlist[g_index+1] + '+0+0' + + else: + envlist.insert(1, '-geometry') + envlist.insert(2, '100x31+0+0') + g_index = 1 + nodes = [] sess = client.Command() for res in sess.read('/noderange/{0}/nodes/'.format(args[0])): @@ -87,9 +139,87 @@ if options.windowed: sys.stderr.write(res.get('error', repr(res)) + '\n') sys.exit(1) nodes.append(node) + + if options.tile and not envlist[0] == 'xterm': + sys.stderr.write('[ERROR] UNSUPPORTED OPTIONS. \nWindowed and tiled consoles are only supported when using xterm \n') + sys.exit(1) + firstnode=nodes[0] + nodes.pop(0) + with open(os.devnull, 'wb') as devnull: + xopen=subprocess.Popen(envlist + [confettypath, '-c', '/tmp/controlpath-{0}'.format(firstnode), '-m', '5', 'start', '/nodes/{0}/console/session'.format(firstnode) ] , stdin=devnull) + time.sleep(2) + s=socket.socket(socket.AF_UNIX) + winid='' + try: + s.connect('/tmp/controlpath-{firstnode}'.format(firstnode=firstnode)) + s.recv(64) + s.send(b'GETWINID') + winid=s.recv(64).decode('utf-8') + + except: + time.sleep(2) + # try to get id of first panel/xterm window using name + win=subprocess.Popen(['xwininfo', '-tree', '-root'], stdout=subprocess.PIPE) + wintr=win.communicate()[0] + for line in wintr.decode('utf-8').split('\n'): + if 'console: {firstnode}'.format(firstnode=firstnode) in line or 'confetty' in line: + win_obj = [ele for ele in line.split(' ') if ele.strip()] + winid = win_obj[0] + if winid: + firstnode_window=subprocess.Popen(['xwininfo', '-id', '{winid}'.format(winid=winid)], stdout=subprocess.PIPE) + xinfo=firstnode_window.communicate()[0] + xinfl = xinfo.decode('utf-8').split('\n') + for line in xinfl: + if 'Absolute upper-left X:' in line: + side_pad = int(line.split(':')[1]) + elif 'Absolute upper-left Y:' in line: + top_pad = int(line.split(':')[1]) + + elif 'Width:' in line: + window_width = int(line.split(':')[1]) + elif 'Height' in line: + window_height = int(line.split(':')[1]) + elif '-geometry' in line: + l = re.split(' |x|\+', line) + l_nosp = [ele for ele in l if ele.strip()] + wmxo = int(l_nosp[1]) + wmyo = int(l_nosp[2]) + sizegeometry = str(wmxo) + 'x' + str(wmyo) + else: + pass + + window_width += side_pad*2 + window_height += side_pad+top_pad + screenwidth -= wmxo + screenheight -= wmyo + currx = window_width + curry = 0 + maxcol = int(screenwidth/window_width) + for node in sortutil.natural_sort(nodes): + if options.tile and envlist[0] == 'xterm': + corrected_x = currx + corrected_y = curry + xgeometry = '{0}+{1}+{2}'.format(sizegeometry, corrected_x, corrected_y) + currx += window_width + if currx >= screenwidth: + currx=0 + curry += window_height + if curry > screenheight: + curry =top_pad + if not envstring: + envlist= handle_geometry(envlist, sizegeometry, corrected_x, corrected_y) + else: + if g_index: + envlist[g_index+1] = xgeometry + elif envlist[0] == 'xterm': + envlist=handle_geometry(envlist, sizegeometry, side_pad, top_pad) + side_pad+=(side_pad+1) + top_pad+=(top_pad+30) + else: + pass with open(os.devnull, 'wb') as devnull: - subprocess.Popen(envlist + [confettypath, '-m', '5', 'start', '/nodes/{0}/console/session'.format(node)], stdin=devnull) + xopen=subprocess.Popen(envlist + [confettypath, '-m', '5', 'start', '/nodes/{0}/console/session'.format(node)] , stdin=devnull) sys.exit(0) #end of wcons if options.tile: @@ -128,4 +258,4 @@ if options.tile: os.execlp('tmux', 'tmux', 'attach', '-t', sessname) else: os.execl(confettypath, confettypath, 'start', - '/nodes/{0}/console/session'.format(args[0])) + '/nodes/{0}/console/session'.format(args[0])) \ No newline at end of file diff --git a/confluent_client/bin/nodeeventlog b/confluent_client/bin/nodeeventlog index afe2a2fe..680ea400 100755 --- a/confluent_client/bin/nodeeventlog +++ b/confluent_client/bin/nodeeventlog @@ -17,6 +17,7 @@ import codecs from datetime import datetime as dt +from datetime import timedelta import optparse import os import signal @@ -45,7 +46,14 @@ argparser.add_option('-m', '--maxnodes', type='int', argparser.add_option('-l', '--lines', type='int', help='return the last entries ' 'for each node in the eventlog. ' - ) + ) +argparser.add_option('-t', '--timeframe', type='string', + help='return entries within a specified timeframe ' + 'for each node in the eventlog. This will return ' + 'entries from the last hours or days. ' + '1h would be one hour, 4d would be four days. ' + 'format h or d' + ) (options, args) = argparser.parse_args() try: noderange = args[0] @@ -93,13 +101,27 @@ def format_event(evt): msg = '' return ' '.join(retparts) + msg - if deletemode: func = session.delete session.stop_if_noderange_over(noderange, options.maxnodes) else: func = session.read +if options.timeframe: + try: + delta = int(options.timeframe[:-1]) + except ValueError: + argparser.print_help() + sys.exit(1) + if options.timeframe[-1].lower() == 'd': + tdelta = timedelta(days=delta) + elif options.timeframe[-1].lower() == 'h': + tdelta = timedelta(hours=delta) + else: + argparser.print_help() + sys.exit(1) + timeframe = dt.now() - tdelta + event_dict = {} nodes = [] for res in session.read('/noderange/{0}/nodes/'.format(args[0])): @@ -124,7 +146,14 @@ for rsp in func('/noderange/{0}/events/hardware/log'.format(noderange)): event_dict[node].extend(evtdata) else: for evt in evtdata: - print('{0}: {1}'.format(node, format_event(evt))) + if options.timeframe: + # check if line is in timeframe + if 'timestamp' in evt and evt['timestamp'] is not None: + display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S') + if display > timeframe: + print('{0}: {1}'.format(node, format_event(evt))) + else: + print('{0}: {1}'.format(node, format_event(evt))) if options.lines: for node in nodes: @@ -133,5 +162,10 @@ if options.lines: if len(evtdata_list) > options.lines: evtdata_list = evtdata_list[-abs(options.lines):] for evt in evtdata_list: - print('{0}: {1}'.format(node, format_event(evt))) - \ No newline at end of file + if options.timeframe: + if 'timestamp' in evt and evt['timestamp'] is not None: + display = dt.strptime(evt['timestamp'], '%Y-%m-%dT%H:%M:%S') + if display > timeframe: + print('{0}: {1}'.format(node, format_event(evt))) + else: + print('{0}: {1}'.format(node, format_event(evt))) diff --git a/confluent_client/doc/man/nodeeventlog.ronn b/confluent_client/doc/man/nodeeventlog.ronn index 2e76ecf3..c1d5b1b7 100644 --- a/confluent_client/doc/man/nodeeventlog.ronn +++ b/confluent_client/doc/man/nodeeventlog.ronn @@ -18,6 +18,11 @@ noderange. * `-l LINES`, `--lines=LINES`: return the last entries for each node in the eventlog. + +* `-t TIMEFRAME`, `--timeframe=TIMEFRAME`: + return entries within a specified timeframe for each node's event log. + This will return entries from the last hours or days. 1h would be + entries from with the last one hour. * `-h`, `--help`: