docklet/web/web.py

677 lines
21 KiB
Python
Raw Normal View History

2017-05-08 17:01:57 +08:00
#!/usr/bin/python3
import json
import os
import getopt
import sys, inspect
2016-06-06 21:35:28 +08:00
this_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0]))
src_folder = os.path.realpath(os.path.abspath(os.path.join(this_folder,"..", "src")))
if src_folder not in sys.path:
sys.path.insert(0, src_folder)
# must first init loadenv
import tools, env
config = env.getenv("CONFIG")
tools.loadenv(config)
from webViews.log import initlogging
initlogging("docklet-web")
from webViews.log import logger
from flask import Flask, request, session, render_template, redirect, send_from_directory, make_response, url_for, abort
from webViews.dashboard import dashboardView
from webViews.user.userlist import userlistView, useraddView, usermodifyView, userdataView, userqueryView
2016-06-07 16:21:32 +08:00
from webViews.notification.notification import CreateNotificationView, NotificationView, QuerySelfNotificationsView, \
2016-06-07 21:10:43 +08:00
QueryNotificationView, ModifyNotificationView, DeleteNotificationView
from webViews.user.userinfo import userinfoView
from webViews.user.userActivate import userActivateView
from webViews.settings import settingsView
from webViews.user.grouplist import grouplistView, groupqueryView, groupdetailView, groupmodifyView
from functools import wraps
from webViews.dockletrequest import dockletRequest
from webViews.cluster import *
from webViews.admin import *
from webViews.monitor import *
from webViews.beansapplication import *
2017-04-07 16:25:57 +08:00
from webViews.cloud import *
from webViews.authenticate.auth import login_required, administration_required,activated_required
from webViews.authenticate.register import registerView
from webViews.authenticate.login import loginView, logoutView
import webViews.dockletrequest
from webViews import cookie_tool
import traceback
from werkzeug.utils import secure_filename
external_login = env.getenv('EXTERNAL_LOGIN')
#default config
external_login_url = '/external_auth/'
external_login_callback_url = '/external_auth_callback/'
if (external_login == 'True'):
sys.path.insert(0, os.path.realpath(os.path.abspath(os.path.join(this_folder,"../src", "plugin"))))
import external_generate
from webViews.authenticate.login import external_loginView, external_login_callbackView
external_login_url = external_generate.external_login_url
external_login_callback_url = external_generate.external_login_callback_url
app = Flask(__name__)
@app.route("/", methods=['GET'])
def home():
return render_template('home.html')
@app.route("/login/", methods=['GET', 'POST'])
def login():
return loginView.as_view()
@app.route(external_login_url, methods=['GET'])
def external_login_func():
try:
return external_loginView.as_view()
except:
abort(404)
@app.route(external_login_callback_url, methods=['GET'])
def external_login_callback():
try:
return external_login_callbackView.as_view()
except:
abort(404)
@app.route("/logout/", methods=["GET"])
@login_required
def logout():
return logoutView.as_view()
@app.route("/register/", methods=['GET', 'POST'])
@administration_required
#now forbidden,only used by SEI & PKU Staffs and students.
#can be used by admin for testing
def register():
return registerView.as_view()
@app.route("/activate/", methods=['GET', 'POST'])
@login_required
def activate():
return userActivateView.as_view()
@app.route("/dashboard/", methods=['GET'])
@login_required
def dashboard():
return dashboardView.as_view()
@app.route("/document/", methods=['GET'])
def redirect_dochome():
return redirect("http://docklet.unias.org/userguide")
@app.route("/config/", methods=['GET'])
@login_required
def config():
return configView.as_view()
@app.route("/workspace/create/", methods=['GET'])
@activated_required
def addCluster():
return addClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/list/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def listCluster(masterip):
listClusterView.masterip = masterip
return listClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/add/<masterip>/", methods=['POST'])
@login_required
2017-04-07 16:25:57 +08:00
def createCluster(masterip):
createClusterView.clustername = request.form["clusterName"]
createClusterView.image = request.form["image"]
2017-04-07 16:25:57 +08:00
createClusterView.masterip = masterip
return createClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/scaleout/<clustername>/<masterip>/", methods=['POST'])
@login_required
2017-04-07 16:25:57 +08:00
def scaleout(clustername,masterip):
scaleoutView.image = request.form["image"]
2017-04-07 16:25:57 +08:00
scaleoutView.masterip = masterip
scaleoutView.clustername = clustername
return scaleoutView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/scalein/<clustername>/<containername>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def scalein(clustername,containername,masterip):
scaleinView.clustername = clustername
scaleinView.containername = containername
2017-04-07 16:25:57 +08:00
scaleinView.masterip = masterip
return scaleinView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/start/<clustername>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def startClustet(clustername,masterip):
startClusterView.clustername = clustername
2017-04-07 16:25:57 +08:00
startClusterView.masterip = masterip
return startClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/stop/<clustername>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def stopClustet(clustername,masterip):
stopClusterView.clustername = clustername
2017-04-07 16:25:57 +08:00
stopClusterView.masterip = masterip
return stopClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/delete/<clustername>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def deleteClustet(clustername,masterip):
deleteClusterView.clustername = clustername
2017-04-07 16:25:57 +08:00
deleteClusterView.masterip = masterip
return deleteClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/detail/<clustername>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def detailCluster(clustername,masterip):
detailClusterView.clustername = clustername
2017-04-07 16:25:57 +08:00
detailClusterView.masterip = masterip
return detailClusterView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/workspace/flush/<clustername>/<containername>/<masterip>", methods=['GET'])
@login_required
def flushCluster(clustername,containername):
flushClusterView.clustername = clustername
flushClusterView.containername = containername
return flushClusterView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/save/<clustername>/<containername>/<masterip>/", methods=['POST'])
@login_required
2017-04-07 16:25:57 +08:00
def saveImage(clustername,containername,masterip):
saveImageView.clustername = clustername
saveImageView.containername = containername
2017-04-07 16:25:57 +08:00
saveImageView.masterip = masterip
saveImageView.isforce = "false"
saveImageView.imagename = request.form['ImageName']
saveImageView.description = request.form['description']
return saveImageView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/workspace/save/<clustername>/<containername>/force/<masterip>/", methods=['POST'])
@login_required
2017-04-07 16:25:57 +08:00
def saveImage_force(clustername,containername,masterip):
saveImageView.clustername = clustername
saveImageView.containername = containername
2017-04-07 16:25:57 +08:00
saveImageView.masterip = masterip
saveImageView.isforce = "true"
saveImageView.imagename = request.form['ImageName']
saveImageView.description = request.form['description']
return saveImageView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/addproxy/<clustername>/<masterip>/", methods=['POST'])
@login_required
2017-04-09 18:18:12 +08:00
def addproxy(clustername,masterip):
addproxyView.clustername = clustername
2017-04-09 18:18:12 +08:00
addproxyView.masterip = masterip
addproxyView.ip = request.form['proxy_ip']
addproxyView.port = request.form['proxy_port']
return addproxyView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/deleteproxy/<clustername>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def deleteproxy(clustername,masterip):
deleteproxyView.clustername = clustername
2017-04-09 18:18:12 +08:00
deleteproxyView.masterip = masterip
return deleteproxyView.as_view()
@app.route("/getmasterdesc/<mastername>/", methods=['POST'])
@login_required
def getmasterdesc(mastername):
return env.getenv(mastername+"_desc")[1:-1]
@app.route("/masterdesc/<mastername>/", methods=['GET'])
@login_required
def masterdesc(mastername):
descriptionMasterView.desc=env.getenv(mastername+"_desc")[1:-1]
return descriptionMasterView.as_view()
@app.route("/image/list/<masterip>/", methods=['POST'])
@login_required
def image_list(masterip):
data = {
"user": session['username']
}
path = request.path[:request.path.rfind("/")]
path = path[:path.rfind("/")+1]
result = dockletRequest.post(path, data, masterip)
logger.debug("image" + str(type(result)))
return json.dumps(result)
2017-04-07 16:25:57 +08:00
@app.route("/image/description/<image>/<masterip>/", methods=['GET'])
@login_required
2017-04-07 16:25:57 +08:00
def descriptionImage(image,masterip):
descriptionImageView.image = image
2017-04-07 16:25:57 +08:00
descriptionImageView.masterip = masterip
return descriptionImageView.as_view()
2017-04-10 15:21:39 +08:00
@app.route("/image/share/<image>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def shareImage(image,masterip):
shareImageView.image = image
2017-04-09 18:18:12 +08:00
shareImageView.masterip = masterip
return shareImageView.as_view()
2017-04-10 15:21:39 +08:00
@app.route("/image/unshare/<image>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def unshareImage(image,masterip):
unshareImageView.image = image
2017-04-09 18:18:12 +08:00
unshareImageView.masterip = masterip
return unshareImageView.as_view()
2017-04-10 15:21:39 +08:00
@app.route("/image/delete/<image>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def deleteImage(image,masterip):
deleteImageView.image = image
2017-04-09 18:18:12 +08:00
deleteImageView.masterip = masterip
return deleteImageView.as_view()
2017-04-10 15:21:39 +08:00
@app.route("/image/updatebase/<image>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def updatebaseImage(image,masterip):
updatebaseImageView.image = image
2017-04-09 18:18:12 +08:00
updatebaseImageView.masterip = masterip
return updatebaseImageView.as_view()
@app.route("/hosts/", methods=['GET'])
@administration_required
def hosts():
return hostsView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/hosts/<com_ip>/<masterip>/", methods=['GET'])
@administration_required
2017-04-09 18:18:12 +08:00
def hostsRealtime(com_ip,masterip):
hostsRealtimeView.com_ip = com_ip
2017-04-09 18:18:12 +08:00
hostsRealtimeView.masterip = masterip
return hostsRealtimeView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/hosts/<com_ip>/containers/<masterip>/", methods=['GET'])
@administration_required
2017-04-09 18:18:12 +08:00
def hostsConAll(com_ip,masterip):
hostsConAllView.com_ip = com_ip
2017-04-09 18:18:12 +08:00
hostsConAllView.masterip = masterip
return hostsConAllView.as_view()
@app.route("/vclusters/", methods=['GET'])
@login_required
def status():
return statusView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/vclusters/<vcluster_name>/<node_name>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def statusRealtime(vcluster_name,node_name,masterip):
statusRealtimeView.masterip = masterip
statusRealtimeView.node_name = node_name
return statusRealtimeView.as_view()
@app.route("/history/", methods=['GET'])
#@login_required
def history():
2016-07-24 13:51:01 +08:00
return historyView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/history/<vnode_name>/<masterip>/", methods=['GET'])
@login_required
2017-04-09 18:18:12 +08:00
def historyVNode(vnode_name,masterip):
historyVNodeView.masterip = masterip
historyVNodeView.vnode_name = vnode_name
return historyVNodeView.as_view()
2017-04-09 18:18:12 +08:00
@app.route("/monitor/hosts/<comid>/<infotype>/<masterip>/", methods=['POST'])
@app.route("/monitor/vnodes/<comid>/<infotype>/<masterip>/", methods=['POST'])
@login_required
2017-04-09 18:18:12 +08:00
def monitor_request(comid,infotype,masterip):
data = {
"user": session['username']
}
2017-04-09 18:18:12 +08:00
path = request.path[:request.path.rfind("/")]
path = path[:path.rfind("/")+1]
logger.debug(path + "_____" + masterip)
result = dockletRequest.post(path, data, masterip)
logger.debug("monitor" + str(type(result)))
return json.dumps(result)
@app.route("/beans/application/", methods=['GET'])
@login_required
def beansapplication():
return beansapplicationView.as_view()
2016-09-15 18:04:12 +08:00
@app.route("/beans/apply/", methods=['POST'])
@login_required
def beansapply():
return beansapplyView.as_view()
@app.route("/beans/admin/<msgid>/<cmd>/", methods=['GET'])
@login_required
@administration_required
def beansadmin(msgid,cmd):
beansadminView.msgid = msgid
if cmd == "agree" or cmd == "reject":
beansadminView.cmd = cmd
return beansadminView.as_view()
else:
return redirect("/user/list/")
2016-04-25 01:00:06 +08:00
'''@app.route("/monitor/User/", methods=['GET'])
@administration_required
def monitorUserAll():
return monitorUserAllView.as_view()
2016-04-25 01:00:06 +08:00
'''
@app.route("/settings/", methods=['GET', 'POST'])
@administration_required
def settings():
return settingsView.as_view()
@app.route("/logs/<filename>/", methods=['GET'])
@administration_required
def logs_get(filename):
data = {
"filename": filename
}
result = dockletRequest.post('/logs/get/', data).get('result', '')
response = make_response(result)
response.headers["content-type"] = "text/plain"
return response
@app.route("/user/list/", methods=['GET', 'POST'])
@administration_required
def userlist():
return userlistView.as_view()
@app.route("/group/list/", methods=['POST'])
@administration_required
def grouplist():
return grouplistView.as_view()
@app.route("/group/detail/", methods=['POST'])
@administration_required
def groupdetail():
return groupdetailView.as_view()
@app.route("/group/query/", methods=['POST'])
@administration_required
def groupquery():
return groupqueryView.as_view()
@app.route("/group/modify/<groupname>/", methods=['POST'])
@administration_required
def groupmodify(groupname):
return groupmodifyView.as_view()
@app.route("/user/data/", methods=['GET', 'POST'])
@administration_required
def userdata():
return userdataView.as_view()
@app.route("/user/add/", methods=['POST'])
@administration_required
def useradd():
return useraddView.as_view()
@app.route("/user/modify/", methods=['POST'])
@administration_required
def usermodify():
return usermodifyView.as_view()
@app.route("/user/change/", methods=['POST'])
@administration_required
def userchange():
return usermodifyView.as_view()
@app.route("/quota/add/", methods=['POST'])
@administration_required
def quotaadd():
return quotaaddView.as_view()
2016-04-27 16:31:46 +08:00
@app.route("/quota/chdefault/", methods=['POST'])
@administration_required
def chdefault():
return chdefaultView.as_view()
@app.route("/quota/chlxcsetting/", methods=['POST'])
@administration_required
def chlxcsetting():
return chlxcsettingView.as_view()
@app.route("/group/add/", methods=['POST'])
@administration_required
def groupadd():
return groupaddView.as_view()
@app.route("/group/delete/<groupname>/", methods=['POST', 'GET'])
@administration_required
def groupdel(groupname):
groupdelView.groupname = groupname
return groupdelView.as_view()
@app.route("/user/info/", methods=['GET', 'POST'])
@login_required
def userinfo():
return userinfoView.as_view()
@app.route("/user/query/", methods=['GET', 'POST'])
@administration_required
def userquery():
return userqueryView.as_view()
2017-04-07 16:25:57 +08:00
@app.route("/cloud/", methods=['GET', 'POST'])
@administration_required
def cloud():
return cloudView.as_view()
@app.route("/cloud/account/add/", methods = ['POST'])
@administration_required
def cloud_account_add():
return cloudAccountAddView.as_view()
@app.route("/cloud/account/delete/<cloudname>/", methods = ['POST', 'GET'])
@administration_required
def cloud_account_del(cloudname):
cloudAccountDelView.cloudname = cloudname
return cloudAccountDelView.as_view()
@app.route("/cloud/account/modify/<cloudname>/", methods = ['POST'])
@administration_required
def cloud_account_modify(cloudname):
return cloudAccountModifyView.as_view()
2016-06-06 18:19:35 +08:00
2016-06-06 21:43:03 +08:00
@app.route("/notification/", methods=['GET'])
2016-06-06 21:35:28 +08:00
@administration_required
2016-06-06 21:58:58 +08:00
def notification_list():
2016-06-06 21:35:28 +08:00
return NotificationView.as_view()
2016-06-07 00:59:47 +08:00
@app.route("/notification/create/", methods=['GET', 'POST'])
2016-06-06 18:19:35 +08:00
@administration_required
def create_notification():
return CreateNotificationView.as_view()
2016-06-06 21:35:28 +08:00
2016-06-07 21:10:43 +08:00
@app.route("/notification/modify/", methods=['POST'])
@administration_required
def modify_notification():
return ModifyNotificationView.as_view()
@app.route("/notification/delete/", methods=['POST'])
@administration_required
def delete_notification():
return DeleteNotificationView.as_view()
2016-06-07 02:20:14 +08:00
@app.route("/notification/query_self/", methods=['POST'])
@login_required
def query_self_notifications():
return QuerySelfNotificationsView.as_view()
2016-06-07 16:21:32 +08:00
@app.route("/notification/detail/<notify_id>/", methods=['GET'])
@login_required
def query_notification_detail(notify_id):
return QueryNotificationView.get_by_id(notify_id)
@app.route("/system/modify/", methods=['POST'])
@administration_required
def systemmodify():
return systemmodifyView.as_view()
@app.route("/system/clear_history/", methods=['POST'])
@administration_required
def systemclearhistory():
return systemclearView.as_view()
@app.route("/system/add/", methods=['POST'])
@administration_required
def systemadd():
return systemaddView.as_view()
@app.route("/system/delete/", methods=['POST'])
@administration_required
def systemdelete():
return systemdeleteView.as_view()
@app.route("/system/resetall/", methods=['POST'])
@administration_required
def systemresetall():
return systemresetallView.as_view()
@app.route("/admin/", methods=['GET', 'POST'])
@administration_required
def adminpage():
return adminView.as_view()
@app.route('/index/', methods=['GET'])
def jupyter_control():
return redirect('/dashboard/')
# for download basefs.tar.bz
# remove, not the function of docklet
# should download it from a http server
#@app.route('/download/basefs', methods=['GET'])
#def download():
#fsdir = env.getenv("FS_PREFIX")
#return send_from_directory(fsdir+'/local', 'basefs.tar.bz', as_attachment=True)
# jupyter auth APIs
@app.route('/jupyter/', methods=['GET'])
def jupyter_prefix():
path = request.args.get('next')
if path == None:
return redirect('/login/')
return redirect('/login/'+'?next='+path)
@app.route('/jupyter/home/', methods=['GET'])
def jupyter_home():
return redirect('/dashboard/')
@app.route('/jupyter/login/', methods=['GET', 'POST'])
def jupyter_login():
return redirect('/login/')
@app.route('/jupyter/logout/', methods=['GET'])
def jupyter_logout():
return redirect('/logout/')
@app.route('/jupyter/authorizations/cookie/<cookie_name>/<cookie_content>/', methods=['GET'])
def jupyter_auth(cookie_name, cookie_content):
username = cookie_tool.parse_cookie(cookie_content, app.secret_key)
if username == None:
resp = make_response('cookie auth failed')
resp.status_code = 404
return resp
return json.dumps({'name': username})
@app.errorhandler(401)
def not_authorized(error):
if "username" in session:
if "401" in session:
reason = session['401']
session.pop('401', None)
if (reason == 'Token Expired'):
return redirect('/logout/')
return render_template('error/401.html', mysession = session)
else:
return redirect('/login/')
@app.errorhandler(500)
def internal_server_error(error):
logger.error(error)
logger.error(traceback.format_exc())
if "username" in session:
if "500" in session and "500_title" in session:
reason = session['500']
title = session['500_title']
session.pop('500', None)
session.pop('500_title', None)
else:
reason = '''The server encountered something unexpected that didn't allow it to complete the request. We apologize.You can go back to
<a href="/dashboard/">dashboard</a> or <a href="/logout">log out</a>'''
title = 'Internal Server Error'
return render_template('error/500.html', mysession = session, reason = reason, title = title)
else:
return redirect('/login/')
if __name__ == '__main__':
'''
to generate a secret_key
from base64 import b64encode
from os import urandom
secret_key = urandom(24)
secret_key = b64encode(secret_key).decode('utf-8')
'''
logger.info('Start Flask...:')
try:
secret_key_file = open(env.getenv('FS_PREFIX') + '/local/web_secret_key.txt')
app.secret_key = secret_key_file.read()
secret_key_file.close()
except:
from base64 import b64encode
from os import urandom
secret_key = urandom(24)
secret_key = b64encode(secret_key).decode('utf-8')
app.secret_key = secret_key
secret_key_file = open(env.getenv('FS_PREFIX') + '/local/web_secret_key.txt', 'w')
secret_key_file.write(secret_key)
secret_key_file.close()
os.environ['APP_KEY'] = app.secret_key
runcmd = sys.argv[0]
app.runpath = runcmd.rsplit('/', 1)[0]
webip = "0.0.0.0"
webport = env.getenv("WEB_PORT")
webViews.dockletrequest.endpoint = 'http://%s:%d' % (env.getenv('MASTER_IP'), env.getenv('MASTER_PORT'))
try:
opts, args = getopt.getopt(sys.argv[1:], "i:p:", ["ip=", "port="])
except getopt.GetoptError:
print ("%s -i ip -p port" % sys.argv[0])
sys.exit(2)
for opt, arg in opts:
if opt in ("-i", "--ip"):
webip = arg
elif opt in ("-p", "--port"):
webport = int(arg)
app.run(host = webip, port = webport, debug = True, threaded=True)