create-activate phase 3

This commit is contained in:
deflax 2017-12-15 01:00:02 +02:00
parent 9c085f4561
commit 860eccd159
15 changed files with 155 additions and 112 deletions

View file

@ -12,8 +12,8 @@ from werkzeug.contrib.fixers import ProxyFix
from config import config from config import config
app = Flask(__name__) app = Flask(__name__)
app.config.from_object(config['default']) app.config.from_object(config['dev'])
config['default'].init_app(app) config['dev'].init_app(app)
app.wsgi_app = ProxyFix(app.wsgi_app) app.wsgi_app = ProxyFix(app.wsgi_app)
db = SQLAlchemy(session_options = { "autoflush": False }) db = SQLAlchemy(session_options = { "autoflush": False })
@ -76,8 +76,7 @@ class CustomJSONEncoder(JSONEncoder):
app.json_encoder = CustomJSONEncoder app.json_encoder = CustomJSONEncoder
#TODO: if app.debug: if app.config['DEBUG'] == 1:
if not app.debug:
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
file_handler = RotatingFileHandler('/home/proxadmin/appserver/proxadmin/log/proxadmin.log', 'a', 1 * 1024 * 1024, 10) 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.request_time = lambda: '%.5fs' % (time.time() - g.request_start_time)
# g.pjax = 'X-PJAX' in request.headers # 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 import logging
from logging.handlers import SMTPHandler from logging.handlers import SMTPHandler
credentials = None credentials = None

View file

@ -7,7 +7,7 @@ from .forms import ChargeForm, Addr2PoolForm
from .. import db from .. import db
from ..email import send_email 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 from ..decorators import admin_required, permission_required
import base64 import base64
@ -70,7 +70,8 @@ def list_recyclebin():
@admin_required @admin_required
def list_addresses(): def list_addresses():
alladdresses = Address.query.order_by(Address.ip.asc()).all() 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']) @admin.route("/addr2pool", methods=['GET', 'POST'])
@fresh_login_required @fresh_login_required
@ -156,28 +157,29 @@ def dashboard(user_pid=0):
inv_deploycubeids = [] inv_deploycubeids = []
inv_deployments_list = [] inv_deployments_list = []
for invcls in inv_deployments: for invcls in inv_deployments:
if invcls.user_id == cuser.pid:
inv_deploycubeids.extend([invcls.machine_id]) inv_deploycubeids.extend([invcls.machine_id])
inv_deployments_list.extend([invcls.machine_alias]) 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 = cuser.inv_services.filter_by(deleted=False).order_by(Service.date_last_charge.asc()).all()
inv_services_list = [] inv_services_list = []
for invcls in inv_services: 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 = cuser.inv_domains.filter_by(deleted=False).order_by(Domain.date_created.desc()).all()
inv_domains_list = [] inv_domains_list = []
for invcls in inv_domains: 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 = cuser.inv_addresses.order_by(Address.ip.asc()).all()
inv_addresses_list = [] inv_addresses_list = []
for invcls in inv_addresses: 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() sys_regions = Region.query.all()
regions = {} regions = {}
for region in sys_regions: for region in sys_regions:
@ -202,6 +204,7 @@ def dashboard(user_pid=0):
rrd[unit_id][graph] = base64.b64encode(raw).decode() rrd[unit_id][graph] = base64.b64encode(raw).decode()
status = { unit_id : query['status'] } status = { unit_id : query['status'] }
statuses.update(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)

View file

@ -69,8 +69,9 @@ def login():
user.last_ip = lastip user.last_ip = lastip
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
#send_email(current_app.config['MAIL_USERNAME'], user.email + ' logged in.', 'auth/email/adm_loginnotify', user=user, ipaddr=lastip ) 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: {} 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')) return redirect(request.args.get('next') or url_for('main.dashboard'))
else: else:
flash('Invalid username or password.') flash('Invalid username or password.')

View file

