From 541bd3663ea55189db89c35b10b64a9b99c90784 Mon Sep 17 00:00:00 2001
From: deflax
Date: Sun, 15 Oct 2017 14:38:38 +0300
Subject: [PATCH] various fixes 2
---
app/admin/routes.py | 26 ++---
app/templates/admin/list_recyclebin.html | 2 +-
app/templates/main/dashboard.html | 8 +-
app/vmanager/forms.py | 2 +-
app/vmanager/routes.py | 139 +++++++++++++++++------
5 files changed, 121 insertions(+), 56 deletions(-)
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