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, current_user from flask_sqlalchemy import get_debug_queries from . import vmanager from .forms import DeployForm, ActivateForm from .. import db from ..email import send_email from ..models import User, Permission, Deployment, Service, Region, Address, Domain, contact_proxmaster from ..decorators import admin_required, permission_required import base64 import string import random from datetime import datetime, timedelta, date, time import ast def randstr(n): return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(n)) #@vmanager.before_app_request #def before_request(): # g.user = current_user # print('current_user: %s, g.user: %s, leaving bef_req' % (current_user, g.user)) @vmanager.after_app_request def after_request(response): for query in get_debug_queries(): if query.duration >= current_app.config['SLOW_DB_QUERY_TIME']: current_app.logger.warning('Slow query: %s\nParameters: %s\nDuration: %fs\nContext: %s\n' % (query.statement, query.parameters, query.duration, query.context)) return response #APP STORE @vmanager.route('/market/', methods=['GET']) @login_required def market(group_id=0): page = { 'title': 'Market' } allproducts = Product.get_products() allgroups = current_app.config['GROUPS'] if group_id == 0: return render_template('vmanager/market.html', groups=allgroups, products=allproducts) filtered_products = {} for key, value in allproducts.items(): if value['group'] == group_id: filtered_products[key] = value if filtered_products == {}: abort(404) return render_template('vmanager/marketgroup.html', groupname=allgroups[group_id], products=filtered_products) @vmanager.route('/deploy/', methods=['GET', 'POST']) @login_required def deploy(product_id=None): #if current_user.wallet < 20: # flash('Недостатъчно средства в сметката за тази операция') # return redirect(url_for('uinvoice.addfunds')) if current_user.name is None: flash('Please update profile info for this operation.') return redirect(url_for('uinvoice.profile')) page = { 'title': 'Deploy' } try: product = Product.get_products()[product_id] except: current_app.logger.error('unknown product {}'.format(product_id)) abort(404) product_pic = '..' + product['img'] product_name = product['name'] product_description = product['description'] product_cpu = product['cpu'] product_mem = product['mem'] product_hdd = product['hdd'] product_recipe = product['recipe'] hostname = 'deploy-{}.local'.format(randstr(6)) form = DeployForm(servername=hostname, cpu=product_cpu, mem=product_mem, hdd=product_hdd, recipe=product_recipe) form.region.choices = current_app.config['REGIONS'] form.recipe.choices = current_app.config['RECIPES'] if current_user.confirmed and form.validate_on_submit(): client_id = current_user.pid data = { 'clientid': str(client_id), 'clientname': str(current_user.name), 'clientemail': str(current_user.email), 'hostname': str(form.servername.data), 'vmpass': form.vmpassword.data, 'region': form.region.data, 'vps_type': 'kvm', 'vps_recipe': form.recipe.data, 'vps_cpu': form.cpu.data, 'vps_mem': form.mem.data, 'vps_hdd': form.hdd.data, 'vps_ipv4': form.ipv4.data } try: query = contact_proxmaster(data, 'vmcreate') except: flash('Region unreachable! Please try again later...') return redirect(url_for('main.dashboard')) if query is not None: deployment = Deployment(user_id=client_id, product_id=product_id, machine_alias=form.servername.data, machine_id=query['cube'], machine_cpu=form.cpu.data, machine_mem=form.mem.data, machine_hdd=form.hdd.data, date_expire=(datetime.utcnow() + timedelta(days=30)), enabled=True) db.session.add(deployment) db.session.commit() flash('Deploy requested.') else: flash('Deploy cancelled! Please try again later...') return redirect(url_for('main.dashboard')) return render_template('vmanager/deploy.html', page=page, form=form, product_id=product_id, product_pic=product_pic, product_name=product_name, product_description=product_description, product_recipe=product_recipe) @vmanager.route('/activate/', methods=['GET', 'POST']) @login_required def activate(itemid=0): if current_user.wallet < 1: flash('Insufficient Funds') return redirect(url_for('uinvoice.addfunds')) #work with disabled deploys only result = current_user.inv_deployments.all() inventory = [] for invcls in result: inventory.extend([invcls.machine_id]) if current_user.is_administrator(): current_app.logger.info('[ADMIN] Access override for deployment id:{}'.format(itemid)) elif not itemid in inventory: current_app.logger.warning('[{}] Access violation with deployment id: {}'.format(current_user.email, itemid)) abort(404) #current_app.logger.info('[{}] Disabled deployments: {}'.format(current_user.email, inventory)) form = ActivateForm(period=Deployment.query.filter_by(machine_id=itemid)) if current_user.confirmed and form.validate_on_submit(): current_app.logger.info('payment') return render_template('vmanager/activate.html', form=form, itemid=itemid) @vmanager.route('//') @login_required def command(cmd=None, vmid=0): valid_commands = ['vmstatus', 'vmstart', 'vmshutdown', 'vmstop', 'vmvnc'] #checks whether this is a valid command if not cmd in valid_commands: current_app.logger.warning(cmd + ' is not a valid command!') abort(404) #if cmd == 'vmstart' and current_user.wallet < 3.0: # flash('Недостатъчно средства в сметката за тази операция') # return redirect(url_for('uinvoice.addfunds')) #work with enabled deploys only result = current_user.inv_deployments.filter_by(enabled=True) inventory = [] for invcls in result: inventory.extend([invcls.machine_id]) if current_user.is_administrator(): current_app.logger.info('[ADMIN] Access override for cube id:{}'.format(vmid)) db_result = contact_proxmaster({}, cmd, vmid) if cmd == 'vmvnc': return redirect(db_result['url']) else: #checks if current user owns this vmid if not vmid in inventory: current_app.logger.warning('[{}] Access violation with cube id: {}'.format(current_user.email, vmid)) #TODO: log ips else: db_result = contact_proxmaster({}, cmd, vmid) #print(db_result) if cmd == 'vmvnc': return redirect(db_result['url']) abort(404)