From 05e08fb92d8d3b898bdb63e4866a64f06bbd0dfd Mon Sep 17 00:00:00 2001 From: Jordan Rodgers Date: Mon, 11 Dec 2017 17:45:58 -0500 Subject: [PATCH] add ability to set and reset user usage limits --- app.py | 30 +++++++++++ db.py | 41 +++++++++++++-- db_init.py | 8 +++ proxmox.py | 16 +++--- static/js/script.js | 117 ++++++++++++++++++++++++++++++++++++++++++ templates/base.html | 6 +++ templates/limits.html | 43 ++++++++++++++++ 7 files changed, 248 insertions(+), 13 deletions(-) create mode 100644 templates/limits.html diff --git a/app.py b/app.py index 369da55..29c051d 100644 --- a/app.py +++ b/app.py @@ -245,6 +245,36 @@ def create(): return vmid +@app.route('/limits/', 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//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/') def send_novnc(path): return send_from_directory('static/novnc-pve/novnc', path) diff --git a/db.py b/db.py index d1f4493..1457a22 100644 --- a/db.py +++ b/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() diff --git a/db_init.py b/db_init.py index 810be80..3f5a7ff 100644 --- a/db_init.py +++ b/db_init.py @@ -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) diff --git a/proxmox.py b/proxmox.py index 099a233..354ad9f 100644 --- a/proxmox.py +++ b/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 diff --git a/static/js/script.js b/static/js/script.js index a9106c0..a086394 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -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(); + } + }); + } + }); +}); diff --git a/templates/base.html b/templates/base.html index a34d936..e2809bf 100644 --- a/templates/base.html +++ b/templates/base.html @@ -38,6 +38,12 @@ Create VM +
  • + + + Usage Limits + +