Merge branch 'master' of https://github.com/unias/docklet into batch

This commit is contained in:
Firmlyzhu 2018-09-23 12:45:14 +08:00
commit a10b9393f6
9 changed files with 68 additions and 27 deletions

View File

@ -620,7 +620,7 @@ def user_quotainfo_monitor(user, beans, form, issue):
return json.dumps({'success':'true', 'createdvnodes':res}) return json.dumps({'success':'true', 'createdvnodes':res})
elif issue == 'net_stats': elif issue == 'net_stats':
logger.info("handle request: monitor/user/net_stats/") logger.info("handle request: monitor/user/net_stats/")
res = G_historymgr.get_user_net_stats(user) res = monitor.Container_Fetcher.get_user_net_stats(user)
return json.dumps({'success':'true', 'net_stats':res}) return json.dumps({'success':'true', 'net_stats':res})
else: else:
return json.dumps({'success':'false', 'message':"Unspported Method!"}) return json.dumps({'success':'false', 'message':"Unspported Method!"})

View File

@ -2,6 +2,7 @@ import threading, time, traceback
from utils import env from utils import env
from utils.log import logger from utils.log import logger
from httplib2 import Http from httplib2 import Http
from urllib.parse import urlencode
# major dict to store the monitoring data # major dict to store the monitoring data
# only use on Master # only use on Master
@ -152,6 +153,18 @@ class Container_Fetcher:
res = {} res = {}
return res return res
# get users' net_stats
@staticmethod
def get_user_net_stats(owner):
global monitor_vnodes
try:
res = monitor_vnodes[owner]['net_stats']
except Exception as err:
logger.warning(traceback.format_exc())
logger.warning(err)
res = {}
return res
def get_basic_info(self): def get_basic_info(self):
global monitor_vnodes global monitor_vnodes
try: try:

View File

@ -7,7 +7,7 @@ Warning: in some early versions, "token" stand for the instance of class model.U
Original author: Liu Peidong Original author: Liu Peidong
''' '''
from utils.model import db, User, UserGroup, Notification, UserUsage from utils.model import db, User, UserGroup, Notification, UserUsage, LoginMsg
from functools import wraps from functools import wraps
import os, subprocess, math import os, subprocess, math
import hashlib import hashlib
@ -144,6 +144,7 @@ class userManager:
''' '''
try: try:
User.query.all() User.query.all()
LoginMsg.query.all()
except: except:
db.create_all() db.create_all()
if password == None: if password == None:
@ -254,7 +255,7 @@ class userManager:
} }
return result return result
def auth_external(self, form): def auth_external(self, form, userip=""):
if (env.getenv('EXTERNAL_LOGIN') != 'True'): if (env.getenv('EXTERNAL_LOGIN') != 'True'):
failed_result = {'success': 'false', 'reason' : 'external auth disabled'} failed_result = {'success': 'false', 'reason' : 'external auth disabled'}
@ -267,6 +268,10 @@ class userManager:
return failed_result return failed_result
username = result['username'] username = result['username']
logger.info("External login success: username=%s, userip=%s" % (username, userip))
loginmsg = LoginMsg(username,userip)
db.session.add(loginmsg)
db.session.commit()
user = User.query.filter_by(username = username).first() user = User.query.filter_by(username = username).first()
if (user != None and user.auth_method == result['auth_method']): if (user != None and user.auth_method == result['auth_method']):
result = { result = {
@ -316,19 +321,28 @@ class userManager:
} }
return result return result
def auth(self, username, password): def auth(self, username, password, userip=""):
''' '''
authenticate a user by username & password authenticate a user by username & password
return a token as well as some user information return a token as well as some user information
''' '''
user = User.query.filter_by(username = username).first() user = User.query.filter_by(username = username).first()
result = {}
if (user == None or user.auth_method =='pam'): if (user == None or user.auth_method =='pam'):
return self.auth_pam(username, password) result = self.auth_pam(username, password)
elif (user.auth_method == 'local'): elif (user.auth_method == 'local'):
return self.auth_local(username, password) result = self.auth_local(username, password)
else: else:
result = {'success':'false', 'reason':'auth_method error'} result = {'success':'false', 'reason':'auth_method error'}
return result
if result['success'] == 'true':
loginmsg = LoginMsg(result['data']['username'],userip)
db.session.add(loginmsg)
db.session.commit()
logger.info("Login success: username=%s, userip=%s" % (result['data']['username'], userip))
else:
logger.info("Login failed: userip=%s" % (userip))
return result
def auth_token(self, token): def auth_token(self, token):
''' '''

