2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-28 12:29:40 +00:00

Cleanup the confetty client code

This commit is contained in:
jbjohnso 2014-04-21 10:17:13 -04:00
parent 5e79db5ca4
commit a1ca028029
3 changed files with 76 additions and 57 deletions

View File

@ -35,7 +35,7 @@
# When in a console client mode, will recognize two escape sequences by
# default:
# Ctrl-E, c, ?: mimick conserver behavior
# Ctrl-E, c, ?: mimic conserver behavior
# ctrl-]: go to interactive prompt (telnet escape, but not telnet prompt)
# esc-( would interfere with normal esc use too much
# ~ I will not use for now...
@ -47,8 +47,6 @@ import os
import readline
import select
import shlex
import socket
import ssl
import sys
import termios
import tty
@ -64,13 +62,14 @@ sys.path.append(path)
import confluent.common.tlvdata as tlvdata
import confluent.common.client as client
conserversequence = '\x05c' # ctrl-e, c
conserversequence = '\x05c' # ctrl-e, c
oldtcattr = termios.tcgetattr(sys.stdin.fileno())
server = None
netserver = None
statedata = {}
def updatestatus(stateinfo):
status = consolename
if 'clientcount' in stateinfo:
@ -78,7 +77,8 @@ def updatestatus(stateinfo):
if 'connectstate' in stateinfo:
statedata['connectstate'] = stateinfo['connectstate']
info = []
if 'connectstate' in statedata and statedata['connectstate'] != 'connected':
if ('connectstate' in statedata and
statedata['connectstate'] != 'connected'):
info.append(statedata['connectstate'])
if 'clientcount' in statedata and statedata['clientcount'] != 1:
info.append('clients: %d' % statedata['clientcount'])
@ -117,6 +117,7 @@ valid_commands = [
candidates = None
session = None
def completer(text, state):
try:
return rcompleter(text, state)
@ -124,6 +125,7 @@ def completer(text, state):
import traceback
traceback.print_exc()
def rcompleter(text, state):
global candidates
global valid_commands
@ -137,6 +139,8 @@ def rcompleter(text, state):
currpos += 1
elif currpos:
lastarg = args[-1]
else:
lastarg = ''
if currpos <= 1:
foundcount = 0
for cmd in valid_commands:
@ -178,6 +182,7 @@ def parse_command(command):
currchildren = None
def do_command(command, server):
global exitcode
global target
@ -194,7 +199,7 @@ def do_command(command, server):
otarget = target
if len(argv) > 1:
target = fullpath_target(argv[1], forcepath=True)
else: # cd by itself, go 'home'
else: # cd by itself, go 'home'
target = '/'
for res in session.read(target, server):
if 'errorcode' in res:
@ -236,9 +241,12 @@ def do_command(command, server):
else:
attrstr = '%s=""' % key
if res[key] is not None and 'inheritedfrom' in res[key]:
notes.append('Inherited from %s' % res[key]['inheritedfrom'])
notes.append(
'Inherited from %s' % res[key]['inheritedfrom'])
if res[key] is not None and 'expression' in res[key]:
notes.append('Derived from expression "%s"' % res[key]['expression'])
notes.append(
('Derived from expression "%s"' %
res[key]['expression']))
notestr = '(' + ', '.join(notes) + ')'
output = '{0:<40} {1:>39}'.format(attrstr, notestr)
print(output)
@ -246,7 +254,8 @@ def do_command(command, server):
targpath = fullpath_target(argv[1])
nodename = targpath.split('/')[-3]
currconsole = targpath
tlvdata.send(session.connection, {'operation': 'start', 'path': targpath})
tlvdata.send(
session.connection, {'operation': 'start', 'path': targpath})
status = tlvdata.recv(session.connection)
if 'error' in status:
if 'errorcode' in status:
@ -281,6 +290,7 @@ def createresource(args):
def makecall(callout, args):
global exitcode
for response in callout(*args):
if 'error' in response:
if 'errorcode' in response:
@ -289,6 +299,7 @@ def makecall(callout, args):
def clearvalues(resource, attribs):
global exitcode
targpath = fullpath_target(resource)
keydata = {}
for attrib in attribs:
@ -304,7 +315,9 @@ def delresource(resname):
resname = fullpath_target(resname)
makecall(session.delete, (resname,))
def setvalues(attribs):
global exitcode
if '=' in attribs[0]: # going straight to attribute
resource = attribs[0][:attribs[0].index("=")]
if '/' in resource:
@ -323,6 +336,7 @@ def setvalues(attribs):
exitcode = res['errorcode']
sys.stderr.write('Error: ' + res['error'] + '\n')
def parameterize_attribs(attribs):
keydata = {}
for attrib in attribs:
@ -337,19 +351,19 @@ def parameterize_attribs(attribs):
return keydata
def fullpath_target(path, forcepath=False):
def fullpath_target(currpath, forcepath=False):
global target
if path == '':
if currpath == '':
return target
pathcomponents = path.split("/")
pathcomponents = currpath.split("/")
if pathcomponents[-1] == "": # preserve path
forcepath=True
forcepath = True
if pathcomponents[0] == "": # absolute path
ntarget = path
ntarget = currpath
else:
targparts = target.split("/")[:-1]
for component in pathcomponents:
if component in ('.',''): # ignore these
if component in ('.', ''): # ignore these
continue
elif component == '..':
if len(targparts) > 0:
@ -363,6 +377,7 @@ def fullpath_target(path, forcepath=False):
ntarget += '/'
return ntarget
def startconsole(nodename):
global inconsole
global consolename
@ -372,21 +387,22 @@ def startconsole(nodename):
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl | os.O_NONBLOCK)
inconsole = True
def exit(code=0):
global consoleonly
def quitconfetty(code=0, fullexit=False):
global inconsole
global currconsole
currfl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, currfl ^ os.O_NONBLOCK)
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
if consoleonly:
if fullexit:
sys.exit(code)
else:
tlvdata.send(session.connection, {'operation': 'stop',
'path': currconsole})
inconsole = False
def conserver_command(fh, command):
def conserver_command(filehandle, command):
# x - conserver has that as 'show baud', I am inclined to replace that with
# 'request exclusive'
# b - conserver has that as 'broadcast message', I'm tempted to use that
@ -402,12 +418,12 @@ def conserver_command(fh, command):
# L - toggle logging
# w - who is on console
while not command:
ready, _, _ = select.select((fh,), (), (), 1)
ready, _, _ = select.select((filehandle,), (), (), 1)
if ready:
command += fh.read()
command += filehandle.read()
if command[0] == '.':
print("disconnect]\r")
exit()
quitconfetty(fullexit=consoleonly)
if command[0] == 'b':
tlvdata.send(session.connection, {'operation': 'break',
'path': currconsole})
@ -419,27 +435,29 @@ def conserver_command(fh, command):
print("<cr> abort command\r")
elif command[0] == '\x0d':
print("ignored]\r")
else: #not a command at all..
else: # not a command at all..
print("unknown -- use '?']\r")
def check_escape_seq(input, fh):
while conserversequence.startswith(input):
if input.startswith(conserversequence): # We have full sequence
def check_escape_seq(currinput, filehandle):
while conserversequence.startswith(currinput):
if currinput.startswith(conserversequence): # We have full sequence
sys.stdout.write("[")
sys.stdout.flush()
return conserver_command(fh, input[len(conserversequence):])
ready, _, _ = select.select((fh,), (), (), 3)
return conserver_command(
filehandle, currinput[len(conserversequence):])
ready, _, _ = select.select((filehandle,), (), (), 3)
if not ready: # 3 seconds of no typing
break
input += fh.read()
return input
currinput += filehandle.read()
return currinput
parser = optparse.OptionParser()
parser.add_option("-s", "--server", dest="server",
help="Confluent instance to connect to", metavar="SERVER:PORT")
opts, args = parser.parse_args()
parser.add_option("-s", "--server", dest="netserver",
help="Confluent instance to connect to",
metavar="SERVER:PORT")
opts, shellargs = parser.parse_args()
if opts.server: # going over a TLS network
session = client.Command(opts.server)
else:
@ -464,12 +482,13 @@ readline.set_completer(completer)
doexit = False
inconsole = False
pendingcommand = ""
if len(args) == 1: # a node name, go straight to trying to console
if len(shellargs) == 1: # a node name, go straight to trying to console
consoleonly = True
do_command("start /nodes/%s/console/session" % args[0], server)
do_command("start /nodes/%s/console/session" % shellargs[0], netserver)
while not doexit:
if inconsole:
rdylist, _, _ = select.select((sys.stdin, session.connection), (), (), 60)
rdylist, _, _ = select.select(
(sys.stdin, session.connection), (), (), 60)
for fh in rdylist:
if fh == session.connection:
# this only should get called in the
@ -492,12 +511,11 @@ while not doexit:
sys.stdout.write("\r\n[remote disconnected]\r\n")
break
else:
input = fh.read()
input = check_escape_seq(input, fh)
if input:
tlvdata.send(session.connection, input)
myinput = fh.read()
myinput = check_escape_seq(myinput, fh)
if myinput:
tlvdata.send(session.connection, myinput)
else:
command = prompt()
do_command(command, server)
consoleonly = True
exit()
currcommand = prompt()
do_command(currcommand, netserver)
quitconfetty(fullexit=True)

