From 860eccd159bbc4750a491bc8a90d3c0658d803e2 Mon Sep 17 00:00:00 2001 From: deflax Date: Fri, 15 Dec 2017 01:00:02 +0200 Subject: [PATCH] create-activate phase 3 --- app/__init__.py | 9 ++- app/admin/routes.py | 27 ++++---- app/auth/routes.py | 5 +- app/main/routes.py | 34 ++-------- app/models.py | 12 ++-- app/templates/admin/list_addresses.html | 8 ++- app/templates/email/adm_logger.html | 6 ++ app/templates/email/adm_logger.txt | 6 ++ app/templates/main/dashboard.html | 68 ++++++++++++------- .../vmanager/email/adm_unreachable.html | 4 +- .../vmanager/email/adm_unreachable.txt | 3 + app/vmanager/routes.py | 66 +++++++++--------- cronexec.sh | 5 ++ manage.py | 10 ++- start.wsgi | 4 +- 15 files changed, 155 insertions(+), 112 deletions(-) create mode 100644 app/templates/email/adm_logger.html create mode 100644 app/templates/email/adm_logger.txt diff --git a/app/__init__.py b/app/__init__.py index d84d953..683ee20 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -12,8 +12,8 @@ from werkzeug.contrib.fixers import ProxyFix from config import config app = Flask(__name__) -app.config.from_object(config['default']) -config['default'].init_app(app) +app.config.from_object(config['dev']) +config['dev'].init_app(app) app.wsgi_app = ProxyFix(app.wsgi_app) db = SQLAlchemy(session_options = { "autoflush": False }) @@ -76,8 +76,7 @@ class CustomJSONEncoder(JSONEncoder): app.json_encoder = CustomJSONEncoder -#TODO: if app.debug: -if not app.debug: +if app.config['DEBUG'] == 1: import logging from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler('/home/proxadmin/appserver/proxadmin/log/proxadmin.log', 'a', 1 * 1024 * 1024, 10) @@ -137,7 +136,7 @@ def get_locale(): # g.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time) # g.pjax = 'X-PJAX' in request.headers -if not app.debug and app.config['MAIL_SERVER'] != '': +if not app.config['DEBUG'] == 1 and app.config['MAIL_SERVER'] != '': import logging from logging.handlers import SMTPHandler credentials = None diff --git a/app/admin/routes.py b/app/admin/routes.py index 3d1dc0a..dad6b08 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -7,7 +7,7 @@ from .forms import ChargeForm, Addr2PoolForm from .. import db from ..email import send_email -from ..models import User, Transaction, Deployment, Service, Region, Address, Domain, contact_proxmaster +from ..models import User, Transaction, Deployment, Service, Region, Bridge, Router, Address, Domain, contact_proxmaster from ..decorators import admin_required, permission_required import base64 @@ -70,7 +70,8 @@ def list_recyclebin(): @admin_required def list_addresses(): alladdresses = Address.query.order_by(Address.ip.asc()).all() - return render_template('admin/list_addresses.html', addresses=alladdresses) + allrouters = Router.query.all() + return render_template('admin/list_addresses.html', addresses=alladdresses, routers=allrouters) @admin.route("/addr2pool", methods=['GET', 'POST']) @fresh_login_required @@ -156,27 +157,28 @@ def dashboard(user_pid=0): inv_deploycubeids = [] inv_deployments_list = [] for invcls in inv_deployments: - if invcls.user_id == cuser.pid: - inv_deploycubeids.extend([invcls.machine_id]) - inv_deployments_list.extend([invcls.machine_alias]) + inv_deploycubeids.extend([invcls.machine_id]) + inv_deployments_list.extend([invcls.machine_alias]) inv_services = cuser.inv_services.filter_by(deleted=False).order_by(Service.date_last_charge.asc()).all() inv_services_list = [] for invcls in inv_services: - if invcls.user_id == cuser.pid: - inv_services_list.extend([invcls.description]) + inv_services_list.extend([invcls.description]) inv_domains = cuser.inv_domains.filter_by(deleted=False).order_by(Domain.date_created.desc()).all() inv_domains_list = [] for invcls in inv_domains: - if invcls.user_id == cuser.pid: - inv_domains_list.extend([invcls.fqdn]) + inv_domains_list.extend([invcls.fqdn]) inv_addresses = cuser.inv_addresses.order_by(Address.ip.asc()).all() inv_addresses_list = [] for invcls in inv_addresses: - if invcls.user_id == cuser.pid: - inv_addresses_list.extend([invcls.ip]) + inv_addresses_list.extend([invcls.ip]) + + inv_bridges = cuser.inv_bridges.order_by(Bridge.bridge_id.asc()).all() + inv_bridges_list = [] + for invcls in inv_bridges: + inv_bridges_list.extend([invcls.bridge_id]) sys_regions = Region.query.all() regions = {} @@ -202,6 +204,7 @@ def dashboard(user_pid=0): rrd[unit_id][graph] = base64.b64encode(raw).decode() status = { unit_id : query['status'] } statuses.update(status) - return render_template('main/dashboard.html', rrd=rrd, status=statuses, inv_deployments=inv_deployments, inv_services=inv_services, inv_domains=inv_domains, inv_addresses=inv_addresses, region=regions) + current_app.logger.info('[{}] Enabled deployments: {}, services: {}, domains: {}, bridges: {}, addresses: {}'.format(cuser.email, inv_deployments_list, inv_services_list, inv_domains_list, inv_bridges_list, inv_addresses_list)) + return render_template('main/dashboard.html', rrd=rrd, status=statuses, inv_deployments=inv_deployments, inv_services=inv_services, inv_domains=inv_domains, inv_bridges=inv_bridges, inv_addresses=inv_addresses, region=regions) diff --git a/app/auth/routes.py b/app/auth/routes.py index 647916b..8f85ca4 100644 --- a/app/auth/routes.py +++ b/app/auth/routes.py @@ -69,8 +69,9 @@ def login(): user.last_ip = lastip db.session.add(user) db.session.commit() - #send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip ) - flash('Last Login: {} from {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"), previp)) + send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip ) + #flash('Last Login: {} from {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"), previp)) + flash('Last Login: {}'.format(user.last_seen.strftime("%a %d %B %Y %H:%M"))) return redirect(request.args.get('next') or url_for('main.dashboard')) else: flash('Invalid username or password.') diff --git a/app/main/routes.py b/app/main/routes.py index ade13c8..2770494 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -5,7 +5,7 @@ from flask_sqlalchemy import get_debug_queries from . import main from .. import db from ..email import send_email -from ..models import User, Permission, Deployment, Service, Region, Address, Domain, contact_proxmaster +from ..models import User, Permission, Deployment, Service, Region, Address, Bridge, Router, Domain, contact_proxmaster import base64 @@ -58,33 +58,15 @@ def market(group_id=0): @login_required def dashboard(): cuser = current_user - inv_deployments = cuser.inv_deployments.filter_by(deleted=False).order_by(Deployment.date_created.desc()).all() inv_deploycubeids = [] - inv_deployments_list = [] for invcls in inv_deployments: if invcls.user_id == cuser.pid: inv_deploycubeids.extend([invcls.machine_id]) - inv_deployments_list.extend([invcls.machine_alias]) - inv_services = cuser.inv_services.filter_by(deleted=False).order_by(Service.date_last_charge.asc()).all() - inv_services_list = [] - for invcls in inv_services: - if invcls.user_id == cuser.pid: - inv_services_list.extend([invcls.description]) - inv_domains = cuser.inv_domains.filter_by(deleted=False).order_by(Domain.date_created.desc()).all() - inv_domains_list = [] - for invcls in inv_domains: - if invcls.user_id == cuser.pid: - inv_domains_list.extend([invcls.fqdn]) - inv_addresses = cuser.inv_addresses.order_by(Address.ip.asc()).all() - inv_addresses_list = [] - for invcls in inv_addresses: - if invcls.user_id == cuser.pid: - inv_addresses_list.extend([invcls.ip]) - + inv_bridges = cuser.inv_bridges.order_by(Bridge.bridge_id.asc()).all() sys_regions = Region.query.all() regions = {} for region in sys_regions: @@ -102,9 +84,9 @@ def dashboard(): query = contact_proxmaster(data, 'vmrrd') except Exception as e: current_app.logger.error(e) - flash('Deploy #{} unreachable. Support is notified'.format(str(unit_id))) + flash('Support is notified.'.format(str(unit_id))) send_email(current_app.config['MAIL_USERNAME'], 'Cube {} is unreachable'.format(unit_id), - 'vmanager/email/adm_unreachable', user=current_user, unit_id=unit_id) + 'vmanager/email/adm_unreachable', user=current_user, unit_id=unit_id, error=str(e)) #current_app.logger.info('debug query:') #current_app.logger.info(query) @@ -117,10 +99,8 @@ def dashboard(): statuses.update(status) except Exception as e: current_app.logger.error(e) - flash('Deploy #{} unreachable. Support is notified'.format(str(unit_id))) + flash('Support is notified.'.format(str(unit_id))) send_email(current_app.config['MAIL_USERNAME'], 'Cube {} is unreachable'.format(unit_id), - 'vmanager/email/adm_unreachable', user=current_user, unit_id=unit_id ) - - #current_app.logger.info('[{}] Enabled deployments: {}, services: {}, domains: {}, addresses: {}'.format(current_user.email, inv_deployments_list, inv_services_list, inv_domains_list, inv_addresses_list )) - return render_template('main/dashboard.html', rrd=rrd, status=statuses, inv_deployments=inv_deployments, inv_services=inv_services, inv_domains=inv_domains, inv_addresses=inv_addresses, region=regions) + 'vmanager/email/adm_unreachable', user=current_user, unit_id=unit_id, error=str(e)) + return render_template('main/dashboard.html', rrd=rrd, status=statuses, inv_bridges=inv_bridges, inv_deployments=inv_deployments, inv_services=inv_services, inv_domains=inv_domains, inv_addresses=inv_addresses, region=regions) diff --git a/app/models.py b/app/models.py index 014c8d9..73781ae 100644 --- a/app/models.py +++ b/app/models.py @@ -220,7 +220,8 @@ def contact_proxmaster(data, method): try: db_result = requests.post( url, data=data_json, headers={"content-type": "application/json"}, timeout=30 ) proxjson = db_result.json() - current_app.logger.info('grid> {}'.format(str(proxjson))) + if current_app.config['DEBUG'] == 1: + current_app.logger.info('API> {}'.format(str(proxjson))) return proxjson except: return { 'status': 'UNREACHABLE' } @@ -232,6 +233,8 @@ class Router(db.Model): date_created = db.Column(db.DateTime, default=datetime.utcnow) deleted = db.Column(db.Boolean, default=False) + inv_addresses = db.relationship('Address', backref='router', lazy='dynamic') + machine_id = db.Column(db.BigInteger) #unit_id class Bridge(db.Model): @@ -286,6 +289,8 @@ class Region(db.Model): pid = db.Column(db.Integer, primary_key=True) enabled = db.Column(db.Boolean) + inv_addresses = db.relationship('Address', backref='region', lazy='dynamic') + name = db.Column(db.String) description = db.Column(db.String) extraprice = db.Column(db.Float) @@ -294,11 +299,10 @@ class Address(db.Model): __tablename__ = 'address' pid = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK - date_assigned = db.Column(db.DateTime, default=datetime.utcnow) - enabled = db.Column(db.Boolean) - region_id = db.Column(db.Integer, db.ForeignKey('regions.pid')) #FK router_id = db.Column(db.Integer, db.ForeignKey('routers.pid')) #FK + date_assigned = db.Column(db.DateTime, default=datetime.utcnow) + enabled = db.Column(db.Boolean) ip = db.Column(db.String) mac = db.Column(db.String) diff --git a/app/templates/admin/list_addresses.html b/app/templates/admin/list_addresses.html index c397fff..860eea4 100644 --- a/app/templates/admin/list_addresses.html +++ b/app/templates/admin/list_addresses.html @@ -17,8 +17,10 @@ IP - MAC Addr. Reverse DNS + Region + Router + Owner @@ -26,8 +28,10 @@ {% if address.enabled == False %}{% else %}{% endif %} {{ address.ip }} - {{ address.mac }} {{ address.rdns }} + {{ address.region.name }} + {{ address.router.machine_id }} + {{ address.owner.email }} {% endfor %} diff --git a/app/templates/email/adm_logger.html b/app/templates/email/adm_logger.html new file mode 100644 index 0000000..13e0520 --- /dev/null +++ b/app/templates/email/adm_logger.html @@ -0,0 +1,6 @@ +