@ -5,7 +5,7 @@ from flask_sqlalchemy import get_debug_queries
from . import main from . import main
from .. import db from .. import db
from ..email import send_email 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 import base64
@ -58,33 +58,15 @@ def market(group_id=0):
@login_required @login_required
def dashboard(): def dashboard():
cuser = current_user cuser = current_user
inv_deployments = cuser.inv_deployments.filter_by(deleted=False).order_by(Deployment.date_created.desc()).all() inv_deployments = cuser.inv_deployments.filter_by(deleted=False).order_by(Deployment.date_created.desc()).all()
inv_deploycubeids = [] inv_deploycubeids = []
inv_deployments_list = []
for invcls in inv_deployments: for invcls in inv_deployments:
if invcls.user_id == cuser.pid: if invcls.user_id == cuser.pid:
inv_deploycubeids.extend([invcls.machine_id]) 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 = 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 = 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 = cuser.inv_addresses.order_by(Address.ip.asc()).all()
inv_addresses_list = [] inv_bridges = cuser.inv_bridges.order_by(Bridge.bridge_id.asc()).all()
for invcls in inv_addresses:
if invcls.user_id == cuser.pid:
inv_addresses_list.extend([invcls.ip])
sys_regions = Region.query.all() sys_regions = Region.query.all()
regions = {} regions = {}
for region in sys_regions: for region in sys_regions:
@ -102,9 +84,9 @@ def dashboard():
query = contact_proxmaster(data, 'vmrrd') query = contact_proxmaster(data, 'vmrrd')
except Exception as e: except Exception as e:
current_app.logger.error(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), 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('debug query:')
#current_app.logger.info(query) #current_app.logger.info(query)
@ -117,10 +99,8 @@ def dashboard():
statuses.update(status) statuses.update(status)
except Exception as e: except Exception as e:
current_app.logger.error(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), 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))
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)
#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)

View file

