add ability to set and reset user usage limits

This commit is contained in:
Jordan Rodgers 2017-12-11 17:45:58 -05:00
parent 79fff2e762
commit 05e08fb92d
7 changed files with 248 additions and 13 deletions

30
app.py
View file

@ -245,6 +245,36 @@ def create():
return vmid
@app.route('/limits/<string:user>', methods=['POST'])
def set_limits(user):
cpu = request.form['cpu']
mem = request.form['mem']
disk = request.form['disk']
set_user_usage_limits(user, cpu, mem, disk)
return '', 200
@app.route('/limits/<string:user>/reset', methods=['POST'])
def reset_limits(user):
delete_user_usage_limits(user)
return '', 200
@app.route('/limits')
def limits():
proxmox = connect_proxmox(app.config['PROXMOX_HOST'],
app.config['PROXMOX_USER'],
app.config['PROXMOX_PASS'])
pools = get_pools(proxmox)
pools = sorted(pools)
user_limits = []
for pool in pools:
if pool not in app.config['IGNORED_POOLS']:
limits = get_user_usage_limits(pool)
user_limits.append([pool, limits['cpu'], limits['mem'], limits['disk']])
return render_template('limits.html', username='com6056', user_limits=user_limits)
@app.route('/novnc/<path:path>')
def send_novnc(path):
return send_from_directory('static/novnc-pve/novnc', path)

41
db.py
View file

@ -3,7 +3,7 @@ from sqlalchemy.orm import sessionmaker
from dateutil.relativedelta import relativedelta
import datetime
from db_init import VM_Expiration, Base
from db_init import VM_Expiration, Usage_Limit, Base
engine = create_engine('sqlite:///proxstar.db')
Base.metadata.bind = engine
@ -55,8 +55,39 @@ def get_expired_vms():
expired.append(vm.id)
return expired
def get_user_usage_limits(user):
limits = dict()
if session.query(exists().where(Usage_Limit.id == user)).scalar():
limits['cpu'] = session.query(Usage_Limit).filter(
Usage_Limit.id == user).one().cpu
limits['mem'] = session.query(Usage_Limit).filter(
Usage_Limit.id == user).one().mem
limits['disk'] = session.query(Usage_Limit).filter(
Usage_Limit.id == user).one().disk
else:
limits['cpu'] = 4
limits['mem'] = 4
limits['disk'] = 100
return limits
#for entry in session.query(VM_Expiration).all():
# print(entry.id, entry.expire_date)
#expiry = session.query(VM_Expiration).filter(VM_Expiration.id == 100).one()
#print(expiry.expire_date)
def set_user_usage_limits(user, cpu, mem, disk):
if session.query(exists().where(Usage_Limit.id == user)).scalar():
limits = session.query(Usage_Limit).filter(
Usage_Limit.id == user).one()
limits.cpu = cpu
limits.mem = mem
limits.disk = disk
session.commit()
else:
limits = Usage_Limit(id=user, cpu=cpu, mem=mem, disk=disk)
session.add(limits)
session.commit()
def delete_user_usage_limits(user):
if session.query(exists().where(Usage_Limit.id == user)).scalar():
limits = session.query(Usage_Limit).filter(
Usage_Limit.id == user).one()
session.delete(limits)
session.commit()

View file

@ -12,6 +12,14 @@ class VM_Expiration(Base):
expire_date = Column(Date, nullable=False)
class Usage_Limit(Base):
__tablename__ = 'usage_limit'
id = Column(String(32), primary_key=True)
cpu = Column(Integer, nullable=False)
mem = Column(Integer, nullable=False)
disk = Column(Integer, nullable=False)
engine = create_engine('sqlite:///proxstar.db')
Base.metadata.create_all(engine)

View file

@ -1,5 +1,6 @@
import time
from proxmoxer import ProxmoxAPI
from db import *
def connect_proxmox(host, user, password):
@ -119,14 +120,6 @@ def get_vm_iso(proxmox, vmid, config=None):
return iso
def get_user_usage_limits(user):
limits = dict()
limits['cpu'] = 4
limits['mem'] = 4
limits['disk'] = 100
return limits
def get_user_usage(proxmox, user):
usage = dict()
usage['cpu'] = 0
@ -247,3 +240,10 @@ def eject_vm_iso(proxmox, vmid):
def mount_vm_iso(proxmox, vmid, iso):
node = proxmox.nodes(get_vm_node(proxmox, vmid))
node.qemu(vmid).config.post(ide2="{},media=cdrom".format(iso))
def get_pools(proxmox):
pools = []
for pool in proxmox.pools.get():
pools.append(pool['poolid'])
return pools

