create-activate phase 3
This commit is contained in:
parent
9c085f4561
commit
860eccd159
15 changed files with 155 additions and 112 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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.')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
6
app/templates/email/adm_logger.html
Normal file
6
app/templates/email/adm_logger.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<p>{{ user.email }}.<br />
|
||||
<br />
|
||||
{{ content }}<br />
|
||||
</p>
|
||||
<p>Regards,
|
||||
Proxadmin</p>
|
6
app/templates/email/adm_logger.txt
Normal file
6
app/templates/email/adm_logger.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
User {{ user.email }}
|
||||
|
||||
{{ content }}
|
||||
|
||||
Regards,
|
||||
Proxadmin
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
User {{ user.email }} encountered an error working with id: {{ unit_id }}
|
||||
|
||||
debug:
|
||||
{{ error }}
|
||||
|
||||
Regards,
|
||||
Proxadmin
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
10
manage.py
10
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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Reference in a new issue