View File

@ -43,7 +43,8 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+fsdir+'/global/sys/UserTabl
app.config['SQLALCHEMY_BINDS'] = { app.config['SQLALCHEMY_BINDS'] = {
'history': 'sqlite:///'+fsdir+'/global/sys/HistoryTable.db', 'history': 'sqlite:///'+fsdir+'/global/sys/HistoryTable.db',
'beansapplication': 'sqlite:///'+fsdir+'/global/sys/BeansApplication.db', 'beansapplication': 'sqlite:///'+fsdir+'/global/sys/BeansApplication.db',
'system': 'sqlite:///'+fsdir+'/global/sys/System.db' 'system': 'sqlite:///'+fsdir+'/global/sys/System.db',
'login': 'sqlite:///'+fsdir+'/global/sys/Login.db'
} }
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
try: try:
@ -97,7 +98,7 @@ class User(db.Model):
self.department = department self.department = department
self.truename = truename self.truename = truename
self.tel = tel self.tel = tel
self.beans = 1000 self.beans = 150
if (date != None): if (date != None):
self.register_date = date self.register_date = date
else: else:
@ -205,6 +206,21 @@ class UserNotificationPair(db.Model):
def __repr__(self): def __repr__(self):
return '<UserName: %r, NotifyId: %r>' % (self.userName, self.notifyId) return '<UserName: %r, NotifyId: %r>' % (self.userName, self.notifyId)
class LoginMsg(db.Model):
__bind_key__ = 'login'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(10))
userip = db.Column(db.String(20))
time = db.Column(db.DateTime)
def __init__(self, username, userip):
self.username = username
self.userip = userip
self.time = datetime.now()
def __repr__(self):
return '<id=%d, username=%s, userip=%s, time=%s>' % (self.id,self.username,self.userip,self.time.strftime("%Y-%m-%d %H:%M:%S"))
class VNode(db.Model): class VNode(db.Model):
__bind_key__ = 'history' __bind_key__ = 'history'
name = db.Column(db.String(100), primary_key=True) name = db.Column(db.String(100), primary_key=True)

View File

@ -668,14 +668,3 @@ class History_Manager:
tmp = {"name":vnode.name,"billing":vnode.billing} tmp = {"name":vnode.name,"billing":vnode.billing}
res.append(tmp) res.append(tmp)
return res return res
# get users' net_stats
def get_user_net_stats(self,owner):
global monitor_vnodes
try:
res = monitor_vnodes[owner]['net_stats']
except Exception as err:
logger.warning(traceback.format_exc())
logger.warning(err)
res = {}
return res

View File

@ -87,9 +87,10 @@ def login():
logger.info("handle request : user login") logger.info("handle request : user login")
user = request.form.get("user", None) user = request.form.get("user", None)
key = request.form.get("key", None) key = request.form.get("key", None)
userip = request.form.get("ip", "")
if user == None or key == None: if user == None or key == None:
return json.dumps({'success': 'false', 'message':'user or key is null'}) return json.dumps({'success': 'false', 'message':'user or key is null'})
auth_result = G_usermgr.auth(user,key) auth_result = G_usermgr.auth(user,key,userip)
if auth_result['success'] == 'false': if auth_result['success'] == 'false':
logger.info("%s login failed" % user) logger.info("%s login failed" % user)
return json.dumps({'success':'false', 'message':'auth failed'}) return json.dumps({'success':'false', 'message':'auth failed'})
@ -100,8 +101,9 @@ def login():
def external_login(): def external_login():
global G_usermgr global G_usermgr
logger.info("handle request : external user login") logger.info("handle request : external user login")
userip = request.form.get("ip", "")
try: try:
result = G_usermgr.auth_external(request.form) result = G_usermgr.auth_external(request.form,userip)
return json.dumps(result) return json.dumps(result)
except: except:
result = {'success':'false', 'reason':'Something wrong happened when auth an external account'} result = {'success':'false', 'reason':'Something wrong happened when auth an external account'}
@ -517,6 +519,9 @@ def billing_beans():
def beans_apply(cur_user,user,form,issue): def beans_apply(cur_user,user,form,issue):
global G_applicationmgr global G_applicationmgr
if issue == 'apply': if issue == 'apply':
if not cur_user.status == 'normal':
return json.dumps({'success':'false', 'message':'Fail to apply for beans because your account is locked/not activated. Please:'+
'\n 1. Complete your information and activate your account. \n Or: \n 2.Contact administor for further information'})
number = form.get("number",None) number = form.get("number",None)
reason = form.get("reason",None) reason = form.get("reason",None)
if number is None or reason is None: if number is None or reason is None:

View File

@ -50,14 +50,14 @@
<form action="/beans/apply/" method="POST" id="beansapplyForm"> <form action="/beans/apply/" method="POST" id="beansapplyForm">
<div class="form-group"> <div class="form-group">
<label>Number</label><small class="font-bold"> How many beans do you need?</small> <label>Number</label><small class="font-bold"> How many beans do you need?</small>
<input type="number" class="form-control" placeholder="100-5000" name="number" id="number" min="100" max="5000"/> <input type="number" class="form-control" placeholder="100-5000" name="number" id="number" min="100" max="5000" required />
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Reason</label> <label>Reason</label>
<textarea class="form-control" name="reason" cols="28" rows="5" onKeyDown="textCounter(reason,remLen,300);" onKeyUp="textCounter(reason,remLen,300);" placeholder="Please describe what you will do in your workspace with the beans."></textarea> <textarea class="form-control" name="reason" cols="28" rows="5" onKeyDown="textCounter(reason,remLen,300);" onKeyUp="textCounter(reason,remLen,300);" placeholder="Please describe what you will do in your workspace with the beans."></textarea>
You could only input <input name="remLen" type="text" value="300" size="3" readonly="readonly"> more characters. You could only input <input name="remLen" type="text" value="300" size="3" readonly="readonly"> more characters.
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-white" data-dismiss="modal">Close</button> <button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Submit</button> <button type="submit" class="btn btn-primary">Submit</button>
@ -104,11 +104,15 @@
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script> <script src="http://cdn.bootcss.com/datatables/1.10.11/js/jquery.dataTables.js"></script>
<script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script> <script src="http://cdn.bootcss.com/datatables/1.10.11/js/dataTables.bootstrap.js"></script>
<script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script> <script src="http://cdn.bootcss.com/datatables-tabletools/2.1.5/js/TableTools.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-validate/1.17.0/jquery.validate.js"></script>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$(".table-image").DataTable(); $(".table-image").DataTable();
}); });
$().ready(function() {
$("#beansapplyForm").validate();
});
function textCounter(field,countfield,maxlimit) function textCounter(field,countfield,maxlimit)
{ {
if(field.value.length > maxlimit) if(field.value.length > maxlimit)
@ -116,7 +120,7 @@ function textCounter(field,countfield,maxlimit)
else else
countfield.value = maxlimit - field.value.length; countfield.value = maxlimit - field.value.length;
} }
</script> </script>
{% endblock %} {% endblock %}

View File

@ -143,7 +143,7 @@ def state_batch_job():
return stateBatchJobView().as_view() return stateBatchJobView().as_view()
@app.route("/workspace/create/", methods=['GET']) @app.route("/workspace/create/", methods=['GET'])
@activated_required #@activated_required
def addCluster(): def addCluster():
return addClusterView.as_view() return addClusterView.as_view()

View File

@ -52,7 +52,7 @@ class loginView(normalView):
@classmethod @classmethod
def post(self): def post(self):
if (request.form['username']): if (request.form['username']):
data = {"user": request.form['username'], "key": request.form['password']} data = {"user": request.form['username'], "key": request.form['password'], 'ip': request.remote_addr}
result = dockletRequest.unauthorizedpost('/login/', data) result = dockletRequest.unauthorizedpost('/login/', data)
ok = result and result.get('success', None) ok = result and result.get('success', None)
if (ok and (ok == "true")): if (ok and (ok == "true")):