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
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

View file

@ -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)

View file

@ -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.')

View file

@ -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)

View file

@ -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)

View file

@ -17,8 +17,10 @@
<thead>
<tr>
<th>IP</th>
<th>MAC Addr.</th>
<th>Reverse DNS</th>
<th>Region</th>
<th>Router</th>
<th>Owner</th>
</tr>
</thead>
<tbody>
@ -26,8 +28,10 @@
<tr>
{% if address.enabled == False %}<tr class="danger">{% else %}<tr>{% endif %}
<td>{{ address.ip }}</td>
<td>{{ address.mac }}</td>
<td>{{ address.rdns }}</td>
<td>{{ address.region.name }}</td>
<td>{{ address.router.machine_id }}</td>
<td>{{ address.owner.email }}</td>
{% endfor %}
</tr>
</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) {
/* 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); }
}
</style>
{% endblock %}
@ -233,7 +233,7 @@ addEventListener("DOMContentLoaded", function() {
<div id="misc{{ deploy.machine_id }}" class="tab-pane fade">
<br />
<p>
ID: {{ deploy.machine_id }}<br />
Unit: {{ deploy.machine_id }}<br />
State: {{ status[deploy.machine_id] }}<br />
Protected: {{ deploy.protected }}<br />
</p>
@ -261,7 +261,7 @@ addEventListener("DOMContentLoaded", function() {
<div class="panel panel-info" id="domains">
<div class="panel-heading">Domains</div>
<div class="panel-body">
<div id="no-more-tables">
<div class="no-more-tables">
<table class="table table-hover table-striped table-condensed cf">
<thead>
<tr>
@ -304,29 +304,51 @@ addEventListener("DOMContentLoaded", function() {
<div class="panel panel-info" id="addresses">
<div class="panel-heading">Communications</div>
<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">
<thead>
<tr>
<th>IP</th>
<th>Region</th>
<th>MAC Addr.</th>
<th>Reverse DNS</th>
</tr>
<tbody>
</thead>
<tbody>
{% for address in inv_addresses %}
<tr>
<td data-title="IP">{{ address.ip }}</td>
<td data-title="Region">{{ region[address.region_id] }}</td>
<td data-title="MAC">{{ address.mac }}</td>
<td data-title="RDNS">{{ address.rdns }}</td>
{% endfor %}
</tr>
</tbody>
{% endfor %}
</tbody>
</table>
</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> -->
</div>
</div>

View file

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

View file

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

View file

@ -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:

View file

@ -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"

View file

@ -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

View file

@ -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))