mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-03-09 15:40:09 +00:00
add ability to set and reset user usage limits
This commit is contained in:
parent
79fff2e762
commit
05e08fb92d
7 changed files with 248 additions and 13 deletions
30
app.py
30
app.py
|
@ -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
41
db.py
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
16
proxmox.py
16
proxmox.py
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
43
templates/limits.html
Normal 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 %}
|
Loading…
Add table
Add a link
Reference in a new issue