{{ user.email }}.
+
+{{ content }}
+

+

Regards, +Proxadmin

diff --git a/app/templates/email/adm_logger.txt b/app/templates/email/adm_logger.txt new file mode 100644 index 0000000..91a289b --- /dev/null +++ b/app/templates/email/adm_logger.txt @@ -0,0 +1,6 @@ +User {{ user.email }} + +{{ content }} + +Regards, +Proxadmin diff --git a/app/templates/main/dashboard.html b/app/templates/main/dashboard.html index 3139043..8a4790a 100644 --- a/app/templates/main/dashboard.html +++ b/app/templates/main/dashboard.html @@ -26,25 +26,25 @@ @media only screen and (max-width: 768px) { /* Force table to not be like tables anymore */ - #no-more-tables table, - #no-more-tables thead, - #no-more-tables tbody, - #no-more-tables th, - #no-more-tables td, - #no-more-tables tr { + .no-more-tables table, + .no-more-tables thead, + .no-more-tables tbody, + .no-more-tables th, + .no-more-tables td, + .no-more-tables tr { display: block; } /* Hide table headers (but not display: none;, for accessibility) */ - #no-more-tables thead tr { + .no-more-tables thead tr { position: absolute; top: -9999px; left: -9999px; } - #no-more-tables tr { border: 1px solid #ccc; } + .no-more-tables tr { border: 1px solid #ccc; } - #no-more-tables td { + .no-more-tables td { /* Behave like a "row" */ border: none; border-bottom: 1px solid #eee; @@ -54,23 +54,23 @@ text-align:left; } - #no-more-tables td:before { + .no-more-tables td:before { /* Now like a table header */ - position: absolute; + /* position: absolute; */ /* Top/left values mimic padding */ top: 6px; left: 6px; width: 45%; padding-right: 10px; white-space: nowrap; - text-align:left; + text-align: left; font-weight: bold; } /* Label the data */ - #no-more-tables td:before { content: attr(data-title); } + .no-more-tables td:before { content: attr(data-title); } } {% endblock %} @@ -233,7 +233,7 @@ addEventListener("DOMContentLoaded", function() {

- ID: {{ deploy.machine_id }}
+ Unit: {{ deploy.machine_id }}
State: {{ status[deploy.machine_id] }}
Protected: {{ deploy.protected }}

@@ -261,7 +261,7 @@ addEventListener("DOMContentLoaded", function() {
Domains
-
+
@@ -304,29 +304,51 @@ addEventListener("DOMContentLoaded", function() {
Communications

-

+ Private
+
+
+ + + + + + + + {% for bridge in inv_bridges %} + + + + + {% endfor %} + +
UnitNetwork
{{ bridge.bridge_id }}192.168.9.0
+
+ + Public
+
- - + + {% for address in inv_addresses %} - - {% endfor %} - + {% endfor %} +
IP RegionMAC Addr. Reverse DNS
{{ address.ip }} {{ region[address.region_id] }}{{ address.mac }} {{ address.rdns }}
- - + + + +
diff --git a/app/templates/vmanager/email/adm_unreachable.html b/app/templates/vmanager/email/adm_unreachable.html index 52abd1f..1e2ad65 100644 --- a/app/templates/vmanager/email/adm_unreachable.html +++ b/app/templates/vmanager/email/adm_unreachable.html @@ -1,5 +1,7 @@

{{ user.email }} encountered an error working with id: {{ unit_id }}

+debug: +{{ error }}

-

Regards, +

Regards,
Proxadmin

diff --git a/app/templates/vmanager/email/adm_unreachable.txt b/app/templates/vmanager/email/adm_unreachable.txt index dbb7ddd..ad94add 100644 --- a/app/templates/vmanager/email/adm_unreachable.txt +++ b/app/templates/vmanager/email/adm_unreachable.txt @@ -1,4 +1,7 @@ User {{ user.email }} encountered an error working with id: {{ unit_id }} +debug: +{{ error }} + Regards, Proxadmin diff --git a/app/vmanager/routes.py b/app/vmanager/routes.py index f7c78b7..2222d3c 100644 --- a/app/vmanager/routes.py +++ b/app/vmanager/routes.py @@ -15,6 +15,7 @@ import random from datetime import datetime, timedelta, date, time from dateutil.relativedelta import relativedelta import ast +import time def randstr(n): return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(n)) @@ -166,48 +167,45 @@ def activate(itemid=0): #TODO: Filter bridges for the selected region only. switch should return slave name selected_bridge = owner.inv_bridges.filter_by(deleted=False).first() if selected_bridge is None: - flash('No bridge created yet. Cannot activate.') - return redirect(url_for('main.dashboard')) + flash('No private network found.') else: #bridge found. lets see on which slave it is so we can create the instance on the same slave. data = { 'unit_id': int(selected_bridge.bridge_id), 'type': 'br' } query = contact_proxmaster(data, 'query') if query['status'] == 'query_success': + #TODO: selected random ip address from the pool. + selected_ip = '87.120.110.41' #machine will be installed where the switch physically is region_name = query['region'] slave_name = query['slave'] bridge_phy_id = query['phy_id'] + data = { 'clientid': str(owner.pid), + 'clientemail': str(owner.email), + 'hostname': 'c' + str(owner.pid) + '-r' + selected_ip, + 'region': str(region_name), + 'slave': str(slave_name), + 'type': 'lxc', + 'cpu': '1', + 'mem': '256', + 'hdd': '1', + 'net0if': 'vmbr' + str(bridge_phy_id), + 'net0ip': '192.168.9.1', + 'net0mask': '24', + 'net1if': 'vmbr0', + 'net1ip': selected_ip, + 'net1mask': '24', + 'net1gw': '87.120.110.1' #should be queried from the current region + } + query = contact_proxmaster(data, 'create') + if query['status'] == 'lxc_created': + router = Router(user_id=int(owner.pid), machine_id=query['unit_id']) + db.session.add(router) + db.session.commit() else: - flash('Point found but cannot be used!') + flash('Router cannot be created.') return redirect(url_for('main.dashboard')) - #no router. creating... - data = { 'clientid': str(owner.pid), - 'clientemail': str(owner.email), - 'hostname': 'c' + str(owner.pid) + '-rt' + str(selected_address.ip), - 'region': str(region_name), - 'slave': str(slave_name), - 'type': 'lxc', - 'cpu': '1', - 'mem': '128', - 'hdd': '1', - 'net0if': 'vmbr' + bridge_phy_id, - 'net0ip': '192.168.9.1', - 'net1if': 'vmbr0', - 'net1ip': str(selected_address.ip), - 'net1gw': '87.120.110.1' #should be queried from the current region - } - try: - query = contact_proxmaster(data, 'create') - 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(owner.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 @@ -226,7 +224,7 @@ def activate(itemid=0): owner.wallet = owner.wallet - total db.session.commit() flash('Deployment {} activated for {} month(s)'.format(str(deploy.machine_alias), form.period.data)) - if owner.is_administrator: + if current_user.is_administrator(): return redirect(url_for('admin.list_deployments')) else: return redirect(url_for('main.dashboard')) @@ -241,13 +239,19 @@ def remove(unit_id=0): if current_user.is_administrator(): if deploy.protected is not True: try: + query = contact_proxmaster(data, 'status') + if query['status'] == 'running': + query = contact_proxmaster(data, 'stop') + flash('Machine {} force stopped'.format(unit_id)) + time.sleep(7) query = contact_proxmaster(data, 'remove') flash('Machine {} terminated'.format(unit_id)) deploy.deleted = True deploy.enabled = False deploy.warning = False db.session.commit() - except: + except Exception as e: + current_app.logger.error(e) flash('Cannot delete machine {}'.format(unit_id)) return redirect(url_for('admin.list_recyclebin')) else: diff --git a/cronexec.sh b/cronexec.sh index be99172..c81c7d5 100755 --- a/cronexec.sh +++ b/cronexec.sh @@ -1,4 +1,9 @@ #!/bin/bash + +# cronjob manager + +echo "_.··¸.-~*¨¯¨*·~-.,-( proxmaster )-,.-~*¨¯¨*·~-.¸··._" + scriptdir=`dirname $0` cd $scriptdir /bin/bash -c "source ../bin/activate; python3 manage.py autodisable ; python3 manage.py autowarn ; python3 manage.py autoremove" diff --git a/manage.py b/manage.py index ac77f57..fed64d5 100644 --- a/manage.py +++ b/manage.py @@ -6,6 +6,7 @@ from datetime import date, time, datetime from dateutil.relativedelta import relativedelta from app import app, db +from app.email import send_email from flask_script import Manager, Shell, Command from flask_migrate import Migrate, MigrateCommand @@ -40,13 +41,15 @@ def deploy(): def autoremove(): from app.models import User, Deployment today = datetime.utcnow() - print('\nScan for unprotected deployments, lower their days left by 1 and autodelete them if expired. Script Started at {}'.format(today)) + print('\n[{}] Scan for unprotected deployments, lower their days left by 1 and autodelete them if expired:'.format(today.replace(microsecond=0))) drafts = Deployment.query.filter_by(deleted=False).filter_by(protected=False).all() for draft in drafts: daysleft = draft.daysleft daysleft -= 1 draft.daysleft = daysleft print('Draft {} will be autoremoved after {} days.'.format(draft.machine_alias, daysleft)) + email_content = draft.owner + ' draft days left: ' + daysleft + send_email(app.config['MAIL_USERNAME'], str(email_content), 'email/adm_logger', user=user, content=str(email_content)) db.session.commit() @manager.command @@ -54,7 +57,7 @@ def autodisable(): from app.models import User, Deployment, Service, Domain from sqlalchemy import and_, or_, not_ today = datetime.utcnow() - print('\nScan for active expired items and set them as inactive. Script started at {}'.format(today)) + print('\n[{}] Scan for active expired items and set them as inactive:'.format(today.replace(microsecond=0))) dep_c = 0 srv_c = 0 dom_c = 0 @@ -100,7 +103,7 @@ def autodisable(): def autowarn(): from app.models import User, Deployment, Service, Domain, Transaction today = datetime.utcnow() - print('\nScan for items that will expire soon and enable the warning flag. Script started at {}'.format(today)) + print('\n[{}] Scan for enabled and protected deployments that will expire soon and enable the warning flag:'.format(today.replace(microsecond=0))) deployments_ena = Deployment.query.filter_by(deleted=False).filter_by(enabled=True).filter_by(protected=True).all() for deploy in deployments_ena: lastcharge = deploy.date_last_charge @@ -114,6 +117,7 @@ def autowarn(): deploy.warning = True db.session.commit() + print('\n[{}] Scan for enabled services that will expire soon and enable the warning flag:'.format(today.replace(microsecond=0))) services_ena = Service.query.filter_by(deleted=False).filter_by(enabled=True).all() for service in services_ena: lastcharge = service.date_last_charge diff --git a/start.wsgi b/start.wsgi index 108f21f..b0a4787 100644 --- a/start.wsgi +++ b/start.wsgi @@ -7,10 +7,10 @@ import site site.addsitedir('/home/proxadmin/appserver/lib/python3.5/site-packages') #activate virtualenv -#using libapache2-mod-wsgi ... +#using libapache2-mod-wsgi: #activate_this = '/home/proxadmin/appserver/bin/activate_this.py' #execfile(activate_this, dict(__file__=activate_this)) -#... or using libapache2-mod-wsgi-py3 +#... or using libapache2-mod-wsgi-py3: activate_this = '/home/proxadmin/appserver/bin/activate_this.py' with open(activate_this) as file_: exec(file_.read(), dict(__file__=activate_this))