Merge pull request #46 from zhongyehong/quotaadd

Quotaadd
This commit is contained in:
zhong yehong 2016-04-12 18:15:13 +08:00
commit ce0d18a8df
15 changed files with 240 additions and 188 deletions

View File

@ -75,6 +75,8 @@ pre_start_master () {
[ ! -d $FS_PREFIX/global ] && mkdir -p $FS_PREFIX/global
[ ! -d $FS_PREFIX/local ] && mkdir -p $FS_PREFIX/local
[ ! -d $FS_PREFIX/global/users ] && mkdir -p $FS_PREFIX/global/users
[ ! -d $FS_PREFIX/global/sys ] && mkdir -p $FS_PREFIX/global/sys
[ ! -d $FS_PREFIX/global/images ] && mkdir -p $FS_PREFIX/global/images
[ ! -d $FS_PREFIX/local/volume ] && mkdir -p $FS_PREFIX/local/volume
[ ! -d $FS_PREFIX/local/temp ] && mkdir -p $FS_PREFIX/local/temp
[ ! -d $FS_PREFIX/local/run ] && mkdir -p $FS_PREFIX/local/run

View File

@ -27,8 +27,9 @@ class Container(object):
user_info = json.loads(user_info)
cpu = user_info["data"]["groupinfo"]["cpu"]
memory = user_info["data"]["groupinfo"]["memory"]
disk = user_info["data"]["groupinfo"]["disk"]
image = json.loads(image)
status = self.imgmgr.prepareFS(username,image,lxc_name)
status = self.imgmgr.prepareFS(username,image,lxc_name,disk)
if not status:
return [False, "Create container failed when preparing filesystem, possibly insufficient space"]
@ -327,8 +328,8 @@ IP=%s
onlyglobal.append(container)
return [both, onlylocal, onlyglobal]
def create_image(self,username,imagename,containername,description="not thing",isforce = False):
return self.imgmgr.createImage(username,imagename,containername,description,isforce)
def create_image(self,username,imagename,containername,description="not thing",imagenum=10):
return self.imgmgr.createImage(username,imagename,containername,description,imagenum)
def flush_container(self,username,imagename,containername):
self.imgmgr.flush_one(username,imagename,containername)

View File

@ -234,17 +234,19 @@ class DockletHttpHandler(http.server.BaseHTTPRequestHandler):
description = form.getvalue("description")
containername = form.getvalue("containername")
isforce = form.getvalue("isforce")
if isforce == "true":
isforce = True
else:
isforce = False
[status,message] = G_vclustermgr.create_image(user,clustername,containername,imagename,description,isforce)
if not isforce == "true":
[status,message] = G_vclustermgr.image_check(user,imagename)
if not status:
self.response(200, {'success':'false','reason':'exists', 'message':message})
return [False, "image already exists"]
user_info = G_usermgr.selfQuery(cur_user = cur_user)
[status,message] = G_vclustermgr.create_image(user,clustername,containername,imagename,description,user_info["data"]["groupinfo"]["image"])
if status:
logger.info("image has been saved")
self.response(200, {'success':'true', 'action':'save'})
else:
logger.debug(message)
self.response(400, {'success':'false', 'message':message})
self.response(200, {'success':'false', 'reason':'exceed', 'message':message})
else:
logger.warning ("request not supported ")
@ -423,6 +425,9 @@ class DockletHttpHandler(http.server.BaseHTTPRequestHandler):
elif cmds[1] == 'groupadd':
result = G_usermgr.groupadd(form = form, cur_user = cur_user)
self.response(200, result)
elif cmds[1] == 'quotaadd':
result = G_usermgr.quotaadd(form = form, cur_user = cur_user)
self.response(200, result)
elif cmds[1] == 'groupdel':
result = G_usermgr.groupdel(name = form.getvalue('name', None), cur_user = cur_user)
self.response(200, result)

View File

@ -58,14 +58,18 @@ class ImageMgr():
return self.dealpath(fspath[:-1])
else:
return fspath
def createImage(self,user,image,lxc,description="Not thing",isforce = False):
def createImage(self,user,image,lxc,description="Not thing", imagenum=10):
fspath = self.NFS_PREFIX + "/local/volume/" + lxc
imgpath = self.imgpath + "private/" + user + "/"
if isforce is False:
logger.info("this save operation is not force")
if os.path.exists(imgpath+image):
return [False,"target image is exists"]
if not os.path.exists(imgpath+image):
cur_imagenum = 0
for filename in os.listdir(imgpath):
if os.path.isdir(imgpath+filename):
cur_imagenum += 1
if cur_imagenum >= int(imagenum):
return [False,"image number limit exceeded"]
try:
sys_run("mkdir -p %s" % imgpath+image,True)
sys_run("rsync -a --delete --exclude=lost+found/ --exclude=root/nfs/ --exclude=dev/ --exclude=mnt/ --exclude=tmp/ --exclude=media/ --exclude=proc/ --exclude=sys/ %s/ %s/" % (self.dealpath(fspath),imgpath+image),True)

View File

@ -40,7 +40,7 @@ import env
fsdir = env.getenv('FS_PREFIX')
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+fsdir+'/local/UserTable.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+fsdir+'/global/sys/UserTable.db'
try:
secret_key_file = open(env.getenv('FS_PREFIX') + '/local/token_secret_key.txt')
app.secret_key = secret_key_file.read()

View File

@ -20,6 +20,7 @@ from email.mime.multipart import MIMEMultipart
from email.header import Header
from datetime import datetime
import json
from log import logger
email_from_address = env.getenv('EMAIL_FROM_ADDRESS')
admin_email_address = env.getenv('ADMIN_EMAIL_ADDRESS')
@ -145,12 +146,13 @@ class userManager:
path = env.getenv('DOCKLET_LIB')
subprocess.call([path+"/userinit.sh", username])
db.session.commit()
if not os.path.exists(fspath+"/global/group"):
groupfile = open(fspath+"/global/group",'w')
if not os.path.exists(fspath+"/global/sys/quota"):
groupfile = open(fspath+"/global/sys/quota",'w')
groups = []
groups.append({'name':'root', 'cpu':'100000', 'memory':'2000', 'imageQuantity':'10', 'lifeCycle':'24'})
groups.append({'name':'admin', 'cpu':'100000', 'memory':'2000', 'imageQuantity':'10', 'lifeCycle':'24'})
groups.append({'name':'primary', 'cpu':'100000', 'memory':'2000', 'imageQuantity':'10', 'lifeCycle':'24'})
groups.append({'name':'root', 'quotas':{ 'cpu':'100000', 'disk':'2000', 'memory':'2000', 'image':'10', 'idletime':'24', 'network':'8' }})
groups.append({'name':'admin', 'quotas':{'cpu':'100000', 'disk':'2000', 'memory':'2000', 'image':'10', 'idletime':'24', 'network':'8'}})
groups.append({'name':'primary', 'quotas':{'cpu':'100000', 'disk':'2000', 'memory':'2000', 'image':'10', 'idletime':'24', 'network':'8'}})
groups.append({'name':'fundation', 'quotas':{'cpu':'100000', 'disk':'2000', 'memory':'2000', 'image':'10', 'idletime':'24', 'network':'8'}})
groupfile.write(json.dumps(groups))
groupfile.close()
@ -356,18 +358,18 @@ class userManager:
List informantion for oneself
'''
user = kwargs['cur_user']
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
group = None
for one_group in groups:
if one_group['name'] == user.user_group:
group = one_group
group = one_group['quotas']
break
else:
for one_group in groups:
if one_group['name'] == "primary":
group = one_group
group = one_group['quotas']
break
result = {
"success": 'true',
@ -385,12 +387,7 @@ class userManager:
"tel" : user.tel,
"register_date" : "%s"%(user.register_date),
"group" : user.user_group,
"groupinfo": {
"cpu": group['cpu'],
"memory": group['memory'],
"imageQuantity": group['imageQuantity'],
"lifeCycle":group['lifeCycle'],
},
"groupinfo": group,
},
}
return result
@ -458,24 +455,14 @@ class userManager:
Usage: list(cur_user = token_from_auth)
List all groups for an administrator
'''
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
result = {
"success": 'true',
"data":[]
"groups": groups,
"quotas": list(groups[0]['quotas'].keys()),
}
for group in groups:
groupinfo = [
group['name'],
group['cpu'],
group['memory'],
group['imageQuantity'],
group['lifeCycle'],
'',
]
result["data"].append(groupinfo)
return result
@administration_required
@ -484,20 +471,14 @@ class userManager:
Usage: groupQuery(name = XXX, cur_user = token_from_auth)
List a group for an administrator
'''
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
for group in groups:
if group['name'] == kwargs['name']:
result = {
"success":'true',
"data":{
"name" : group['name'] ,
"cpu" : group['cpu'] ,
"memory" : group['memory'],
"imageQuantity" : group['imageQuantity'],
"lifeCycle" : group['lifeCycle'],
}
"data": group,
}
return result
else:
@ -509,7 +490,7 @@ class userManager:
Usage: grouplist(cur_user = token_from_auth)
List all group names for an administrator
'''
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
result = {
@ -524,17 +505,18 @@ class userManager:
'''
Usage: groupModify(newValue = dict_from_form, cur_user = token_from_auth)
'''
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
for group in groups:
if group['name'] == kwargs['newValue'].getvalue('groupname',None):
form = kwargs['newValue']
group['cpu'] = form.getvalue('cpu', '')
group['memory'] = form.getvalue('memory', '')
group['imageQuantity'] = form.getvalue('image', '')
group['lifeCycle'] = form.getvalue('lifecycle', '')
groupfile = open(fspath+"/global/group",'w')
for key in form.keys():
if key == "groupname" or key == "token":
pass
else:
group['quotas'][key] = form.getvalue(key)
groupfile = open(fspath+"/global/sys/quota",'w')
groupfile.write(json.dumps(groups))
groupfile.close()
return {"success":'true'}
@ -622,15 +604,44 @@ class userManager:
return {"success":'true'}
@administration_required
def groupadd(*args, **kwargs):
def quotaadd(*args, **kwargs):
form = kwargs.get('form')
if (form.getvalue("name") == None):
return {"success":'false', "reason": "Empty group name"}
groupfile = open(fspath+"/global/group",'r')
quotaname = form.getvalue("quotaname")
default_value = form.getvalue("default_value")
if (quotaname == None):
return { "success":'false', "reason": "Empty quota name"}
if (default_value == None):
default_value = "--"
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
groups.append({'name':form.getvalue("name"), 'cpu':form.getvalue("cpu"), 'memory':form.getvalue("memory"), 'imageQuantity':form.getvalue("image"), 'lifeCycle':form.getvalue("lifecycle")})
groupfile = open(fspath+"/global/group",'w')
for group in groups:
group['quotas'][quotaname] = default_value
groupfile = open(fspath+"/global/sys/quota",'w')
groupfile.write(json.dumps(groups))
groupfile.close()
return {"success":'true'}
@administration_required
def groupadd(*args, **kwargs):
form = kwargs.get('form')
groupname = form.getvalue("groupname")
if (groupname == None):
return {"success":'false', "reason": "Empty group name"}
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
group = {
'name': groupname,
'quotas': {}
}
for key in form.keys():
if key == "groupname" or key == "token":
pass
else:
group['quotas'][key] = form.getvalue(key)
groups.append(group)
groupfile = open(fspath+"/global/sys/quota",'w')
groupfile.write(json.dumps(groups))
groupfile.close()
return {"success":'true'}
@ -640,14 +651,14 @@ class userManager:
name = kwargs.get('name', None)
if (name == None):
return {"success":'false', "reason": "Empty group name"}
groupfile = open(fspath+"/global/group",'r')
groupfile = open(fspath+"/global/sys/quota",'r')
groups = json.loads(groupfile.read())
groupfile.close()
for group in groups:
if group['name'] == name:
groups.remove(group)
break
groupfile = open(fspath+"/global/group",'w')
groupfile = open(fspath+"/global/sys/quota",'w')
groupfile.write(json.dumps(groups))
groupfile.close()
return {"success":'true'}

View File

@ -204,7 +204,14 @@ class VclusterMgr(object):
logger.info("flush success")
def create_image(self,username,clustername,containername,imagename,description,isforce=False):
def image_check(self,username,imagename):
imagepath = self.fspath + "/global/images/private/" + username + "/"
if os.path.exists(imagepath + imagename):
return [False, "image already exists"]
else:
return [True, "image not exists"]
def create_image(self,username,clustername,containername,imagename,description,imagenum=10):
[status, info] = self.get_clusterinfo(clustername,username)
if not status:
return [False, "cluster not found"]
@ -213,7 +220,7 @@ class VclusterMgr(object):
if container['containername'] == containername:
logger.info("container: %s found" % containername)
onework = self.nodemgr.ip_to_rpc(container['host'])
res = onework.create_image(username,imagename,containername,description,isforce)
res = onework.create_image(username,imagename,containername,description,imagenum)
container['lastsave'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
container['image'] = imagename
break

View File

@ -56,7 +56,7 @@
<tbody>
<tr>
<td>base</td>
<td><div class="label label-outline-success">public</div></td>
<td>public</td>
<td>docklet</td>
<td>A base image for you</td>
<td><div class="i-checks"><label><input type="radio" name="image" value="base_base_base" checked="checked"></label></div></td>
@ -64,7 +64,7 @@
{% for image in images['private'] %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-warning">{{"private"}}</div></td>
<td>private</td>
<td>{{user}}</td>
<td><a href="/image/description/{{image['name']}}_{{user}}_private/" target="_blank">{{image['description']}}</a></td>
<td><div class="i-checks"><label><input type="radio" name="image" value="{{image['name']}}_{{user}}_private"></label></div></td>
@ -74,7 +74,7 @@
{% for image in p_images %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-success">{{"public"}}</div></td>
<td>public</td>
<td>{{p_user}}</td>
<td><a href="/image/description/{{image['name']}}_{{p_user}}_public" target="_blank">{{image['description']}}</a></td>
<td><div class="i-checks"><label><input type="radio" name="image" value="{{image['name']}}_{{p_user}}_public"></label></div></td>

View File

@ -51,27 +51,16 @@
<div class="modal-body">
<form action="/group/add/" method="POST" id="addGroupForm">
<div class="form-group">
<label>Group Name</label>
<input type = "text" placeholder="Enter GroupName" class="form-control" name="name" id="mymyname">
</div>
<div class="form-group">
<label>CPU Quota</label>
<input type = "text" placeholder="Enter CPU Quota" class="form-control" name="cpu" id="myCpu" value="100000">
</div>
<div class="form-group">
<label>Memory Quota</label>
<input type="text" placeholder="Enter Memory Quota" class="form-control" name="memory" id="myMemory" value="2000">
</div>
<div class="form-group">
<label>Image Quantity</label>
<input type = "text" placeholder="Enter Image Quantity" class="form-control" name="image" id="myImage" value="10">
</div>
<div class="form-group">
<label>Life Cycle</label>
<input type = "text" placeholder="Enter Life Cycle" class="form-control" name="lifecycle" id="myLifecycle" value="24">
</div>
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" name="groupname"/>
</div>
{% for quota in quotas %}
<div class="form-group">
<label>{{ quota }}</label>
<input type="text" placeholder="Enter {{ quota }}" class="form-control" name={{ quota }} />
</div>
{% endfor %}
</form>
</div>
@ -82,59 +71,93 @@
</div>
</div>
</div>
<table id="myGroupTable" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>CPU</th>
<th>Memory</th>
<th>ImageQuantity</th>
<th>LifeCycle</th>
<th>Command</th>
</tr>
</thead>
<tbody>
</tbody>
<div class="modal inmodal" id="ModifyGroupModal" tabindex="-1" role="dialog" aria-hidden="true">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#AddQuotaModal"><i class="fa fa-plus"></i> Add Quota</button>
<div class="modal inmodal" id="AddQuotaModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content animated fadeIn">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<i class="fa fa-laptop modal-icon"></i>
<h4 class="modal-title">Modify Group</h4>
<small class="font-bold">Modify a group in Docklet</small>
<h4 class="modal-title">Add Quota</h4>
<small class="font-bold">Add a quota to Docklet</small>
</div>
<div class="modal-body">
<form action="/group/modify/" method="POST" id="modifyGroupForm">
<div class="form-group">
<label>Group Name</label>
<input type = "text" placeholder="Enter Groupname" class="form-control" name="groupname" id="mGroupname" readonly="readonly">
</div>
<div class="form-group">
<label>CPU Quota</label>
<input type = "text" placeholder="Enter CPU Quota" class="form-control" name="cpu" id="mCpu">
</div>
<div class="form-group">
<label>Memory Quota</label>
<input type="text" placeholder="Enter Memory Quota" class="form-control" name="memory" id="mMemory">
</div>
<div class="form-group">
<label>Image Quantity</label>
<input type = "text" placeholder="Enter Image Quantity" class="form-control" name="image" id="mImage">
</div>
<div class="form-group">
<label>Life Cycle</label>
<input type = "text" placeholder="Enter Life Cycle" class="form-control" name="lifecycle" id="mLifecycle">
</div>
</form>
<form action="/quota/add/" method="POST" id="addQuotaForm">
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" name="quotaname"/>
</div>
<div class="form-group">
<label>Default Value</label>
<input type="text" placeholder="Enter Default Value" class="form-control" name="default_value"/>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onClick="javascript:sendModifyGroup();">Submit</button>
<button type="button" class="btn btn-primary" onClick="javascript:sendAddQuota();">Submit</button>
</div>
</div>
</div>
</div>
</div>
<table id="myGroupTable" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
{% for quota in quotas %}
<th> {{ quota }} </th>
{% endfor %}
<th>Command</th>
</tr>
</thead>
<tbody>
{% for group in groups %}
<tr>
<th>{{ group['name'] }}</th>
{% for quota in quotas %}
<th> {{ group['quotas'][quota] }} </th>
{% endfor %}
<th><a class="btn btn-xs btn-info" data-toggle="modal" data-target="#ModifyGroupModal_{{ group['name'] }}">Edit</a>&nbsp;
{% if group['name'] in [ "root", "primary", "admin", "fundation" ] %}
<a class="btn btn-xs btn-default" href="javascript:void(0)">Delete</a></th>
{% else %}
<a class="btn btn-xs btn-danger" href="/group/delete/{{group['name']}}">Delete</a></th>
{% endif %}
<div class="modal inmodal" id="ModifyGroupModal_{{ group['name'] }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content animated fadeIn">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<i class="fa fa-laptop modal-icon"></i>
<h4 class="modal-title">Modify Group</h4>
<small class="font-bold">Modify a group in Docklet</small>
</div>
<form action="/group/modify/{{group['name']}}/" method="POST" >
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Enter Name" class="form-control" name="groupname" readonly="true" value={{ group['name'] }} />
</div>
{% for quota in quotas %}
<div class="form-group">
<label> {{ quota }}</label>
<input type="text" placeholder="Enter {{ quota }}" class="form-control" name={{ quota }} value={{ group['quotas'][quota] }} />
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
@ -149,30 +172,11 @@
<script type="text/javascript">
$(document).ready(function() {
var gTable = $('#myGroupTable').dataTable({
"ajax": {
"url": "/group/detail/",
"type": "POST"
},
//"scrollX": true,
"columnDefs": [
{
"render": function ( data, type, row ) {
return '<a class="btn btn-xs btn-info" data-toggle="modal" data-target="#ModifyGroupModal" onClick="javascript:setFormGroup('+ "'" + row[0] + "'" + ');">' + 'Edit' + '</a>'
+ '&nbsp;' +'<a class="btn btn-xs btn-danger" href="/group/delete/' + row[0] +'">' + 'Delete' + '</a>';
},
"targets": 5
},
]
});
});
function sendAddGroup(){
document.getElementById("addGroupForm").submit();
}
function sendModifyGroup(){
document.getElementById("modifyGroupForm").submit();
function sendAddQuota(){
document.getElementById("addQuotaForm").submit();
}
function setFormGroup(arg){
$.post("/group/query/",

View File

@ -68,7 +68,7 @@
</div>
<div class="modal-body">
<div class="form-group">
<form action="/workspace/scaleout/{{ clustername }}/" method="POST" id="scaleout">
<form action="/workspace/scaleout/{{ clustername }}/" method="POST" >
<table class="table table-striped table-bordered table-hover table-image">
<thead>
<tr>
@ -81,14 +81,14 @@
<tbody>
<tr>
<td>base</td>
<td><div class="label label-outline-success">public</div></td>
<td>public</td>
<td>docklet</td>
<td><input type="radio" name="image" value="base_base_base" checked="checked"></td>
</tr>
{% for image in images['private'] %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-warning">private</div></td>
<td>private</td>
<td>{{mysession['username']}}</td>
<td><input type="radio" name="image" value="{{image['name']}}_{{mysession['username']}}_private"></td>
</tr>
@ -97,7 +97,7 @@
{% for image in p_images %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-success">public</div></td>
<td>public</td>
<td>{{p_user}}</td>
<td><input type="radio" name="image" value="{{image['name']}}_{{p_user}}_public"></td>
</tr>
@ -247,7 +247,7 @@
<tbody>
<tr>
<td>base</td>
<td><div class="label label-outline-success">public</div></td>
<td>public</td>
<td>docklet</td>
<td>2015-01-01 00:00:00</td>
<td>A Base Image For You</td>
@ -257,18 +257,18 @@
{% for image in images['private'] %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-warning">{{"private"}}</div></td>
<td>private</td>
<td>{{mysession['username']}}</td>
<td>{{image['time']}}</td>
<td><a href="/image/description/{{image['name']}}_{{mysession['username']}}_private/" target="_blank">{{image['description']}}</a></td>
{% if image['isshared'] == 'false' %}
<td><div class="label label-outline-default">unshared</div></td>
<td>unshared</td>
<td>
<a href="/image/share/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-success">share</button></a>
<a href="/image/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
</td>
{% else %}
<td><div class="label label-outline-default">shared</div></td>
<td>shared</td>
<td>
<a href="/image/unshare/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-warning">unshare</button></a>
<a href="/image/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
@ -280,7 +280,7 @@
{% for image in p_images %}
<tr>
<td>{{image['name']}}</td>
<td><div class="label label-outline-success">{{"public"}}</div></td>
<td>public</td>
<td>{{p_user}}</td>
<td>{{image['time']}}</td>
<td><a href="/image/description/{{image['name']}}_{{p_user}}_public/" target="_blank">{{image['description']}}</a></td>

View File

@ -56,7 +56,7 @@
<a href="/go/{{ mysession['username'] }}/{{ cluster['name'] }}" target="_blank"><button type="button" class="btn btn-xs btn-success">&nbsp;&nbsp;&nbsp;Go&nbsp;&nbsp;&nbsp;</button></a>
</td>
{% else %}
<td><a href="/monitor/Node/"><div class="text-warning"><i class="fa fa-stop "></i> Stopped</div></a></td>
<td><a href="/vclusters/"><div class="text-warning"><i class="fa fa-stop "></i> Stopped</div></a></td>
<td>
<a href="/workspace/start/{{ cluster['name'] }}/"><button type="button" class="btn btn-xs btn-success"> &nbsp;Start&nbsp;</button></a>
<a href="/workspace/delete/{{ cluster['name'] }}/"><button type="button" class="btn btn-xs btn-danger">Delete</button></a>

View File

@ -20,7 +20,7 @@ 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, groupaddView, groupdelView, userdataView, userqueryView
from webViews.user.userlist import userlistView, useraddView, usermodifyView, userdataView, userqueryView
from webViews.user.userinfo import userinfoView
from webViews.user.userActivate import userActivateView
from webViews.user.grouplist import grouplistView, groupqueryView, groupdetailView, groupmodifyView
@ -303,9 +303,9 @@ def groupdetail():
def groupquery():
return groupqueryView.as_view()
@app.route("/group/modify/", methods=['POST'])
@app.route("/group/modify/<groupname>/", methods=['POST'])
@administration_required
def groupmodify():
def groupmodify(groupname):
return groupmodifyView.as_view()
@app.route("/user/data/", methods=['GET', 'POST'])
@ -323,6 +323,11 @@ def useradd():
def usermodify():
return usermodifyView.as_view()
@app.route("/quota/add/", methods=['POST'])
@administration_required
def quotaadd():
return quotaaddView.as_view()
@app.route("/group/add/", methods=['POST'])
@administration_required
def groupadd():

View File

@ -1,14 +1,40 @@
from flask import session
from flask import session, render_template, redirect, request
from webViews.view import normalView
from webViews.dockletrequest import dockletRequest
from webViews.dashboard import *
import time, re
import time, re, json
class adminView(normalView):
template_path = "admin.html"
@classmethod
def get(self):
groups = dockletRequest.post('/user/groupNameList/')["groups"]
return self.render(self.template_path, groups = groups)
result = dockletRequest.post('/user/groupList/')
groups = result["groups"]
quotas = result["quotas"]
return self.render(self.template_path, groups = groups, quotas = quotas)
class groupaddView(normalView):
@classmethod
def post(self):
dockletRequest.post('/user/groupadd', request.form)
return redirect('/admin/')
class quotaaddView(normalView):
@classmethod
def post(self):
dockletRequest.post('/user/quotaadd', request.form)
return redirect('/admin/')
class groupdelView(normalView):
@classmethod
def post(self):
data = {
"name" : self.groupname,
}
dockletRequest.post('/user/groupdel', data)
return redirect('/admin/')
@classmethod
def get(self):
return self.post()

View File

@ -182,6 +182,7 @@ class detailClusterView(normalView):
class saveImageView(normalView):
template_path = "saveconfirm.html"
success_path = "opsuccess.html"
error_path = "error.html"
@classmethod
def post(self):
@ -201,7 +202,10 @@ class saveImageView(normalView):
#res.clustername = self.clustername
#return res.as_view()
else:
return self.render(self.template_path, containername = self.containername, clustername = self.clustername, image = self.imagename, user = session['username'], description = self.description)
if result.get('reason') == "exists":
return self.render(self.template_path, containername = self.containername, clustername = self.clustername, image = self.imagename, user = session['username'], description = self.description)
else:
return self.render(self.error_path, message = result.get('message'))
else:
self.error()

View File

@ -49,21 +49,4 @@ class usermodifyView(normalView):
return self.render('user/mailservererror.html')
return redirect('/user/list/')
class groupaddView(normalView):
@classmethod
def post(self):
dockletRequest.post('/user/groupadd', request.form)
return redirect('/admin/')
class groupdelView(normalView):
@classmethod
def post(self):
data = {
"name" : self.groupname,
}
dockletRequest.post('/user/groupdel', data)
return redirect('/admin/')
@classmethod
def get(self):
return self.post()