2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-01-28 11:57:37 +00:00

Get to the point where it almost starts to work

eventlet spawns the scgi server which is able to create a new console session.
So far, not actually hooked in any way to a backend.
The plan will be to hook up read and write of ConsoleSession instance handle method.

That handle will in turn be hooked into the logging/watching scheme which in turn is
hooked into the likes of pyghmi.ipmi.console and/or ssh execution
This commit is contained in:
Jarrod Johnson 2013-08-09 16:59:08 -04:00
parent ac8e0df051
commit 79259a9c32
3 changed files with 131 additions and 0 deletions

View File

@ -11,6 +11,7 @@
# Things like heartbeating and discovery
# It also will optionally snoop SLP DA requests
import confluent.webapi as webapi
import eventlet
from eventlet.green import socket
from eventlet import wsgi
@ -35,3 +36,8 @@ def _load_plugins():
def run():
_load_plugins()
httpapi = webapi.HttpApi()
httpapi.start()
while (1):
eventlet.sleep(100)

16
confluent/util.py Normal file
View File

@ -0,0 +1,16 @@
# IBM (c) 2013
# Various utility functions that do not neatly fit into one category or another
import base64
import os
def randomstring(length=20):
"""Generate a random string of requested length
:param length: The number of characters to produce, defaults to 20
"""
chunksize = length / 4
if (length % 4 > 0):
chunksize += 1
strval = base64.urlsafe_b64encode(os.urandom(chunksize * 3))
return strval[0:length-1]

109
confluent/webapi.py Normal file
View File

@ -0,0 +1,109 @@
# Copyright (C) IBM 2013
# All rights reserved
# This SCGI server provides a http wrap to confluent api
# It additionally manages httprequest console sessions as supported by
# shillinabox javascript
import base64
import confluent.console as console
import confluent.util as util
import eventlet
import os
import string
scgi = eventlet.import_patched('flup.server.scgi')
consolesessions = {}
def _get_query_dict(qstring):
qdict = {}
if not qstring:
return qdict
for qpair in qstring.split('&'):
qkey, qvalue = qpair.split('=')
qdict[qkey] = qvalue
return qdict
def _authorize_request(env):
"""Grant/Deny access based on data from wsgi env
"""
# TODO(jbjohnso): actually evaluate the request for authorization
# In theory, the x509 or http auth stuff will get translated and then
# passed on to the core authorization function in an appropriate form
# expresses return in the form of http code
# 401 if there is no known identity
# 403 if valid identity, but no access
# going to run 200 just to get going for now
return 200
def _format_response(response):
def _pick_mimetype(env):
"""Detect the http indicated mime to send back.
Note that as it gets into the ACCEPT header honoring, it only looks for
application/json and else gives up and assumes html. This is because
browsers are too terrible. It is assumed that
XMLHttpRequest.setRequestHeader will be used by clever javascript
if the '.json' scheme doesn't cut it.
"""
# TODO(jbjohnso): will this scheme actually play nice with shellinabox?
if env['PATH_INFO'].endswith('.json'):
return 'application/json'
elif env['PATH_INFO'].endswith('.html'):
return 'text/html'
elif 'application/json' in env['HTTP_ACCEPT']:
return 'application/json'
else:
return 'text/html'
def _assign_consessionid(consolesession):
sessid = util.randomstring(20)
while sessid in consolesessions.keys():
sessid = util.randomstring(20)
consolesessions[sessid] = consolesession
return sessid
def resourcehandler(env, start_response):
"""Function to handle new wsgi requests
"""
authorized = _authorize_request(env)
mimetype = _pick_mimetype(env)
print repr(env)
if authorized in (401, 403):
start_response(authorized, [])
return
querydict = _get_query_dict(env['QUERY_STRING'])
if '/console/session' in env['PATH_INFO']:
prefix, _, _ = env['PATH_INFO'].partition('/console/session')
_, _, nodename = prefix.rpartition('/')
if 'session' not in querydict.keys() or not querydict['session']:
# Request for new session
consession = console.ConsoleSession(node=nodename)
if not consession:
start_response("500 Internal Server Error", [])
return
sessid = _assign_consessionid(consession)
start_response('200 OK', [('Content-Type', 'application/json; charset=utf-8')])
return [d+'","data":""}']
start_response('404 Not Found', [])
return []
class HttpApi(object):
def start(self):
# TODO(jbjohnso): move to unix socket and explore
# either making apache deal with it
# or just supporting nginx or lighthttpd
# for now, http port access
self.server = eventlet.spawn(
scgi.WSGIServer(resourcehandler,
bindAddress=("localhost",4004)).run())