diff --git a/app/admin/routes.py b/app/admin/routes.py index 6940f2c..c14f21c 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -1,5 +1,5 @@ from flask import render_template, abort, redirect, url_for, abort, flash, request, current_app, make_response, g -from flask_login import login_required, login_user, logout_user +from flask_login import fresh_login_required, login_user, logout_user from flask_sqlalchemy import get_debug_queries from . import admin @@ -29,35 +29,35 @@ def after_request(response): return response @admin.route("/", methods=['GET']) -@login_required +@fresh_login_required @admin_required def index(): return redirect(url_for('admin.list_users')) @admin.route("/listdeployments", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_deployments(): alldeployments = Deployment.query.filter_by(deleted=False).order_by(Deployment.daysleft.asc()).all() return render_template('admin/list_deployments.html', deployments=alldeployments) @admin.route("/listservices", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_services(): allservices = Service.query.filter_by(deleted=False).order_by(Service.daysleft.asc()).all() return render_template('admin/list_services.html', services=allservices) @admin.route("/listdomains", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_domains(): alldomains = Domain.query.filter_by(deleted=False).order_by(Domain.daysleft.asc()).all() return render_template('admin/list_domains.html', domains=alldomains) @admin.route("/listrecyclebin", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_recyclebin(): deployments = Deployment.query.filter_by(protected=False).order_by(Deployment.daysleft.asc()).all() @@ -66,14 +66,14 @@ def list_recyclebin(): return render_template('admin/list_recyclebin.html', deployments=deployments, services=services, domains=domains) @admin.route("/listaddresses", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_addresses(): alladdresses = Address.query.order_by(Address.ip.asc()).all() return render_template('admin/list_addresses.html', addresses=alladdresses) @admin.route("/addr2pool", methods=['GET', 'POST']) -@login_required +@fresh_login_required @admin_required def addr2pool(): alladdrlist = [] @@ -94,14 +94,14 @@ def addr2pool(): return render_template('admin/addr2pool.html', form=form, alladdresses=alladdrlist) @admin.route("/listusers", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_users(): allusers = User.query.filter_by(active=True).order_by(User.last_seen.desc()).all() return render_template('admin/list_users.html', users=allusers) @admin.route("/charge/", methods=['GET', 'POST']) -@login_required +@fresh_login_required @admin_required def charge(user_pid=0): cuser = User.query.filter_by(pid=user_pid).first() @@ -118,14 +118,14 @@ def charge(user_pid=0): return render_template('admin/charge.html', form=form, usr=cuser) @admin.route("/listtransactions", methods=['GET']) -@login_required +@fresh_login_required @admin_required def list_transactions(): alltransactions = Transaction.query.order_by(Transaction.date_created.desc()).all() return render_template('admin/list_transactions.html', transactions=alltransactions) @admin.route("/transaction/", methods=['GET']) -@login_required +@fresh_login_required @admin_required def transaction(user_pid=0): cuser = User.query.filter_by(pid=user_pid).first() @@ -147,7 +147,7 @@ def transaction(user_pid=0): return render_template('uinvoice/transactions.html', transactions=transactions, translist=translist, labelslist=labelslist, cuser=cuser) @admin.route("/dashboard/", methods=['GET']) -@login_required +@fresh_login_required @admin_required def dashboard(user_pid=0): cuser = User.query.filter_by(pid=user_pid).first() diff --git a/app/templates/admin/list_recyclebin.html b/app/templates/admin/list_recyclebin.html index d7e61fd..c06b467 100644 --- a/app/templates/admin/list_recyclebin.html +++ b/app/templates/admin/list_recyclebin.html @@ -38,7 +38,7 @@ addEventListener("DOMContentLoaded", function() { //alert(request.responseText); }; // We point the request at the appropriate command - request.open("GET", "/vmanager/" + command + "/" + vmid, true); + request.open("GET", "/vmanager/command/" + command + "/" + vmid, true); // and then we send it off request.send(); alert("command " + command + " executed."); diff --git a/app/templates/main/dashboard.html b/app/templates/main/dashboard.html index 4a19adb..d356db5 100644 --- a/app/templates/main/dashboard.html +++ b/app/templates/main/dashboard.html @@ -116,7 +116,7 @@ addEventListener("DOMContentLoaded", function() { //alert(request.responseText); }; // We point the request at the appropriate command - request.open("GET", "/vmanager/" + command + "/" + vmid, true); + request.open("GET", "/vmanager/command/" + command + "/" + vmid, true); // and then we send it off request.send(); alert("command " + command + " executed."); @@ -185,7 +185,7 @@ addEventListener("DOMContentLoaded", function() {

- + {% else %} {% endif %} @@ -333,11 +333,11 @@ addEventListener("DOMContentLoaded", function() { {% endif %} + {% if inv_services != [] %}

Services
- {% if inv_services != [] %}
@@ -377,7 +377,7 @@ addEventListener("DOMContentLoaded", function() { {% else %} - + {% endif %} diff --git a/app/vmanager/forms.py b/app/vmanager/forms.py index d98c5aa..1acdc1d 100644 --- a/app/vmanager/forms.py +++ b/app/vmanager/forms.py @@ -12,7 +12,7 @@ class CreateForm(FlaskForm): region = SelectField('Region:', choices=region_choices, coerce=int) invite_key = StringField('Invite Code:', [validators.DataRequired(), validators.Length(6,35)]) def validate_invite_key(self, field): - if field.data != 'inv1919': + if field.data != 'invitation1919': raise ValidationError('Denied') submit = SubmitField('Create') diff --git a/app/vmanager/routes.py b/app/vmanager/routes.py index 5de8265..212e160 100644 --- a/app/vmanager/routes.py +++ b/app/vmanager/routes.py @@ -6,7 +6,7 @@ from . import vmanager from .forms import CreateForm, ActivateForm from .. import db from ..email import send_email -from ..models import User, Permission, Transaction, Router, Deployment, Service, Region, Address, Domain, contact_proxmaster +from ..models import User, Permission, Transaction, Bridge, Router, Deployment, Service, Region, Address, Domain, contact_proxmaster from ..decorators import admin_required, permission_required import base64 @@ -43,55 +43,71 @@ def createvm(): if current_user.confirmed and form.validate_on_submit(): selected_region = Region.query.filter_by(pid=int(form.region.data)).first() + #TODO: Filter switches for the selected region only! + selected_bridge = current_user.inv_bridges.filter_by(deleted=False).all() + if selected_bridge == []: + #no switches in the account. create one... + data = { 'clientid': str(current_user.pid), + 'clientemail': str(current_user.email), + 'region': str(selected_region.name) + } + query = contact_proxmaster(data, 'brcreate') + if query is not None: + bridge = Bridge(user_id=int(current_user.pid)) + db.session.add(bridge) + db.session.commit() + flash('New point created successfully in region "{}".'.format(str(selected_region.description))) + newbridge = True + else: + flash('Point could not be created! Please try again later...') + return redirect(url_for('main.dashboard')) + else: + #bridge found. lets see on which slave it is so we can create the instance on the same slave. + data = {} + query = contact_proxmaster(data, 'brquery', str(selected_bridge.bridge_id)) + if query is not None: + newbridge = False + else: + flash('Point found but cannot be used1') + return redirect(url_for('main.dashboard')) + + #machine will be installed where the switch physically is + slave_name = query['slave_name'] + bridge_id = query['bridge_id'] + + #create new machine... data = { 'clientid': str(current_user.pid), 'clientemail': str(current_user.email), - 'hostname': 'c' + str(current_user.pid) + str(form.servername.data), + 'hostname': str(form.servername.data) + '-c' + str(current_user.pid), 'region': str(selected_region.name), + 'slave': str(slave_name), 'type': 'kvm', 'cpu': '1', 'mem': '512', - 'hdd': '20' + 'hdd': '20', + 'eth0br': str(bridge_id), + 'eth0ip': 'AUTO' } try: query = contact_proxmaster(data, 'vmcreate') except: - flash('Region unreachable! Cannot create deployment. Please try again later...') + flash('Region not available! Please try again later...') return redirect(url_for('main.dashboard')) if query is not None: deployment = Deployment(user_id=int(current_user.pid), machine_alias=query['hostname'], machine_id=query['cube'], machine_cpu=data['cpu'], machine_mem=data['mem'], machine_hdd=data['hdd'], enabled=True, protected=False, daysleft=15, warning=True, discount=0) db.session.add(deployment) db.session.commit() - flash('Machine created successfully in region "{}".'.format(str(selected_region.description))) + flash('New device created successfully in region "{}".'.format(str(selected_region.description))) + return redirect(url_for('main.dashboard')) else: - flash('Machine creation cancelled! Please try again later...') + flash('Device could not be created! Please try again later...') + #TODO: cleanup bridge if the machine is new and we were not be able to create it + return redirect(url_for('main.dashboard')) return render_template('vmanager/create.html', form=form) -@vmanager.route('/vmremove/', methods=['GET', 'POST']) -@login_required -def remove(itemid=0): - data = {} - deploy = Deployment.query.filter_by(machine_id=int(itemid)).first() - if current_user.is_administrator(): - if deploy.protected is not True: - try: - query = contact_proxmaster(data, 'vmremove', int(itemid)) - flash('Machine {} terminated'.format(itemid)) - deploy.deleted = True - deploy.enabled = False - deploy.warning = False - db.session.commit() - except: - flash('Cannot delete machine {}'.format(itemid)) - return redirect(url_for('admin.list_recyclebin')) - else: - current_app.logger.warning('Deployment id:{} is protected! Cannot be removed'.format(itemid)) - else: - current_app.logger.warning('[WARNING] Unauthorized attempt to remove Deployment id:{}'.format(itemid)) - abort(404) - @vmanager.route('/activate/', methods=['GET', 'POST']) @login_required def activate(itemid=0): @@ -103,11 +119,13 @@ def activate(itemid=0): current_app.logger.warning('[ADMIN] Access override for deployment id:{}'.format(itemid)) elif not itemid in inventory: current_app.logger.error('[{}] Access violation with deployment id: {}'.format(current_user.email, itemid)) - abort(404) + abort(403) deploy = Deployment.query.filter_by(machine_id=itemid).first() - if deploy.enabled == True and deploy.warning == False: + if deploy is None: abort(404) + if deploy.enabled == True and deploy.warning == False: + abort(403) cpu_cost = deploy.machine_cpu * current_app.config['CPU_RATIO'] mem_cost = ( deploy.machine_mem / 1024 ) * current_app.config['MEM_RATIO'] hdd_cost = deploy.machine_hdd * current_app.config['HDD_RATIO'] @@ -133,6 +151,35 @@ def activate(itemid=0): else: return redirect(url_for('uinvoice.transactions')) current_app.logger.info('[{}] Charge deployment: {}'.format(owner.email, deploy.machine_id)) + + router = current_user.inv_routers.filter_by(deleted=False).all() + if router == []: + + #no router. creating... + data = { 'clientid': str(current_user.pid), + 'clientemail': str(current_user.email), + 'hostname': 'c' + str(current_user.pid) + 'router', + 'region': str(selected_region.name), + 'slave': str(selected_slave), + 'type': 'lxc', + 'cpu': '1', + 'mem': '128', + 'hdd': '1', + 'eth0br': str(bridge_id), + 'eth0ip': '192.168.9.1', + 'eth1br': 'vmbr0', + 'eth1ip': str(selected_address.ip) + } + try: + query = contact_proxmaster(data, 'vmcreate') + except: + flash('Region unreachable! Cannot create router. Please try again later...') + return redirect(url_for('main.dashboard')) + if query is not None: + router = Router(user_id=int(current_user.pid), machine_id=query['cube']) + db.session.add(router) + db.session.commit() + today = datetime.utcnow() expiry = today + relativedelta(today, months=+(form.period.data)) daysleft = expiry - today @@ -143,11 +190,7 @@ def activate(itemid=0): deploy.warning = False deploy.enabled = True deploy.protected = True - db.session.commit() - - #router = current_user.inv_routers.filter_by(deleted=False).all() - #if router == []: - + db.session.commit() transaction = Transaction(user_id=int(owner.pid), description='Deployment {} activated for {} month(s)'.format(str(deploy.machine_alias), form.period.data), value=-total) db.session.add(transaction) @@ -161,8 +204,30 @@ def activate(itemid=0): return redirect(url_for('main.dashboard')) return render_template('vmanager/activate.html', form=form, deploy=deploy, cpu_cost=cpu_cost, mem_cost=mem_cost, hdd_cost=hdd_cost, ppm=ppm, discount=discount, total=total, currency=owner.currency) +@vmanager.route('/vmremove/', methods=['GET', 'POST']) +@login_required +def remove(itemid=0): + data = {} + deploy = Deployment.query.filter_by(machine_id=int(itemid)).first() + if current_user.is_administrator(): + if deploy.protected is not True: + try: + query = contact_proxmaster(data, 'vmremove', int(itemid)) + flash('Machine {} terminated'.format(itemid)) + deploy.deleted = True + deploy.enabled = False + deploy.warning = False + db.session.commit() + except: + flash('Cannot delete machine {}'.format(itemid)) + return redirect(url_for('admin.list_recyclebin')) + else: + current_app.logger.warning('Deployment id:{} is protected! Cannot be removed'.format(itemid)) + else: + current_app.logger.warning('[WARNING] Unauthorized attempt to remove Deployment id:{}'.format(itemid)) + abort(404) -@vmanager.route('//') +@vmanager.route('/command//') @login_required def command(cmd=None, vmid=0): #checks whether this is a valid command