diff --git a/app.py b/app.py index bf67bdc..a7b99af 100644 --- a/app.py +++ b/app.py @@ -2,9 +2,9 @@ import os import time import psycopg2 import subprocess +from db import * from starrs import * from proxmox import * -from proxmoxer import ProxmoxAPI from flask import Flask, render_template, request, redirect, send_from_directory app = Flask(__name__) @@ -17,9 +17,6 @@ app.config["GIT_REVISION"] = subprocess.check_output( ['git', 'rev-parse', '--short', 'HEAD']).decode('utf-8').rstrip() user = 'proxstar' -starrs = connect_starrs( - app.config['STARRS_DB_NAME'], app.config['STARRS_DB_USER'], - app.config['STARRS_DB_HOST'], app.config['STARRS_DB_PASS']) @app.route("/") @@ -57,6 +54,7 @@ def vm_details(vmid): vm['iso'] = get_vm_iso(proxmox, vmid, config=vm['config']) vm['interfaces'] = get_vm_interfaces( proxmox, vm['vmid'], config=vm['config']) + vm['expire'] = get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']).strftime('%m/%d/%Y') return render_template('vm_details.html', username='com6056', vm=vm) else: return '', 403 @@ -74,6 +72,18 @@ def vm_power(vmid, action): return '', 403 +@app.route("/vm//renew", methods=['POST']) +def vm_renew(vmid): + proxmox = connect_proxmox(app.config['PROXMOX_HOST'], + app.config['PROXMOX_USER'], + app.config['PROXMOX_PASS']) + if int(vmid) in get_user_allowed_vms(proxmox, user): + renew_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']) + return '', 200 + else: + return '', 403 + + @app.route("/vm//eject", methods=['POST']) def iso_eject(vmid): proxmox = connect_proxmox(app.config['PROXMOX_HOST'], @@ -104,10 +114,14 @@ def delete(vmid): proxmox = connect_proxmox(app.config['PROXMOX_HOST'], app.config['PROXMOX_USER'], app.config['PROXMOX_PASS']) + starrs = connect_starrs( + app.config['STARRS_DB_NAME'], app.config['STARRS_DB_USER'], + app.config['STARRS_DB_HOST'], app.config['STARRS_DB_PASS']) if int(vmid) in get_user_allowed_vms(proxmox, user): vmname = get_vm_config(proxmox, vmid)['name'] delete_vm(proxmox, starrs, vmid) delete_starrs(starrs, vmname) + delete_vm_expire(vmid) return '', 200 else: return '', 403 @@ -118,6 +132,9 @@ def create(): proxmox = connect_proxmox(app.config['PROXMOX_HOST'], app.config['PROXMOX_USER'], app.config['PROXMOX_PASS']) + starrs = connect_starrs( + app.config['STARRS_DB_NAME'], app.config['STARRS_DB_USER'], + app.config['STARRS_DB_HOST'], app.config['STARRS_DB_PASS']) if request.method == 'GET': usage = get_user_usage(proxmox, 'proxstar') limits = get_user_usage_limits(user) @@ -149,6 +166,7 @@ def create(): register_starrs(starrs, name, user, mac, get_next_ip(starrs, app.config['STARRS_IP_RANGE'])[0][0]) + get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']) return redirect("/proxstar/vm/{}".format(vmid)) diff --git a/cron.py b/cron.py new file mode 100644 index 0000000..f3f62fe --- /dev/null +++ b/cron.py @@ -0,0 +1,19 @@ +from db import * +from config import * +from starrs import * +from proxmox import * + + +def process_expired_vms(): + proxmox = connect_proxmox(PROXMOX_HOST, PROXMOX_USER, PROXMOX_PASS) + starrs = connect_starrs(STARRS_DB_NAME, STARRS_DB_USER, STARRS_DB_HOST, + STARRS_DB_PASS) + expired_vms = get_expired_vms() + for vmid in expired_vms: + vmname = get_vm_config(proxmox, vmid)['name'] + delete_vm(proxmox, starrs, vmid) + delete_starrs(starrs, vmname) + delete_vm_expire(vmid) + + +process_expired_vms() diff --git a/db.py b/db.py new file mode 100644 index 0000000..d1f4493 --- /dev/null +++ b/db.py @@ -0,0 +1,62 @@ +from sqlalchemy import create_engine, exists +from sqlalchemy.orm import sessionmaker +from dateutil.relativedelta import relativedelta +import datetime + +from db_init import VM_Expiration, Base + +engine = create_engine('sqlite:///proxstar.db') +Base.metadata.bind = engine + +DBSession = sessionmaker(bind=engine) +session = DBSession() + + +def get_vm_expire(vmid, months): + if session.query(exists().where(VM_Expiration.id == vmid)).scalar(): + expire = session.query(VM_Expiration).filter( + VM_Expiration.id == vmid).one().expire_date + else: + expire = datetime.date.today() + relativedelta(months=months) + new_expire = VM_Expiration(id=vmid, expire_date=expire) + session.add(new_expire) + session.commit() + return expire + + +def renew_vm_expire(vmid, months): + if session.query(exists().where(VM_Expiration.id == vmid)).scalar(): + expire = session.query(VM_Expiration).filter( + VM_Expiration.id == vmid).one() + new_expire = datetime.date.today() + relativedelta(months=months) + expire.expire_date = new_expire + session.commit() + else: + expire = datetime.date.today() + relativedelta(months=months) + new_expire = VM_Expiration(id=vmid, expire_date=expire) + session.add(new_expire) + session.commit() + + +def delete_vm_expire(vmid): + if session.query(exists().where(VM_Expiration.id == vmid)).scalar(): + expire = session.query(VM_Expiration).filter( + VM_Expiration.id == vmid).one() + session.delete(expire) + session.commit() + + +def get_expired_vms(): + expired = [] + today = datetime.date.today().strftime('%Y-%m-%d') + expire = session.query(VM_Expiration).filter( + VM_Expiration.expire_date < today).all() + for vm in expire: + expired.append(vm.id) + return expired + + +#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) diff --git a/db_init.py b/db_init.py new file mode 100644 index 0000000..810be80 --- /dev/null +++ b/db_init.py @@ -0,0 +1,17 @@ +from sqlalchemy import Column, ForeignKey, Integer, String, Date +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from sqlalchemy import create_engine + +Base = declarative_base() + + +class VM_Expiration(Base): + __tablename__ = 'vm_expiration' + id = Column(Integer, primary_key=True) + expire_date = Column(Date, nullable=False) + + +engine = create_engine('sqlite:///proxstar.db') + +Base.metadata.create_all(engine) diff --git a/static/css/styles.css b/static/css/styles.css index 786f6b3..c0e1e69 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -81,6 +81,15 @@ table, th, td { border-radius: 15px; } +.proxstar-renewbtn { + width: 20px; + height: 20px; + text-align: center; + padding: 0px 0px 0px 0px; + border-radius: 15px; + line-height: 1; +} + .resource-usage { width: 50%; margin: 0 auto; diff --git a/static/js/script.js b/static/js/script.js index 2a551c0..a9f5a59 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -244,8 +244,13 @@ $("#eject-iso").click(function(){ title: `Are you sure you want to eject ${iso}?`, icon: "warning", buttons: { - cancel: true, - delete: { + cancel: { + text: "Cancel", + visible: true, + closeModal: true, + className: "", + }, + eject: { text: "Eject", closeModal: false, className: "swal-button--danger", @@ -262,6 +267,13 @@ $("#eject-iso").click(function(){ }).then((response) => { return swal(`${iso} is now ejecting!`, { icon: "success", + buttons: { + ok: { + text: "OK", + closeModal: true, + className: "", + } + } }); }).then(() => { window.location = `/proxstar/vm/${vmid}`; @@ -294,11 +306,16 @@ $("#change-iso").click(function(){ title: 'Choose an ISO to mount:', content: iso_list, buttons: { - cancel: true, + cancel: { + text: "Cancel", + visible: true, + closeModal: true, + className: "", + }, select: { text: "Select", closeModal: false, - className: "swal-button", + className: "swal-button--danger", } }, dangerMode: true, @@ -313,6 +330,13 @@ $("#change-iso").click(function(){ }).then((response) => { return swal(`${iso} is now being mounted!`, { icon: "success", + buttons: { + ok: { + text: "OK", + closeModal: true, + className: "", + } + } }); }).then(() => { window.location = `/proxstar/vm/${vmid}`; @@ -335,3 +359,25 @@ $("#change-iso").click(function(){ } }); }); + +$("#renew-vm").click(function(){ + const vmname = $(this).data('vmname') + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/renew`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now renewing!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to renew ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); +}); diff --git a/templates/vm_details.html b/templates/vm_details.html index 224ff8c..fccf3c4 100644 --- a/templates/vm_details.html +++ b/templates/vm_details.html @@ -75,6 +75,13 @@
{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}
Memory
{{ vm['config']['memory'] }} MB
+
Expiration
+
+ {{ vm['expire'] }} + +