@ -220,7 +220,8 @@ def contact_proxmaster(data, method):
try: try:
db_result = requests.post( url, data=data_json, headers={"content-type": "application/json"}, timeout=30 ) db_result = requests.post( url, data=data_json, headers={"content-type": "application/json"}, timeout=30 )
proxjson = db_result.json() 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 return proxjson
except: except:
return { 'status': 'UNREACHABLE' } return { 'status': 'UNREACHABLE' }
@ -232,6 +233,8 @@ class Router(db.Model):
date_created = db.Column(db.DateTime, default=datetime.utcnow) date_created = db.Column(db.DateTime, default=datetime.utcnow)
deleted = db.Column(db.Boolean, default=False) deleted = db.Column(db.Boolean, default=False)
inv_addresses = db.relationship('Address', backref='router', lazy='dynamic')
machine_id = db.Column(db.BigInteger) #unit_id machine_id = db.Column(db.BigInteger) #unit_id
class Bridge(db.Model): class Bridge(db.Model):
@ -286,6 +289,8 @@ class Region(db.Model):
pid = db.Column(db.Integer, primary_key=True) pid = db.Column(db.Integer, primary_key=True)
enabled = db.Column(db.Boolean) enabled = db.Column(db.Boolean)
inv_addresses = db.relationship('Address', backref='region', lazy='dynamic')
name = db.Column(db.String) name = db.Column(db.String)
description = db.Column(db.String) description = db.Column(db.String)
extraprice = db.Column(db.Float) extraprice = db.Column(db.Float)
@ -294,11 +299,10 @@ class Address(db.Model):
__tablename__ = 'address' __tablename__ = 'address'
pid = db.Column(db.Integer, primary_key=True) pid = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK 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 region_id = db.Column(db.Integer, db.ForeignKey('regions.pid')) #FK
router_id = db.Column(db.Integer, db.ForeignKey('routers.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) ip = db.Column(db.String)
mac = db.Column(db.String) mac = db.Column(db.String)

View file

@ -17,8 +17,10 @@
<thead> <thead>
<tr> <tr>
<th>IP</th> <th>IP</th>
<th>MAC Addr.</th>
<th>Reverse DNS</th> <th>Reverse DNS</th>
<th>Region</th>
<th>Router</th>
<th>Owner</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -26,8 +28,10 @@
<tr> <tr>
{% if address.enabled == False %}<tr class="danger">{% else %}<tr>{% endif %} {% if address.enabled == False %}<tr class="danger">{% else %}<tr>{% endif %}
<td>{{ address.ip }}</td> <td>{{ address.ip }}</td>
<td>{{ address.mac }}</td>
<td>{{ address.rdns }}</td> <td>{{ address.rdns }}</td>
<td>{{ address.region.name }}</td>
<td>{{ address.router.machine_id }}</td>
<td>{{ address.owner.email }}</td>
{% endfor %} {% endfor %}
</tr> </tr>
</tbody> </tbody>

View file

@ -0,0 +1,6 @@
<p>{{ user.email }}.<br />
<br />
{{ content }}<br />
</p>
<p>Regards,
Proxadmin</p>

View file

@ -0,0 +1,6 @@
User {{ user.email }}
{{ content }}
Regards,
Proxadmin

View file

@ -26,25 +26,25 @@
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
/* Force table to not be like tables anymore */ /* Force table to not be like tables anymore */
#no-more-tables table, .no-more-tables table,
#no-more-tables thead, .no-more-tables thead,
#no-more-tables tbody, .no-more-tables tbody,
#no-more-tables th, .no-more-tables th,
#no-more-tables td, .no-more-tables td,
#no-more-tables tr { .no-more-tables tr {
display: block; display: block;
} }
/* Hide table headers (but not display: none;, for accessibility) */ /* Hide table headers (but not display: none;, for accessibility) */
#no-more-tables thead tr { .no-more-tables thead tr {
position: absolute; position: absolute;
top: -9999px; top: -9999px;
left: -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" */ /* Behave like a "row" */
border: none; border: none;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
@ -54,9 +54,9 @@
text-align:left; text-align:left;
} }
#no-more-tables td:before { .no-more-tables td:before {
/* Now like a table header */ /* Now like a table header */
position: absolute; /* position: absolute; */
/* Top/left values mimic padding */ /* Top/left values mimic padding */
top: 6px; top: 6px;
left: 6px; left: 6px;
@ -70,7 +70,7 @@
/* /*
Label the data Label the data
*/ */
#no-more-tables td:before { content: attr(data-title); } .no-more-tables td:before { content: attr(data-title); }
} }
</style> </style>
{% endblock %} {% endblock %}
@ -233,7 +233,7 @@ addEventListener("DOMContentLoaded", function() {
<div id="misc{{ deploy.machine_id }}" class="tab-pane fade"> <div id="misc{{ deploy.machine_id }}" class="tab-pane fade">
<br /> <br />
<p> <p>
ID: {{ deploy.machine_id }}<br /> Unit: {{ deploy.machine_id }}<br />
State: {{ status[deploy.machine_id] }}<br /> State: {{ status[deploy.machine_id] }}<br />
Protected: {{ deploy.protected }}<br /> Protected: {{ deploy.protected }}<br />
</p> </p>
@ -261,7 +261,7 @@ addEventListener("DOMContentLoaded", function() {
<div class="panel panel-info" id="domains"> <div class="panel panel-info" id="domains">
<div class="panel-heading">Domains</div> <div class="panel-heading">Domains</div>
<div class="panel-body"> <div class="panel-body">
<div id="no-more-tables"> <div class="no-more-tables">
<table class="table table-hover table-striped table-condensed cf"> <table class="table table-hover table-striped table-condensed cf">
<thead> <thead>
<tr> <tr>
@ -304,29 +304,51 @@ addEventListener("DOMContentLoaded", function() {
<div class="panel panel-info" id="addresses"> <div class="panel panel-info" id="addresses">
<div class="panel-heading">Communications</div> <div class="panel-heading">Communications</div>
<div class="panel-body"><p> <div class="panel-body"><p>
<div id="no-more-tables"> <img width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALnSURBVGhD7ZrPaxNBFMcXRK/q3+JVEKS7G6kWUVP/A+v/IFgQmpm00R7Ve/2RoiB4EEHag3ZnlR4LRtMqgndb8aTF9X0nbw/qxpnRTTIu+4FHmdk3895350eSmQY1Qzi1qNZmrr988SeDD7v7SyxVdvVhP7vx9EOh4Rl82N1fkOSz3l72fvd7oeFZLaQMmvNbh2KZzEYiuRcJ1YtF8gUJFZmNkEKjPtF3JNVdxEJMDl8OoUwvUIDtSCZ7CBKJ9FLU3jhNgad+M0rISkhBW92nTOb0y6JY5NenuOc5jb+nubp6gAIskX0lAQsnlteP8KOh2Aph96EgFsUV5PsNOSAXfuQOvZ0O2W4o0pNcZaQsITkYKeRAL3KRq9zAdMJIuIgAZQsBEENTbJ+m3lmusoMX9g6GlqusQZI2xu7WYESwTo/d3jzIVWailrqIxTYlNw9zlTV6KlgYu1uDNYOcGiJpcpUZvTORcdEbaJbcj4Va4aIZUv6GGs1x0RuQE3Ljohmai59DkZzhojcgJ+TGRTNYjA2pjnPRG5CT00ZRCxkxtRAueoNRSKOtEjiYbJzi8qRNhty5SRBMd9JXVx68zZ5sfRpqutEEhBTlktu1RzsZcucmAyHL9Hu66EtebpMSUpRLbjfXP9ZCaiGu1EIqI6QS229lPhB/RTuMMWlbcnFcNFMLGTG1EC56g7OQyhw+eHsc1Eouk5AeF83EQt3B0T4XvYFEdJ0O6Gg0Zn07Mp0Wz48iJxyuc5UZHGKT+m0SJLnKGixGG2N3a0j8ErXrOx1iA2p0jsTs+3CtELbSCLnEbTXDVW4M3oK+ZAm5ykjZQiBC5yBUm6vcwXUX7iUosL7+GvvVm0w6GAmI+KertxzcFFHwPhYbddrFNog9PV+4P5mlkKK2us/BFttFLMQs/fMMGwAuWbD9UYDXFHgk19P0l/pWK4hV+vW0C0jIRgi7+0ulhCw8fpfdot/TRYZn/4WQyvyb02QIgh+ETy3CcS71GAAAAABJRU5ErkJggg=="> Private<br />
<div id="bridges" class="no-more-tables">
<table class="table table-hover table-striped table-condensed cf">
<thead>
<tr>
<th>Unit</th>
<th>Network</th>
</tr>
</thead>
<tbody>
{% for bridge in inv_bridges %}
<tr>
<td data-title="Unit">{{ bridge.bridge_id }}</td>
<td data-title="Network">192.168.9.0</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<img width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAEW0lEQVRYhe3YT0zbVhwH8HfgwKGHHnrYYYcddkBVT7t0kybNh8kvgTiBJlTdhCba0R03qVo3NBUtUkv88sdOgtapYu0mFQ1tY4BGK9qKaZmYkud/BFzKyBYYGmgRNCGBjf+ovB0SVyklJHEM7aR9pafIVmJ//Ht5z34G4P8AAJHQDxHegm48bkJCj4nFzZQzdPRZux4nByT5jUYRGbK4xZATmFhM1XmFXsoZqtJ7DMoZOkK7IjWQxS0Q4aE87FcVVdPE4pdsnJQ816muWznxViXIXcdthm4hk0PO6EJSzlB1PS/9cX04kYwlt8m7nWr6dFD5qVwkREI/jfBa9jPSSjlDRwAAwOwWXoQI/6JVsmyg2YM/uvD15N8zSztkZmmHxJLb5L0b6lq5ldzjPxiiUfgMAACYXOHXIItViPAWdIXPloyjnKGjFq+4oiY2iQbUkHoqyfiUY7QrYoEIh3LIbbNbeBWAXHdn981p1S0ae0DmP/5mcj4fVykyd+FVJiRczoEmKWeoGgAANLgJhZtKvGIxNTy18hSu0u7WooFoFPkQAABoFL6U3cZdRX9Mt4dPnO4YyRTClVPJWq9ykuHlGMPLMRMSXn8MZAU7RJhAt9ANAAC0O+zQ5seiQCsntbX1xVPFgKUgrbwS//ROirQNJomVV6a1/WbX8PFcNy9lt4Xj2S7Ga0WBjR3K3R4lWRSXjzx/4z6xeEWya7QShpPJXkAAsqPbhISeQtsF4wgq6lBsuWTgfpU0e6Q3LD6JMJwchyx+s+jJS4mNl+aVufWygPshIcLEEJgWq09MR//aKBtYaHQbDmzwywk9FSxUScOBjqCi3vt1STdwN9JwoN0vD3SLCxUB87vb4hWJUU9BAAAAGjtGLl76/veiE3WpyLOdY0TPbbFgIBt52cqJ60YAS5nMdaWeFxfKnQsPFfn2ZyPtH9ycWDQKaDiScoaqGU5c3u+J5pkjzR7h3PtdE8tGAvNHd8VrHMoZqmoMKqP+e7MPDwJpSCUZn3KsnpcWeqPJjecWCT34FYYTdwbUtKFADXn+C3XNwol9uoH24AjfdO1++q2ro6TjxzlDgX3R5GqDX868cy3q0IWjXZGaWo+4/t34Bumd2CItX06QC92TpNLRrSY2ibM/vmnjpFnaFanRXT0bL09eGUxkBqd2yODUDrkdf0TYuwli5UTS+u1vD8uFqolNcuWH6bTFK643XY1er+i1RwMvXzzz+dji7fgjogG1BhEmFo9wmfGJaUdQXnXdmt4aUNPk5/g/RHtUG5/fItKfa+TOgwwJDs1uN3eOZWo94gbjE27WeqQXdMMAyL6WqPOKK13R1adwGlD7Lt0ePmH24E/sAQWf8stxGyclIcKE8YnL9bw0eyogR+s8gtfEYsqwe3GDXxlu7Z1J7YXbDTyU2ALKSXtAju1ele3X7IEn17oHmsYOJd4/uljWH743miKO4JNLyQMLRFjXdHFoXf2fAOpthwJ8XvMve9hz7NcDU4IAAAAASUVORK5CYII="> Public<br />
<div id="routers" class="no-more-tables">
<table class="table table-hover table-striped table-condensed cf"> <table class="table table-hover table-striped table-condensed cf">
<thead> <thead>
<tr> <tr>
<th>IP</th> <th>IP</th>
<th>Region</th> <th>Region</th>
<th>MAC Addr.</th>
<th>Reverse DNS</th> <th>Reverse DNS</th>
</tr> </tr>
</thead>
<tbody> <tbody>
{% for address in inv_addresses %} {% for address in inv_addresses %}
<tr> <tr>
<td data-title="IP">{{ address.ip }}</td> <td data-title="IP">{{ address.ip }}</td>
<td data-title="Region">{{ region[address.region_id] }}</td> <td data-title="Region">{{ region[address.region_id] }}</td>
<td data-title="MAC">{{ address.mac }}</td>
<td data-title="RDNS">{{ address.rdns }}</td> <td data-title="RDNS">{{ address.rdns }}</td>
{% endfor %}
</tr> </tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<!-- GPS Signal icon by Icons8 -->
<img class="icon icons8-GPS-Signal" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAEW0lEQVRYhe3YT0zbVhwH8HfgwKGHHnrYYYcddkBVT7t0kybNh8kvgTiBJlTdhCba0R03qVo3NBUtUkv88sdOgtapYu0mFQ1tY4BGK9qKaZmYkud/BFzKyBYYGmgRNCGBjf+ovB0SVyklJHEM7aR9pafIVmJ//Ht5z34G4P8AAJHQDxHegm48bkJCj4nFzZQzdPRZux4nByT5jUYRGbK4xZATmFhM1XmFXsoZqtJ7DMoZOkK7IjWQxS0Q4aE87FcVVdPE4pdsnJQ816muWznxViXIXcdthm4hk0PO6EJSzlB1PS/9cX04kYwlt8m7nWr6dFD5qVwkREI/jfBa9jPSSjlDRwAAwOwWXoQI/6JVsmyg2YM/uvD15N8zSztkZmmHxJLb5L0b6lq5ldzjPxiiUfgMAACYXOHXIItViPAWdIXPloyjnKGjFq+4oiY2iQbUkHoqyfiUY7QrYoEIh3LIbbNbeBWAXHdn981p1S0ae0DmP/5mcj4fVykyd+FVJiRczoEmKWeoGgAANLgJhZtKvGIxNTy18hSu0u7WooFoFPkQAABoFL6U3cZdRX9Mt4dPnO4YyRTClVPJWq9ykuHlGMPLMRMSXn8MZAU7RJhAt9ANAAC0O+zQ5seiQCsntbX1xVPFgKUgrbwS//ROirQNJomVV6a1/WbX8PFcNy9lt4Xj2S7Ga0WBjR3K3R4lWRSXjzx/4z6xeEWya7QShpPJXkAAsqPbhISeQtsF4wgq6lBsuWTgfpU0e6Q3LD6JMJwchyx+s+jJS4mNl+aVufWygPshIcLEEJgWq09MR//aKBtYaHQbDmzwywk9FSxUScOBjqCi3vt1STdwN9JwoN0vD3SLCxUB87vb4hWJUU9BAAAAGjtGLl76/veiE3WpyLOdY0TPbbFgIBt52cqJ60YAS5nMdaWeFxfKnQsPFfn2ZyPtH9ycWDQKaDiScoaqGU5c3u+J5pkjzR7h3PtdE8tGAvNHd8VrHMoZqmoMKqP+e7MPDwJpSCUZn3KsnpcWeqPJjecWCT34FYYTdwbUtKFADXn+C3XNwol9uoH24AjfdO1++q2ro6TjxzlDgX3R5GqDX868cy3q0IWjXZGaWo+4/t34Bumd2CItX06QC92TpNLRrSY2ibM/vmnjpFnaFanRXT0bL09eGUxkBqd2yODUDrkdf0TYuwli5UTS+u1vD8uFqolNcuWH6bTFK643XY1er+i1RwMvXzzz+dji7fgjogG1BhEmFo9wmfGJaUdQXnXdmt4aUNPk5/g/RHtUG5/fItKfa+TOgwwJDs1uN3eOZWo94gbjE27WeqQXdMMAyL6WqPOKK13R1adwGlD7Lt0ePmH24E/sAQWf8stxGyclIcKE8YnL9bw0eyogR+s8gtfEYsqwe3GDXxlu7Z1J7YXbDTyU2ALKSXtAju1ele3X7IEn17oHmsYOJd4/uljWH743miKO4JNLyQMLRFjXdHFoXf2fAOpthwJ8XvMve9hz7NcDU4IAAAAASUVORK5CYII="> <!--<img width="32" height="32" src="data:image/png;base64,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"> No Public<br />-->
<!--<button class="btn btn-default" onclick="window.open('{{ url_for('main.dashboard') }}','_self')"><span class="glyphicon glyphicon-plus" aria-hiddent="true"></span> Assign</button> --> <!--<button class="btn btn-default" onclick="window.open('{{ url_for('main.dashboard') }}','_self')"><span class="glyphicon glyphicon-plus" aria-hiddent="true"></span> Assign</button> -->
</div> </div>
</div> </div>

View file

@ -1,5 +1,7 @@
<p>{{ user.email }} encountered an error working with id: {{ unit_id }}<br /> <p>{{ user.email }} encountered an error working with id: {{ unit_id }}<br />
<br /> <br />
debug:
{{ error }}
</p> </p>
<p>Regards, <p>Regards,<br />
Proxadmin</p> Proxadmin</p>

View file

@ -1,4 +1,7 @@
User {{ user.email }} encountered an error working with id: {{ unit_id }} User {{ user.email }} encountered an error working with id: {{ unit_id }}
debug:
{{ error }}
Regards, Regards,
Proxadmin Proxadmin

View file

@ -15,6 +15,7 @@ import random
from datetime import datetime, timedelta, date, time from datetime import datetime, timedelta, date, time
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import ast import ast
import time
def randstr(n): def randstr(n):
return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(n)) return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(n))
@ -166,47 +167,44 @@ def activate(itemid=0):
#TODO: Filter bridges for the selected region only. switch should return slave name #TODO: Filter bridges for the selected region only. switch should return slave name
selected_bridge = owner.inv_bridges.filter_by(deleted=False).first() selected_bridge = owner.inv_bridges.filter_by(deleted=False).first()
if selected_bridge is None: if selected_bridge is None:
flash('No bridge created yet. Cannot activate.') flash('No private network found.')
return redirect(url_for('main.dashboard'))
else: else:
#bridge found. lets see on which slave it is so we can create the instance on the same slave. #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), data = { 'unit_id': int(selected_bridge.bridge_id),
'type': 'br' } 'type': 'br' }
query = contact_proxmaster(data, 'query') query = contact_proxmaster(data, 'query')
if query['status'] == 'query_success': 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 #machine will be installed where the switch physically is
region_name = query['region'] region_name = query['region']
slave_name = query['slave'] slave_name = query['slave']
bridge_phy_id = query['phy_id'] bridge_phy_id = query['phy_id']
else:
flash('Point found but cannot be used!')
return redirect(url_for('main.dashboard'))
#no router. creating...
data = { 'clientid': str(owner.pid), data = { 'clientid': str(owner.pid),
'clientemail': str(owner.email), 'clientemail': str(owner.email),
'hostname': 'c' + str(owner.pid) + '-rt' + str(selected_address.ip), 'hostname': 'c' + str(owner.pid) + '-r' + selected_ip,
'region': str(region_name), 'region': str(region_name),
'slave': str(slave_name), 'slave': str(slave_name),
'type': 'lxc', 'type': 'lxc',
'cpu': '1', 'cpu': '1',
'mem': '128', 'mem': '256',
'hdd': '1', 'hdd': '1',
'net0if': 'vmbr' + bridge_phy_id, 'net0if': 'vmbr' + str(bridge_phy_id),
'net0ip': '192.168.9.1', 'net0ip': '192.168.9.1',
'net0mask': '24',
'net1if': 'vmbr0', 'net1if': 'vmbr0',
'net1ip': str(selected_address.ip), 'net1ip': selected_ip,
'net1mask': '24',
'net1gw': '87.120.110.1' #should be queried from the current region 'net1gw': '87.120.110.1' #should be queried from the current region
} }
try:
query = contact_proxmaster(data, 'create') query = contact_proxmaster(data, 'create')
except: if query['status'] == 'lxc_created':
flash('Region unreachable! Cannot create router. Please try again later...') router = Router(user_id=int(owner.pid), machine_id=query['unit_id'])
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.add(router)
db.session.commit() db.session.commit()
else:
flash('Router cannot be created.')
return redirect(url_for('main.dashboard'))
today = datetime.utcnow() today = datetime.utcnow()
expiry = today + relativedelta(today, months=+(form.period.data)) expiry = today + relativedelta(today, months=+(form.period.data))
@ -226,7 +224,7 @@ def activate(itemid=0):
owner.wallet = owner.wallet - total owner.wallet = owner.wallet - total
db.session.commit() db.session.commit()
flash('Deployment {} activated for {} month(s)'.format(str(deploy.machine_alias), form.period.data)) 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')) return redirect(url_for('admin.list_deployments'))
else: else:
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
@ -241,13 +239,19 @@ def remove(unit_id=0):
if current_user.is_administrator(): if current_user.is_administrator():
if deploy.protected is not True: if deploy.protected is not True:
try: 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') query = contact_proxmaster(data, 'remove')
flash('Machine {} terminated'.format(unit_id)) flash('Machine {} terminated'.format(unit_id))
deploy.deleted = True deploy.deleted = True
deploy.enabled = False deploy.enabled = False
deploy.warning = False deploy.warning = False
db.session.commit() db.session.commit()
except: except Exception as e:
current_app.logger.error(e)
flash('Cannot delete machine {}'.format(unit_id)) flash('Cannot delete machine {}'.format(unit_id))
return redirect(url_for('admin.list_recyclebin')) return redirect(url_for('admin.list_recyclebin'))
else: else:

View file

@ -1,4 +1,9 @@
#!/bin/bash #!/bin/bash
# cronjob manager
echo "_.··¸.-~*¨¯¨*·~-.,-( proxmaster )-,.-~*¨¯¨*·~-.¸··._"
scriptdir=`dirname $0` scriptdir=`dirname $0`
cd $scriptdir cd $scriptdir
/bin/bash -c "source ../bin/activate; python3 manage.py autodisable ; python3 manage.py autowarn ; python3 manage.py autoremove" /bin/bash -c "source ../bin/activate; python3 manage.py autodisable ; python3 manage.py autowarn ; python3 manage.py autoremove"

View file

@ -6,6 +6,7 @@ from datetime import date, time, datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from app import app, db from app import app, db
from app.email import send_email
from flask_script import Manager, Shell, Command from flask_script import Manager, Shell, Command
from flask_migrate import Migrate, MigrateCommand from flask_migrate import Migrate, MigrateCommand
@ -40,13 +41,15 @@ def deploy():
def autoremove(): def autoremove():
from app.models import User, Deployment from app.models import User, Deployment
today = datetime.utcnow() 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() drafts = Deployment.query.filter_by(deleted=False).filter_by(protected=False).all()
for draft in drafts: for draft in drafts:
daysleft = draft.daysleft daysleft = draft.daysleft
daysleft -= 1 daysleft -= 1
draft.daysleft = daysleft draft.daysleft = daysleft
print('Draft {} will be autoremoved after {} days.'.format(draft.machine_alias, 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() db.session.commit()
@manager.command @manager.command
@ -54,7 +57,7 @@ def autodisable():
from app.models import User, Deployment, Service, Domain from app.models import User, Deployment, Service, Domain
from sqlalchemy import and_, or_, not_ from sqlalchemy import and_, or_, not_
today = datetime.utcnow() 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 dep_c = 0
srv_c = 0 srv_c = 0
dom_c = 0 dom_c = 0
@ -100,7 +103,7 @@ def autodisable():
def autowarn(): def autowarn():
from app.models import User, Deployment, Service, Domain, Transaction from app.models import User, Deployment, Service, Domain, Transaction
today = datetime.utcnow() 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() deployments_ena = Deployment.query.filter_by(deleted=False).filter_by(enabled=True).filter_by(protected=True).all()
for deploy in deployments_ena: for deploy in deployments_ena:
lastcharge = deploy.date_last_charge lastcharge = deploy.date_last_charge
@ -114,6 +117,7 @@ def autowarn():
deploy.warning = True deploy.warning = True
db.session.commit() 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() services_ena = Service.query.filter_by(deleted=False).filter_by(enabled=True).all()
for service in services_ena: for service in services_ena:
lastcharge = service.date_last_charge lastcharge = service.date_last_charge

View file

@ -7,10 +7,10 @@ import site
site.addsitedir('/home/proxadmin/appserver/lib/python3.5/site-packages') site.addsitedir('/home/proxadmin/appserver/lib/python3.5/site-packages')
#activate virtualenv #activate virtualenv
#using libapache2-mod-wsgi ... #using libapache2-mod-wsgi:
#activate_this = '/home/proxadmin/appserver/bin/activate_this.py' #activate_this = '/home/proxadmin/appserver/bin/activate_this.py'
#execfile(activate_this, dict(__file__=activate_this)) #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' activate_this = '/home/proxadmin/appserver/bin/activate_this.py'
with open(activate_this) as file_: with open(activate_this) as file_:
exec(file_.read(), dict(__file__=activate_this)) exec(file_.read(), dict(__file__=activate_this))