View File

@ -66,6 +66,7 @@ def sessionhdl(connection, authname, skipauth):
# For now, trying to test the console stuff, so let's just do n4.
authenticated = False
authdata = None
cfm = None
if skipauth:
authenticated = True
cfm = configmanager.ConfigManager(tenant=None)
@ -97,15 +98,15 @@ def sessionhdl(connection, authname, skipauth):
try:
process_request(
connection, request, cfm, authdata, authname, skipauth)
except exc.ForbiddenRequest as e:
except exc.ForbiddenRequest:
tlvdata.send(connection, {'errorcode': 403,
'error': 'Forbidden'})
'error': 'Forbidden'})
tlvdata.send(connection, {'_requestdone': 1})
except:
tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event,
event=log.Events.stacktrace)
event=log.Events.stacktrace)
tlvdata.send(connection, {'errorcode': 500,
'error': 'Unexpected error'})
'error': 'Unexpected error'})
tlvdata.send(connection, {'_requestdone': 1})
request = tlvdata.recv(connection)
@ -174,11 +175,11 @@ def process_request(connection, request, cfm, authdata, authname, skipauth):
hdlr = pluginapi.handle_path(path, operation, cfm, params)
except exc.NotFoundException:
tlvdata.send(connection, {"errorcode": 404,
"error": "Target not found"})
"error": "Target not found"})
tlvdata.send(connection, {"_requestdone": 1})
except exc.InvalidArgumentException:
tlvdata.send(connection, {"errorcode": 400,
"error": "Bad Request"})
"error": "Bad Request"})
tlvdata.send(connection, {"_requestdone": 1})
send_response(hdlr, connection)
return
@ -189,9 +190,9 @@ def _tlshandler():
plainsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
plainsocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
srv = ssl.wrap_socket(plainsocket, keyfile="/etc/confluent/privkey.pem",
certfile="/etc/confluent/srvcert.pem",
ssl_version=ssl.PROTOCOL_TLSv1,
server_side=True)
certfile="/etc/confluent/srvcert.pem",
ssl_version=ssl.PROTOCOL_TLSv1,
server_side=True)
srv.bind(('0.0.0.0', 4001))
srv.listen(5)
authname = None
@ -214,8 +215,8 @@ def _unixdomainhandler():
while True:
cnn, addr = unixsocket.accept()
creds = cnn.getsockopt(socket.SOL_SOCKET, SO_PEERCRED,
struct.calcsize('3i'))
pid, uid, gid = struct.unpack('3i',creds)
struct.calcsize('3i'))
pid, uid, gid = struct.unpack('3i', creds)
skipauth = False
if uid in (os.getuid(), 0):
#this is where we happily accept the person

View File

@ -37,7 +37,7 @@ def securerandomnumber(low=0, high=4294967295):
Note that this function will not return smaller than 0 nor larger
than 2^32-1 no matter what is requested.
The python random number facility does not provide charateristics
The python random number facility does not provide characteristics
appropriate for secure rng, go to os.urandom
:param low: Smallest number to return (defaults to 0)