diff --git a/conf/docklet.conf.template b/conf/docklet.conf.template index 0537c51..a5f8727 100644 --- a/conf/docklet.conf.template +++ b/conf/docklet.conf.template @@ -134,3 +134,11 @@ # If this address i "", no email will be sent to admin. # default: "" # ADMIN_EMAIL_ADDRESS="" + +# GLUSTER_VOLUME_QUOTA : whether enable the quota of glusterfs volume or not +# default: "NO" +# GLUSTER_VOLUME_QUOTA="" + +# GLUSTER_VOLUME_NAME : the name of glusterfs volume +# default: "docklet-volume" +# GLUSTER_VOLUME_NAME="" diff --git a/src/env.py b/src/env.py index 77c66bd..88273db 100755 --- a/src/env.py +++ b/src/env.py @@ -50,5 +50,9 @@ def getenv(key): return os.environ.get("EMAIL_FROM_ADDRESS", "") elif key =="ADMIN_EMAIL_ADDRESS": return os.environ.get("ADMIN_EMAIL_ADDRESS", "") + elif key =="GLUSTER_VOLUME_QUOTA": + return os.environ.get("GLUSTER_VOLUME_QUOTA", "NO") + elif key =="GLUSTER_VOLUME_NAME": + return os.environ.get("GLUSTER_VOLUME_NAME", "docklet-volume") else: return os.environ[key] diff --git a/src/httprest.py b/src/httprest.py index 30c7cbd..44da511 100755 --- a/src/httprest.py +++ b/src/httprest.py @@ -315,7 +315,7 @@ def description_image(cur_user, user, form): @login_required def share_image(cur_user, user, form): global G_imagemgr - image = form.getvalue('image') + image = form.get('image') G_imagemgr.shareImage(user,image) return json.dumps({'success':'true', 'action':'share'}) @@ -555,7 +555,7 @@ def groupList_user(cur_user, user, form): def groupQuery_user(cur_user, user, form): global G_usermgr logger.info("handle request: user/groupQuery/") - result = G_usermgr.groupQuery(name = form.getvalue("name"), cur_user = cur_user) + result = G_usermgr.groupQuery(name = form.get("name"), cur_user = cur_user) return json.dumps(result) @app.route("/user/selfQuery/", methods=['POST']) diff --git a/src/userManager.py b/src/userManager.py index 74b9c11..f545982 100755 --- a/src/userManager.py +++ b/src/userManager.py @@ -21,11 +21,15 @@ from email.header import Header from datetime import datetime import json from log import logger +from lvmtool import * email_from_address = env.getenv('EMAIL_FROM_ADDRESS') admin_email_address = env.getenv('ADMIN_EMAIL_ADDRESS') PAM = pam.pam() fspath = env.getenv('FS_PREFIX') +gluster_volume_quota = env.getenv('GLUSTER_VOLUME_QUOTA') +gluster_volume_name = env.getenv('GLUSTER_VOLUME_NAME') + if (env.getenv('EXTERNAL_LOGIN').lower() == 'true'): from plugin import external_receive @@ -305,6 +309,21 @@ class userManager: ''' user = User.verify_auth_token(token) return user + + def set_nfs_quota_bygroup(self,groupname, quota): + users = User.query.filter_by(user_group = groupname).all() + for user in users: + self.set_nfs_quota(user.username, quota) + + def set_nfs_quota(self, username, quota): + if not gluster_volume_quota == "YES": + return + nfspath = "/users/%s/data" % username + try: + sys_run("gluster volume quota %s limit-usage %s %sGB" % (gluster_volume_name, nfspath, quota)) + except Exception as e: + logger.error(e) + @administration_required def query(*args, **kwargs): @@ -487,7 +506,7 @@ class userManager: @administration_required def change_default_group(*args, **kwargs): form = kwargs['form'] - default_group = form.getvalue('defaultgroup') + default_group = form.get('defaultgroup') quotafile = open(fspath+"/global/sys/quotainfo",'r') quotas = json.loads(quotafile.read()) quotafile.close() @@ -498,8 +517,7 @@ class userManager: return { 'success':'true', 'action':'change default group' } - @administration_required - def groupQuery(*args, **kwargs): + def groupQuery(self, *args, **kwargs): ''' Usage: groupQuery(name = XXX, cur_user = token_from_auth) List a group for an administrator @@ -511,7 +529,7 @@ class userManager: if group['name'] == kwargs['name']: result = { "success":'true', - "data": group, + "data": group['quotas'], } return result else: @@ -534,7 +552,7 @@ class userManager: return result @administration_required - def groupModify(*args, **kwargs): + def groupModify(self, *args, **kwargs): ''' Usage: groupModify(newValue = dict_from_form, cur_user = token_from_auth) ''' @@ -545,6 +563,12 @@ class userManager: if group['name'] == kwargs['newValue'].get('groupname',None): form = kwargs['newValue'] for key in form.keys(): + if key == "data": + if not group['quotas'][key] == form.get(key): + self.set_nfs_quota_bygroup(group['name'],form.get(key)) + else: + pass + if key == "groupname" or key == "token": pass else: @@ -557,7 +581,7 @@ class userManager: return {"success":'false', "reason":"UserGroup does not exist"} @administration_required - def modify(*args, **kwargs): + def modify(self, *args, **kwargs): ''' modify a user's information in database will send an e-mail when status is changed from 'applying' to 'normal' @@ -587,6 +611,9 @@ class userManager: #self.chpassword(cur_user = user_modify, password = form.get('password','no_password')) db.session.commit() + res = self.groupQuery(name=user_modify.user_group) + if res['success']: + self.set_nfs_quota(user_modify.username,res['data']['data']) return {"success":'true'} #except: #return {"success":'false', "reason":"Something happened"} @@ -599,6 +626,8 @@ class userManager: cur_user = kwargs['cur_user'] cur_user.password = hashlib.sha512(kwargs['password'].encode('utf-8')).hexdigest() + + def newuser(*args, **kwargs): ''' Usage : newuser() @@ -613,7 +642,7 @@ class userManager: user_new.avatar = 'default.png' return user_new - def register(*args, **kwargs): + def register(self, *args, **kwargs): ''' Usage: register(user = modified_from_newuser()) ''' @@ -637,6 +666,9 @@ class userManager: #if newuser.status == 'normal': path = env.getenv('DOCKLET_LIB') subprocess.call([path+"/userinit.sh", newuser.username]) + res = self.groupQuery(name=newuser.user_group) + if res['success']: + self.set_nfs_quota(newuser.username,res['data']['data']) return {"success":'true'} @administration_required diff --git a/tools/upgrade.py b/tools/upgrade.py index c1eeb37..6f5dcab 100755 --- a/tools/upgrade.py +++ b/tools/upgrade.py @@ -1,6 +1,9 @@ #!/usr/bin/python3 -import os, json +import os, json, sys +sys.path.append("../src") +from model import db, User +from lvmtool import * fspath="/opt/docklet" @@ -39,5 +42,63 @@ def update_quotainfo(): quotafile.write(json.dumps(quotas)) quotafile.close() +def allquota(): + try: + quotafile = open(fspath+"/global/sys/quota", 'r') + quotas = json.loads(quotafile.read()) + quotafile.close() + return quotas + except Exception as e: + print(e) + return None + +def quotaquery(quotaname,quotas): + for quota in quotas: + if quota['name'] == quotaname: + return quota['quotas'] + return None + +def enable_gluster_quota(): + conffile=open("../conf/docklet.conf",'r') + conf=conffile.readlines() + conffile.close() + enable = False + volume_name = "" + for line in conf: + if line.startswith("GLUSTER_VOLUME_QUOTA"): + keyvalue = line.split("=") + if len(keyvalue) < 2: + continue + key = keyvalue[0].strip() + value = keyvalue[1].strip() + if value == "YES": + enable = True + break + for line in conf: + if line.startswith("GLUSTER_VOLUME_NAME"): + keyvalue = line.split("=") + if len(keyvalue) < 2: + continue + volume_name = keyvalue[1].strip() + if not enable: + print("don't need to enable the quota") + return + + users = User.query.all() + quotas = allquota() + if quotaquery == None: + print("quota info not found") + return + sys_run("gluster volume quota %s enable" % volume_name) + for user in users: + quota = quotaquery(user.user_group, quotas) + nfs_quota = quota['data'] + if nfs_quota == None: + print("data quota should be set") + return + nfspath = "/users/%s/data" % user.username + sys_run("gluster volume quota %s limit-usage %s %sGB" % (volume_name,nfspath,nfs_quota)) + if __name__ == '__main__': update_quotainfo() + enable_gluster_quota()