View file

@ -568,3 +568,120 @@ $("#change-mem").click(function(){
}
});
});
$(".edit-limit").click(function(){
const user = $(this).data('user')
const cur_cpu = $(this).data('cpu')
const cur_mem = $(this).data('mem')
const cur_disk = $(this).data('disk')
var options = document.createElement('div');
cpu_text = document.createElement('p');
cpu_text.innerHTML = 'CPU';
options.append(cpu_text);
var cpu = document.createElement('input');
cpu.defaultValue = cur_cpu;
options.append(cpu);
mem_text = document.createElement('p');
mem_text.innerHTML = 'Memory (GB)';
options.append(mem_text);
var mem = document.createElement('input');
mem.defaultValue = cur_mem;
options.append(mem)
disk_text = document.createElement('p');
disk_text.innerHTML = 'Disk (GB)';
options.append(disk_text);
var disk = document.createElement('input');
disk.defaultValue = cur_disk;
options.append(disk)
swal({
title: `Enter the new limits for ${user}:`,
content: options,
buttons: {
cancel: {
text: "Cancel",
visible: true,
closeModal: true,
className: "",
},
select: {
text: "Submit",
closeModal: false,
className: "swal-button",
}
},
})
.then((willChange) => {
if (willChange) {
console.log($(cpu).val());
console.log($(mem).val());
console.log($(disk).val());
var data = new FormData();
data.append('cpu', $(cpu).val());
data.append('mem', $(mem).val());
data.append('disk', $(disk).val());
fetch(`/proxstar/limits/${user}`, {
credentials: 'same-origin',
method: 'post',
body: data
}).then((response) => {
return swal(`Now applying the new limits to ${user}!`, {
icon: "success",
buttons: {
ok: {
text: "OK",
closeModal: true,
className: "",
}
}
});
}).then(() => {
window.location = `/proxstar/limits`;
});
}
}).catch(err => {
if (err) {
swal("Uh oh...", `Unable to change the limits for ${user}. Please try again later.`, "error");
} else {
swal.stopLoading();
swal.close();
}
});
});
$(".reset-limit").click(function(){
const user = $(this).data('user')
swal({
title: `Are you sure you want to reset the usage limits for ${user} to the defaults?`,
icon: "warning",
buttons: {
cancel: true,
reset: {
text: "reset",
closeModal: false,
className: "swal-button--danger",
}
},
dangerMode: true,
})
.then((willReset) => {
if (willReset) {
fetch(`/proxstar/limits/${user}/reset`, {
credentials: 'same-origin',
method: 'post'
}).then((response) => {
return swal(`Usage limits for ${user} are now reset to defaults!`, {
icon: "success",
});
}).then(() => {
window.location = `/proxstar/limits`;
}).catch(err => {
if (err) {
swal("Uh oh...", `Unable to reset the usage limits for ${user}. Please try again later.`, "error");
} else {
swal.stopLoading();
swal.close();
}
});
}
});
});

View file

@ -38,6 +38,12 @@
Create VM
</a>
</li>
<li>
<a href="/proxstar/limits">
<span class="glyphicon glyphicon-pencil"></span>
Usage Limits
</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown navbar-user">

43
templates/limits.html Normal file
View file

@ -0,0 +1,43 @@
{% extends "base.html" %}
{% block body %}
<div class="container">
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Usage Limits</h3>
</div>
<div class="panel-body">
<table class="table table-bordered table-striped">
<thead>
<tr role="row">
<th>Username</th>
<th>CPU</th>
<th>Memory</th>
<th>Disk</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
{% for user_limit in user_limits %}
<tr role="row">
<td>{{ user_limit[0] }}</td>
<td>{{ user_limit[1] }}</td>
<td>{{ user_limit[2] }}</td>
<td>{{ user_limit[3] }}</td>
<td>
<button class="btn btn-info edit-limit" data-user="{{ user_limit[0] }}" data-cpu="{{ user_limit[1] }}" data-mem="{{ user_limit[2] }}" data-disk="{{ user_limit[3] }}">EDIT</button>
<button class="btn btn-danger reset-limit" data-user="{{ user_limit[0] }}">RESET</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}