221 lines
6.9 KiB
Python
221 lines
6.9 KiB
Python
#!/usr/bin/env python
|
|
|
|
import bcrypt
|
|
import json
|
|
from kazoo.client import KazooClient
|
|
from kazoo.recipe.watchers import DataWatch
|
|
import logging
|
|
import requests
|
|
import sqlite3
|
|
import tornado.escape
|
|
import tornado.ioloop
|
|
import tornado.options
|
|
import tornado.web
|
|
import tornado.websocket
|
|
import threading
|
|
import os.path
|
|
import uuid
|
|
|
|
from tornado.options import define, options
|
|
|
|
define("port", default=8000, help="run on the given port", type=int)
|
|
define("sqlite_db", default=os.path.join(os.path.dirname(__file__), "auth.db"), help="User DB")
|
|
|
|
class Application(tornado.web.Application):
|
|
def __init__(self):
|
|
handlers = [
|
|
(r"/", MainHandler),
|
|
(r"/socket", SocketHandler),
|
|
(r"/mount", MountHandler),
|
|
(r"/unmount", UnmountHandler),
|
|
(r"/resolve", ResolveHandler),
|
|
(r"/status", StatusHandler),
|
|
(r"/login", Auth),
|
|
]
|
|
settings = dict(
|
|
cookie_secret="=&r854^9nk7ys49@m7a5eu(g&jn8pytk6f%@quumabt*x5e*)i",
|
|
template_path=os.path.join(os.path.dirname(__file__), "templates/rbmd"),
|
|
static_path=os.path.join(os.path.dirname(__file__), "static/rbmd"),
|
|
xsrf_cookies=True,
|
|
websocket_ping_interval = 59,
|
|
login_url="/login",
|
|
)
|
|
super(Application, self).__init__(handlers, **settings)
|
|
|
|
|
|
class MainHandler(tornado.web.RequestHandler):
|
|
@tornado.web.authenticated
|
|
def get(self):
|
|
user_id = self.get_secure_cookie("user")
|
|
try: metrics = json.loads(action('metrics', 'get'))
|
|
except ValueError: metrics = {}
|
|
dct = {'metrics': metrics}
|
|
self.render("index.html", **dct)
|
|
|
|
def get_current_user(self):
|
|
return self.get_secure_cookie("user")
|
|
|
|
|
|
class Auth(tornado.web.RequestHandler):
|
|
def get(self):
|
|
self.render("login.html", error=None)
|
|
|
|
def post(self):
|
|
con = sqlite3.connect(options.sqlite_db)
|
|
cur = con.cursor()
|
|
cur.execute("SELECT * FROM users WHERE name = :name", {"name": self.get_argument("username")})
|
|
#cur.execute("SELECT * FROM users WHERE name = ?", (self.get_argument("username"),))
|
|
user = cur.fetchone()
|
|
cur.close()
|
|
con.close()
|
|
if not user:
|
|
self.render("login.html", error="user not found")
|
|
return
|
|
hashed_password = bcrypt.hashpw(tornado.escape.utf8(self.get_argument("password")), tornado.escape.utf8(user[2]))
|
|
if hashed_password == user[2]:
|
|
self.set_secure_cookie("user", str(user[0]))
|
|
self.redirect("/")
|
|
else:
|
|
self.render("login.html", error="incorrect password")
|
|
|
|
########### not used ##########################
|
|
#create new user /user?name=user_name&password=user_password
|
|
class User(tornado.web.RequestHandler):
|
|
def get(self):
|
|
con = sqlite3.connect(options.sqlite_db)
|
|
cur = con.cursor()
|
|
data = self.request.arguments
|
|
hashed_password = bcrypt.hashpw(tornado.escape.utf8(self.get_argument("password")), bcrypt.gensalt())
|
|
cur.execute(
|
|
"INSERT INTO users (name, password) VALUES (?, ?)",
|
|
(self.get_argument("name"), hashed_password)
|
|
)
|
|
con.commit()
|
|
if hashed_password == bcrypt.hashpw(tornado.escape.utf8(self.get_argument("password")), hashed_password):
|
|
logging.info('OK')
|
|
cur.close()
|
|
con.close()
|
|
self.write('done')
|
|
|
|
|
|
class MountHandler(tornado.web.RequestHandler):
|
|
def post(self):
|
|
if self.get_secure_cookie("user"):
|
|
data = {k: v[0] for k, v in self.request.arguments.items()}
|
|
res = action('mount', 'post', json.dumps(data))
|
|
self.write(res)
|
|
|
|
|
|
class UnmountHandler(tornado.web.RequestHandler):
|
|
def get(self):
|
|
#data = self.request.arguments
|
|
data = {k: v[0] for k, v in self.request.arguments.items()}
|
|
res = action('umount', 'post', json.dumps(data))
|
|
self.write(res)
|
|
|
|
|
|
class ResolveHandler(tornado.web.RequestHandler):
|
|
#my_status = action('status', 'get')
|
|
def get(self):
|
|
#data = self.request.arguments
|
|
data = {k: v[0] for k, v in self.request.arguments.items()}
|
|
res = action('resolve', 'post', json.dumps(data))
|
|
self.write(res)
|
|
|
|
class StatusHandler(tornado.web.RequestHandler):
|
|
pass
|
|
|
|
class SocketHandler(tornado.websocket.WebSocketHandler):
|
|
waiters = set()
|
|
quorum = json.dumps(dict())
|
|
|
|
def get_compression_options(self):
|
|
# Non-None enables compression with default options.
|
|
return {}
|
|
|
|
def check_origin(self, origin):
|
|
return True
|
|
|
|
def open(self):
|
|
SocketHandler.waiters.add(self)
|
|
SocketHandler.send_updates(SocketHandler.quorum)
|
|
|
|
def on_close(self):
|
|
SocketHandler.waiters.remove(self)
|
|
|
|
@classmethod
|
|
def send_updates(cls, data, *stat):
|
|
#SocketHandler.quorum = data
|
|
if data == '{}':
|
|
my_data = json.loads(data)
|
|
my_data["health"] = 'service is not available'
|
|
my_data["quorum"] = [{"node":""}]
|
|
data = json.dumps(my_data)
|
|
#if json.loads(data)["health"] == "deadly.":
|
|
if json.loads(data).get("health") == "deadly.":
|
|
dead_data = action('status', 'get')
|
|
my_data = json.loads(data)
|
|
my_data["deadlyreason"] = json.loads(dead_data)["deadlyreason"]
|
|
data = json.dumps(my_data)
|
|
SocketHandler.quorum = data
|
|
logging.info('send_upd')
|
|
|
|
for waiter in cls.waiters:
|
|
try:
|
|
waiter.write_message(SocketHandler.quorum)
|
|
except:
|
|
logging.error("Error sending message", exc_info=True)
|
|
|
|
def on_message(self, message): pass
|
|
# logging.info(message)
|
|
|
|
def config(point):
|
|
with open('conf.json') as conf:
|
|
path = json.load(conf)[point]
|
|
return path
|
|
|
|
def action(name, method, data=None):
|
|
with open('conf.json') as conf:
|
|
url = json.load(conf)["api"] + '/' + name
|
|
if method == 'get':
|
|
try:
|
|
res = requests.get(url).content
|
|
except:
|
|
res = 'connection can\'t be established'
|
|
elif method == 'post':
|
|
try:
|
|
res = requests.post(url, data, timeout=10).content
|
|
except:
|
|
res = 'connection can\'t be established'
|
|
return res
|
|
|
|
|
|
def zk_handler():
|
|
logging.basicConfig()
|
|
zk = KazooClient(hosts=config("zookeeper"))
|
|
try: zk.start()
|
|
except: return '{"health": "connection cant be established"}'
|
|
t1 = threading.Thread(target=DataWatch, args=(zk, "/rbmd/log/quorum"), kwargs=dict(func=SocketHandler.send_updates))
|
|
t1.setDaemon(True)
|
|
t1.start()
|
|
|
|
|
|
########### not used ##########################
|
|
#def zk_fetch(path):
|
|
# zk = KazooClient(hosts=config("zookeeper"))
|
|
# zk.start()
|
|
# data = zk.get(path)
|
|
# zk.stop()
|
|
|
|
|
|
def main():
|
|
tornado.options.parse_command_line()
|
|
zk_handler()
|
|
app = Application()
|
|
app.listen(options.port)
|
|
tornado.ioloop.IOLoop.current().start()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|