craete seed function phase 3

This commit is contained in:
deflax 2017-08-01 14:21:22 +03:00
parent c970f0d82a
commit a5a594a980
11 changed files with 194 additions and 140 deletions

View file

@ -39,28 +39,37 @@ def index():
@login_required @login_required
@admin_required @admin_required
def list_deployments(): def list_deployments():
alldeployments = Deployment.query.order_by(Deployment.daysleft.asc()).all() alldeployments = Deployment.query.filter_by(cancelled=False).order_by(Deployment.daysleft.asc()).all()
return render_template('admin/list_deployments.html', deployments=alldeployments) return render_template('admin/list_deployments.html', deployments=alldeployments)
@admin.route("/listservices", methods=['GET']) @admin.route("/listservices", methods=['GET'])
@login_required @login_required
@admin_required @admin_required
def list_services(): def list_services():
allservices = Service.query.order_by(Service.daysleft.asc()).all() allservices = Service.query.filter_by(cancelled=False).order_by(Service.daysleft.asc()).all()
return render_template('admin/list_services.html', services=allservices) return render_template('admin/list_services.html', services=allservices)
@admin.route("/listdomains", methods=['GET']) @admin.route("/listdomains", methods=['GET'])
@login_required @login_required
@admin_required @admin_required
def list_domains(): def list_domains():
alldomains = Domain.query.order_by(Domain.daysleft.asc()).all() alldomains = Domain.query.filter_by(cancelled=False).order_by(Domain.daysleft.asc()).all()
return render_template('admin/list_domains.html', domains=alldomains) return render_template('admin/list_domains.html', domains=alldomains)
@admin.route("/listcancelled", methods=['GET'])
@login_required
@admin_required
def list_cancelled():
expdeployments = Deployment.query.filter_by(cancelled=True).all()
expservices = Service.query.filter_by(cancelled=True).all()
expdomains = Domain.query.filter_by(cancelled=True).all()
return render_template('admin/list_cancelled.html', deployments=expdeployments, services=expservices, domains=expdomains)
@admin.route("/listaddresses", methods=['GET']) @admin.route("/listaddresses", methods=['GET'])
@login_required @login_required
@admin_required @admin_required
def list_addresses(): def list_addresses():
alladdresses = Address.query.order_by(Address.ip.asc()).all() alladdresses = Address.query.filter_by(cancelled=False).order_by(Address.ip.asc()).all()
return render_template('admin/list_addresses.html', addresses=alladdresses) return render_template('admin/list_addresses.html', addresses=alladdresses)
@admin.route("/addr2pool", methods=['GET', 'POST']) @admin.route("/addr2pool", methods=['GET', 'POST'])
@ -143,7 +152,7 @@ def transaction(user_pid=0):
def dashboard(user_pid=0): def dashboard(user_pid=0):
cuser = User.query.filter_by(pid=user_pid).first() cuser = User.query.filter_by(pid=user_pid).first()
inv_deployments = cuser.inv_deployments.order_by(Deployment.date_created.desc()).all() inv_deployments = cuser.inv_deployments.filter_by(cancelled=False).order_by(Deployment.date_created.desc()).all()
inv_deploycubeids = [] inv_deploycubeids = []
inv_deployments_list = [] inv_deployments_list = []
for invcls in inv_deployments: for invcls in inv_deployments:
@ -151,13 +160,13 @@ def dashboard(user_pid=0):
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.order_by(Service.date_last_charge.asc()).all() inv_services = cuser.inv_services.filter_by(cancelled=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 and invcls.enabled == True: if invcls.user_id == cuser.pid and invcls.enabled == True:
inv_services_list.extend([invcls.description]) inv_services_list.extend([invcls.description])
inv_domains = cuser.inv_domains.order_by(Domain.date_created.desc()).all() inv_domains = cuser.inv_domains.filter_by(cancelled=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 and invcls.enabled == True: if invcls.user_id == cuser.pid and invcls.enabled == True:

View file

@ -39,7 +39,7 @@ def terms():
def dashboard(): def dashboard():
cuser = current_user cuser = current_user
inv_deployments = cuser.inv_deployments.order_by(Deployment.date_created.desc()).all() inv_deployments = cuser.inv_deployments.filter_by(cancelled=False).order_by(Deployment.date_created.desc()).all()
inv_deploycubeids = [] inv_deploycubeids = []
inv_deployments_list = [] inv_deployments_list = []
for invcls in inv_deployments: for invcls in inv_deployments:
@ -47,13 +47,13 @@ def dashboard():
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.order_by(Service.date_last_charge.asc()).all() inv_services = cuser.inv_services.filter_by(cancelled=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 and invcls.enabled == True: if invcls.user_id == cuser.pid and invcls.enabled == True:
inv_services_list.extend([invcls.description]) inv_services_list.extend([invcls.description])
inv_domains = cuser.inv_domains.order_by(Domain.date_created.desc()).all() inv_domains = cuser.inv_domains.filter_by(cancelled=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 and invcls.enabled == True: if invcls.user_id == cuser.pid and invcls.enabled == True:

View file

@ -208,19 +208,38 @@ def contact_proxmaster(data, method, cubeid=0):
url = current_app.config['PROXMASTER_URL'] url = current_app.config['PROXMASTER_URL']
data['apikey'] = current_app.config['APIKEY'] data['apikey'] = current_app.config['APIKEY']
data_json = json.dumps(data) data_json = json.dumps(data)
if method == 'vmcreate': if method == 'vmcreate':
url = '{}/{}'.format(url, method) url = '{}/{}'.format(url, method)
else: else:
url = '{}/{}/{}'.format(url, method, cubeid) url = '{}/{}/{}'.format(url, method, cubeid)
try: try:
db_result = requests.post( url, data=data_json, headers={"content-type": "application/json"}, timeout=30 )
proxjson = db_result.json() proxjson = db_result.json()
#print('proxmaster query {}'.format(str(proxjson)))
return proxjson return proxjson
except: except:
return None return None
class Deployment(db.Model):
__tablename__ = 'deployments'
pid = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK
date_created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
date_last_charge = db.Column(db.DateTime)
period = db.Column(db.Integer)
daysleft = db.Column(db.Integer)
warning = db.Column(db.Boolean, default=False)
enabled = db.Column(db.Boolean, default=True)
cancelled = db.Column(db.Boolean, default=False)
protected = db.Column(db.Boolean, default=False) #machines with this False will be autodeleted after the warning period is over.
connected = db.Column(db.Boolean, default=False) #requires: protected=True, indicate that a connection is enabled
machine_id = db.Column(db.BigInteger) #cubeid
machine_alias = db.Column(db.String) #dns name
machine_cpu = db.Column(db.Integer)
machine_mem = db.Column(db.Integer)
machine_hdd = db.Column(db.Integer)
machine_addresses = db.relationship('Address', backref='deployments', lazy='dynamic')
class Service(db.Model): class Service(db.Model):
__tablename__ = 'services' __tablename__ = 'services'
pid = db.Column(db.Integer, primary_key=True) #PK pid = db.Column(db.Integer, primary_key=True) #PK
@ -237,27 +256,6 @@ class Service(db.Model):
description = db.Column(db.Unicode) description = db.Column(db.Unicode)
price = db.Column(db.Float) price = db.Column(db.Float)
class Deployment(db.Model):
__tablename__ = 'deployments'
pid = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK
date_created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
date_last_charge = db.Column(db.DateTime)
period = db.Column(db.Integer)
daysleft = db.Column(db.Integer)
warning = db.Column(db.Boolean, default=False)
enabled = db.Column(db.Boolean, default=True)
protected = db.Column(db.Boolean, default=False) #machines with this False will be autodeleted after the warning period is over.
cancelled = db.Column(db.Boolean, default=False)
machine_id = db.Column(db.BigInteger) #cubeid
machine_alias = db.Column(db.String) #dns name
machine_cpu = db.Column(db.Integer)
machine_mem = db.Column(db.Integer)
machine_hdd = db.Column(db.Integer)
machine_addresses = db.relationship('Address', backref='deployments', lazy='dynamic')
#NAMESPACE
class Region(db.Model): class Region(db.Model):
__tablename__ = 'regions' __tablename__ = 'regions'
pid = db.Column(db.Integer, primary_key=True) pid = db.Column(db.Integer, primary_key=True)

View file

@ -61,7 +61,7 @@ def activate(itemid=0):
service.enabled = True service.enabled = True
db.session.commit() db.session.commit()
transaction = Transaction(user_id=int(owner.pid), description='Deployment {} activated for {} month(s)'.format(str(service.description), form.period.data), value=-price) transaction = Transaction(user_id=int(owner.pid), description='Deployment {} activated for {} month(s)'.format(str(service.description), form.period.data), value=-total)
db.session.add(transaction) db.session.add(transaction)
db.session.commit() db.session.commit()

View file

@ -0,0 +1,65 @@
{% extends "base.html" %}
{% block styles %}
{{ super() }}
</style>
{% endblock %}
{% block page_content %}
<div class="row">
{% include "admin/admin_tasks.html" %}
<div class="col-md-12">
<div class="panel panel-info" id="deployments">
<div class="panel-heading">Deployments</div>
<div class="panel-body"><p>
<table class="table table-hover table-striped table-condensed cf">
<thead>
<tr>
<th>Owner</th>
<th>Cube ID</th>
<th>Alias</th>
<th>CPU</th>
<th>Mem</th>
<th>HDD</th>
<th>Price</th>
<th>Last Charged</th>
<th>Days Left</th>
</tr>
</thead>
<tbody>
{% for deploy in deployments %}
{% if deploy.enabled == False %}
<tr class="danger">
{% else %}
{% if deploy.warning == True %}
<tr class="warning">
{% else %}
<tr>
{% endif %}
{% endif %}
<td><a href="{{ url_for('admin.dashboard', user_pid=deploy.user_id) }}">{{ deploy.owner.email }}</a></td>
<td>{{ deploy.machine_id }}</td>
<td>{{ deploy.machine_alias }}</font></td>
<td>{{ deploy.machine_cpu }}</td>
<td>{{ deploy.machine_mem }} MB</td>
<td>{{ deploy.machine_hdd }} GB</td>
<td>{{ deploy.price }}</td>
<td>{{ moment(deploy.date_last_charge).format('lll') }} ({{ moment(deploy.date_last_charge).fromNow() }})</td>
<td>{{ deploy.daysleft }}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
</div>
</div>
{% endblock %}

View file

@ -133,27 +133,33 @@ addEventListener("DOMContentLoaded", function() {
<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>Name</th> <th><!-- Computer icon by Icons8 -->
<th>CPU</th> <img class="icon icons8-Computer" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACCklEQVRYhe3XzWvaYADHcf+MHXrYP9XLLuuhyNBFYXQuKwYfoezg20Z8UruWBuu0o25gYc6i2FGGynC+LWw6a22X6tJuYVA8SFk7frula7F1LUZa8IHvIQSSD8/zBPIYDNdhmB66bjFEmGMI3WccVNU7C6HipI0f0wAMEeZ84upRqd6C1FR0rVRvIbCcOLYQIfoPgO6X6i3IamcoVRptMA6qngAcVM1XdyCrHXiiFTD+jC55ohXIagdSU4HJznd7Aqw0AyNfwFRwc6AZ+QIYf6Y/4NH8B0wFN+FeOxhobHh7BBgBRoARYAS4IQArzWCcpHBnJj3QxkkKVvofgGx1D+lyS5ey1b3eAIszUNsofh3aD0lO2oLFKWxrAKPNc9fE8YeP3eLvabd4pHdmzn9o4p7d1wAmzs+yLrEbW8/jzUZR12Lredh9oa6Z470ne4BQOSdtDW0JCjUZDBG+99yEelT+JiP9paxdX/gVvPtYvfS0NpRfF758YpGFOeLEi9xaf8DLRAY0HNfyiTHYvUE8mHkO1rWIJ4GVU/dpOI7a7s9zAanPRZgjBNOrbniTof6As+38OEAk/h7uhdeYX0mi0mhfegmWsm/hTYbwSd49H3CVB181qamcOZgQYSmwnDiuNNq6H82kpoKFaOqP1Tkb1wCTNn7MQgKvhnEwZRxUtTpn4/fYp7cN12H8BeroKDHKz3I9AAAAAElFTkSuQmCC"></th>
<th>Mem</th> <th><!-- Flow Chart icon by Icons8 -->
<th>HDD</th> <img class="icon icons8-Flow-Chart" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABlElEQVRYhe2Xz0vCUBzA35/g0T/Bo3+Ah13UIWQgSzQhjE4RHhPq5EHdENSGGkqEdAnpINhliNBOOnU/aBhlp4qIYTA2vNc6JfJ46gQLqX3hA9vjw9vn3d4AMDG+TN+OkxxmFk+64zCzr+nBSS4aLMl69HyoLCJcHqibebGx8oDj65FRFj4WkmxpRoCWGCvACvh7AbHas5FsaQs5rL/9QADVdQVoiYHx53getb6RF2IrDZg1Xopjf+VDVsD/CvBSHGsWD9XRlvHdqbZzpada0q3iJIdZAVbA+gV40h1HsCA2IiWJiZQkhjjh+ckzLdRhn6CFOsoNFsQGfBveosXk1F7dcFG8+X7Hqa4LAAAATnLYfnWgNu91A2b7VFLhgFBRfEe5Bxd3Y/iEoYL4gHJzzRcDJ7noJCBeGypP+qcBs1uRFThgp3L7inKPrh5VVADKveyNrAArYM0CCFrQ4rWhAuPP9sZwgD/bG6NcghY0OICgBRnl7p3J+iQAS7C2eb/acMA8F0uwtmnXnWo7Z7m+TN8OAABf+SW5Q83GlOAAAAAASUVORK5CYII="></th>
<th>Network</th> <th><!-- Electronics icon by Icons8 -->
<th>Control</th> <img class="icon icons8-Electronics" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYheWXMWuDQBiG/Tn+DCdxNFpdBDtLh0L2rjrW4yIEF+lPcJJMnapL7jy4krXQpN2E0KUuyXUSQlNpGr1+lL5wwze9D7zHx/cqSo/0sFSNqNKMqNL0sFSHzn0+vXIxyYOMN0HGGxeTfOh8FsBitRWL1VZ4CS2Gzn8HwET1tRXTzQVmrZ9y4adcODPWDp3NmLxOEJ1+C2DFdDNf7oSMZ6F6fWSoh6XqYpJ7CS28hBYOZu+yAJwZazsfF5NcD0tVMaJKCzLedHldplyK+Xy5E37KRedzdff4ZkSVBg8AHgE4AHgEpwDcP+3FT/XwvB/vD4wFcPYfkAoAHgE4AHgE4ADgEYAvIvBVDA4AHgE4AHgEnzVB9EUWgI3Z8VH6BcDURvXoZ7mN2dq8pTenlQPlPzejQwDQcvpb9fwDkojR+HkAxLYAAAAASUVORK5CYII="></th>
<th>Remote</th> <th><!-- Memory Slot icon by Icons8 -->
<th>Time Left</th> <!-- Memory Slot icon by Icons8 -->
<img class="icon icons8-Memory-Slot" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABpklEQVRYhe2XzUsCURTF35/Ssj/DVQ20c9EXBrrJNrVokdQyoUHcRGUfkAViIbbIbNEyF+VDsKmsqVG0RIhxGgdKUCyYOS3MbPogRJhmMRcOD8595/JbXHg8QqyyihDiCHDLjlVOdG1cGqKxtQtxNHAeJoQQwrC0x711Jd4/aTBSkyG+3LeQ7CUMS20zEcFwgNloVmFYajMfwHpa1anlH+X1fqLYHnZS0ucOs+3cb/MsAAvAArAAzAtwUtKr5XNlvc/L7R4v63tcWQ/30zzzvgXGA/iofXj5rD5/kIeRGglwDcZH7YTxUfvgykV9Li7BSA0FMu8ALLU5g4L4dVv/0hJ9wUS4II2H8o+LyUZH2fW0CmdQED92wBkUxERRQ6UGhC5VVF+AeFbDtaThVtawf6ui9grsZFRUasBpScNkpPjM+OhUP0sn3OGC0mn+G0BG0gAAezcqgOalhypQqQHH981ePNs8hYoG15agMCy1dZs3B8CAP1Wd3hVkb+xOcW1el72xO8W9zUueaE72RHOye5uXPvemdwV5wJ+qtgC6yf/vh8QqM9QbwskG2n58EgAAAAAASUVORK5CYII="></th>
<th><!-- HDD icon by Icons8 -->
<!-- SSD icon by Icons8 -->
<img class="icon icons8-SSD" width="32" height="32" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADMElEQVRYhcWXy0/TcADHe/DgwQNHDhz8Izx44LCD0gHycBiDjygcFjV6UfFCohKdrAPdA4JMkZfxrcEgvkdcjLiOrSuPAQ4HTAQdMLYOcWRutF8PphOyTUlc6y/5HLvPp02/yUoQKY6ixrpJSdlzlVpakREoe66ixro5lSvpkFR/4dGOsdnGN3PhTHKkfXSuWO8s/2vAweah6Y9BAb5wZpnkBFS2uGf+KFdq6a2655+DmZaLNPR+DSu19Na0AXm1tl03+4PfpAp4NLgUyau17UobUKJnzr30rMSlCrBORgWVia1NG7DbyHb3z8QlkfvCAlj/KsoaBl6lDVCZXBNjAV6yAG9IwMHmoem0AUc7RkJSyUWq7n4MpJQX1DmyL/Z8kmwBIobXs6GUSyC19I52OrAkdcA9lltOuYRiveP0s9HvMakDeieiq6UG5kJSQKnRdc82HZNU7gsLYL6sQmVyPU2eoIEZGV2QbgEi40EB5U0DU0kB6taRgNRykZO3x+fXyRU11qzzj32SL0Ck7sVMsKDOkZ0IyNfZt1/vWwjLFXDLEfpGam3KNQH9J7rd36NyBbzyrMSL9K7q3y+gaaDt3acfssh9YQGO2ThUJlfX7wAj63DPS78AkQ+LAsoa2IlEQGXL8MIUJ49c5FjHaFBcwJbqhxOcnHJfWMClp9O/lrBT17ft1P3JQM84DzmpejC1oNTSCkKppRUVrR6/meEhJ5VtnmDKAI2FQ/3bCMwMD511GTrrMswMj/q3EWgsHMwMD6MtCo2FQ6M9hkZ7DBoLB6MtmnT9WjoGNxhAUjTUnV6YGR4Hro1gb9MQzAyP43d8ICkaZoZH9ZN5kBQNjYWDzroMkqJxputL0vUiPk4AAAz4hY0FqEws1J1eFOsZFF1xQt3pxZ7GwcSP7ze7QVI0DrWM4fCNDyApGuVXh6Hu9IKkaOxrdidEN4d4iCcSw8YC/hWViV33BAbnBERiwPvPqZ4AZc/9Hy9hRavHr9TSCkJRY80qvOxYanLEZZM3O1dRYmAW83X2HIIgCKJI7zxZdIUJVbR6/HJQoncGSw3s2XX/CfJ19pyMfY7/hcSdEwTxE6x7GguhLb0ZAAAAAElFTkSuQmCC"></th>
<th><!-- Services icon by Icons8 -->
<img class="icon icons8-Services" width="32" height="32" src="data:image/png;base64,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"></th>
<th><!-- Time icon by Icons8 -->
<img class="icon icons8-Time" width="32" height="32" src="data:image/png;base64,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"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for deploy in inv_deployments %} {% for deploy in inv_deployments %}
{% if deploy.enabled == False %} {% if deploy.enabled == False %}
<tr class="danger"> <tr class="danger">
<td data-title="Name"><b>{% if status[deploy.machine_id] == 'running' %}<font color="green">{% else %}<font color="red">{% endif %}{{ deploy.machine_alias }}</font></b></td> <td data-title="Name"><b>{% if deploy.enabled == True %}<font color="green">{% else %}<font color="red">{% endif %} {{ deploy.machine_alias }}</font></b></td>
<td data-title="CPU">{{ deploy.machine_cpu }} Cores</td> <td data-title="CPU">{{ deploy.machine_cpu }} {% if deploy.machine_cpu > 1 %}cores{% else %}core{% endif %}</td>
<td data-title="Memory">{{ deploy.machine_mem }} MB</td> <td data-title="Memory">{{ deploy.machine_mem }} MB</td>
<td data-title="Disk">{{ deploy.machine_hdd }} GB</td> <td data-title="Disk">{{ deploy.machine_hdd }} GB</td>
<td data-title="Network">{% for addr in deploy.machine_addresses %} {{ addr.ip }}<br /> {% endfor %}</td>
<td data-title="Control"> </td> <td data-title="Control"> </td>
<td data-title="Remote"> </td>
<td data-title="Time Left"><button class="btn btn-default btn-success" onclick="window.open('/vmanager/activate/{{ deploy.machine_id }}','_self');"><span class="glyphicon glyphicon-bell" aria-hidden="true"></span> Activate</td> <td data-title="Time Left"><button class="btn btn-default btn-success" onclick="window.open('/vmanager/activate/{{ deploy.machine_id }}','_self');"><span class="glyphicon glyphicon-bell" aria-hidden="true"></span> Activate</td>
{% else %} {% else %}
{% if deploy.warning == True %} {% if deploy.warning == True %}
@ -161,25 +167,23 @@ addEventListener("DOMContentLoaded", function() {
{% else %} {% else %}
<tr> <tr>
{% endif %} {% endif %}
<td data-title="Name"><a class="rrd" data-toggle="tooltip" title="ID# {{ deploy.machine_id }}<br />Deployment state: {{ status[deploy.machine_id] }}"><b>{% if status[deploy.machine_id] == 'running' %}<font color="green">{% else %}<font color="red">{% endif %}{{ deploy.machine_alias }}</font></b></a></td> <td data-title="Name"><a class="rrd" data-toggle="tooltip" title="Protected: {{ deploy.protected }}<br />Online: {{ deploy.connected }}<br />State: {{ status[deploy.machine_id] }}<br />ID: {{ deploy.machine_id }}"><b>{% if deploy.protected == True %}<font color="green">{% else %}<font color="red">{% endif %}{{ deploy.machine_alias }}</font></b></a></td>
<td data-title="CPU"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['cpu'] }}' />">{{ deploy.machine_cpu }} Cores</a></td> <td data-title="Network">{% for addr in deploy.machine_addresses %}<a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['net'] }}' />"><img class="icon icons8-GPS-Signal" width="24" height="24" 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="></a> {% endfor %}</td>
<td data-title="CPU"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['cpu'] }}' />">{{ deploy.machine_cpu }} {% if deploy.machine_cpu > 1 %}cores{% else %}core{% endif %}</a></td>
<td data-title="Memory"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['mem'] }}' />">{{ deploy.machine_mem }} MB</a></td> <td data-title="Memory"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['mem'] }}' />">{{ deploy.machine_mem }} MB</a></td>
<td data-title="Disk"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['hdd'] }}' />">{{ deploy.machine_hdd }} GB</a></td> <td data-title="Disk"><a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['hdd'] }}' />">{{ deploy.machine_hdd }} GB</a></td>
<td data-title="Network">{% for addr in deploy.machine_addresses %}<a class="rrd" data-toggle="tooltip" title="<img src='data:image/png;base64,{{ rrd[deploy.machine_id]['net'] }}' />">{{ addr.ip }}</a><br />{% endfor %}</td>
<td data-title="Control">{% if status[deploy.machine_id] == 'running' %} <td data-title="Control">{% if status[deploy.machine_id] == 'running' %}
<button class="confirm command command-vmshutdown btn btn-default btn-warning" value="vmshutdown" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Shutdown</button> <button class="confirm command command-vmshutdown btn btn-default btn-warning" value="vmshutdown" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Shutdown</button>
<button class="confirm command command-vmstop btn btn-default btn-danger" value="vmstop" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> Force Stop</button> <button class="confirm command command-vmstop btn btn-default btn-danger" value="vmstop" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> Force Stop</button>
{% else %} {% else %}
<button class="command command-vmstart btn btn-default btn-success" value="vmstart" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</button> <button class="command command-vmstart btn btn-default btn-success" value="vmstart" vmid="{{ deploy.machine_id }}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</button>
{% endif %}</td> {% endif %}
<td data-title="Remote">{% if status[deploy.machine_id] == 'running' %} {% if status[deploy.machine_id] == 'running' %}<button class="btn btn-default btn-info" onclick="window.open('/vmanager/vmvnc/{{ deploy.machine_id }}', '_blank');"><span class="glyphicon glyphicon-console" aria-hidden="true"></span> Console</button>{% endif %}</td>
<button class="btn btn-default btn-info" onclick="window.open('/vmanager/vmvnc/{{ deploy.machine_id }}', '_blank');"><span class="glyphicon glyphicon-console" aria-hidden="true"></span> Console</button>{% endif %}
{% if deploy.warning == True %} {% if deploy.warning == True %}
<td data-title="Time Left"><button class="btn btn-default btn-success" onclick="window.open('/vmanager/activate/{{ deploy.machine_id }}');"><span class="glyphicon glyphicon-bell" aria-hidden="true"></span> Renew ({{ deploy.daysleft }} days left)</button></td> <td data-title="Time Left"><button class="btn btn-default btn-success" onclick="window.open('/vmanager/activate/{{ deploy.machine_id }}');"><span class="glyphicon glyphicon-bell" aria-hidden="true"></span> Activate ({{ deploy.daysleft }} days left)</button></td>
{% else %} {% else %}
<td data-title="Time Left">{{ deploy.daysleft }} day(s)</td> <td data-title="Time Left">{{ deploy.daysleft }} day(s)</td>
{% endif %} {% endif %}
</td>
</tr> </tr>
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Deploy{% endblock %} {% block title %}Create{% endblock %}
{% block page_content %} {% block page_content %}
@ -33,79 +33,37 @@
<br /> <br />
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-12">
<div class="panel panel-info">
<div class="panel-heading">{{ product_name }}</div>
<div class="panel-body">
<img src="{{ product_pic }}"></img><br />
{{ product_description }}
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading">Настройки</div> <div class="panel-heading">Настройки</div>
<div class="panel-body"> <div class="panel-body">
<form method="POST" action="{{ url_for('vmanager.deploy', product_id=product_id) }}"> <form method="POST" action="{{ url_for('vmanager.createvm') }}">
<p> <p>
{{ form.servername.label }}<br />{{ form.servername(size=42) }}<br /> {{ form.servername.label }}<br />{{ form.servername(size=42) }}<br />
{% for error in form.servername.errors %} {% for error in form.servername.errors %}
{{ error }}<br /> {{ error }}<br />
{% endfor %} {% endfor %}
</p> </p>
<br />
<p> <p>
{{ form.region.label }}<br /> {{ form.region }}<br /> {{ form.region.label }}<br /> {{ form.region }}<br />
{% for error in form.region.errors %} {% for error in form.region.errors %}
{{ error }}<br /> {{ error }}<br />
{% endfor %} {% endfor %}
</p> </p>
<br />
<p> <p>
{{ form.vmpassword.label }}<br /> {{ form.vmpassword }}<br /> {{ form.invite_key.label }}<br /> {{ form.invite_key }}<br />
{% for error in form.vmpassword.errors %}
{{ error }}<br />
{% endfor %}
</p>
<br />
<p>
<div id="noUiSlider" class="noUiSlider"></div>
<div id="valueInput">
{{ form.cpu.label }} {{ form.cpu(class_="noUiSluder") }}<br />
</div>
{{ form.mem.label }} {{ form.mem }}<br />
{{ form.hdd.label }} {{ form.hdd }}<br />
{{ form.recipe.label }} {{ form.recipe }}<br />
{{ form.ipv4.label }} {{ form.ipv4 }}<br />
<p>
<br />
{{ form.invite_key.label }} {{ form.invite_key }}<br />
{% for error in form.invite_key.errors %} {% for error in form.invite_key.errors %}
{{ error }}<br /> {{ error }}<br />
{% endfor %} {% endfor %}
</p>
</div>
</div>
<p> <p>
{{ form.csrf_token() }} {{ form.csrf_token() }}
{{ form.submit }} {{ form.submit }}
</p> </p>
</div> </div>
</div>
</div>
</div> </div>
</div> </div>

View file

@ -3,24 +3,20 @@ from wtforms import StringField, PasswordField, BooleanField, SubmitField, Selec
from wtforms import validators, ValidationError from wtforms import validators, ValidationError
from wtforms.fields.html5 import EmailField from wtforms.fields.html5 import EmailField
from .. import db
class DeployForm(FlaskForm):
servername = StringField('Име/Домейн:', [validators.Regexp(message='пример: myservice1.com, myservice2.local', regex='^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$')])
region = SelectField('Регион:')
vmpassword = StringField('Парола:', [validators.DataRequired()])
cpu = StringField('Процесорни ядра:')
mem = StringField('Памет:')
hdd = StringField('Дисково пространство:')
recipe = SelectField('Рецепта')
ipv4 = SelectField('Брой публични IP адреса', choices=[('1', '1'),('2', '2' ), ('3', '3')])
invite_key = StringField('Покана', [validators.DataRequired(), validators.Length(6,35)])
class CreateForm(FlaskForm):
region_choices = [(1, 'Plovdiv, Bulgaria')]
servername = StringField('Domain Name:', [validators.Regexp(message='ex.: myservice1.com, myservice2.local', regex='^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$'), validators.Length(6,64)])
region = SelectField('Region:', choices=region_choices, coerce=int)
invite_key = StringField('Invite Code:', [validators.DataRequired(), validators.Length(6,35)])
def validate_invite_key(self, field): def validate_invite_key(self, field):
if field.data != 'inv1919': if field.data != 'inv1919':
raise ValidationError('Denied') raise ValidationError('Denied')
submit = SubmitField('Create')
submit = SubmitField('Deploy')
class ActivateForm(FlaskForm): class ActivateForm(FlaskForm):
period = SelectField('Deploy Period', choices=[(1, '1 Month'), (3, '3 Months'), (6, '6 Months'), (12, '1 Year'), (24, '2 Years')], coerce=int) period = SelectField('Deploy Period', choices=[(1, '1 Month'), (3, '3 Months'), (6, '6 Months'), (12, '1 Year'), (24, '2 Years')], coerce=int)
submit = SubmitField('Activate') submit = SubmitField('Activate')

View file

@ -3,7 +3,7 @@ from flask_login import login_required, login_user, logout_user, current_user
from flask_sqlalchemy import get_debug_queries from flask_sqlalchemy import get_debug_queries
from . import vmanager from . import vmanager
from .forms import DeployForm, ActivateForm from .forms import CreateForm, ActivateForm
from .. import db from .. import db
from ..email import send_email from ..email import send_email
from ..models import User, Permission, Transaction, Deployment, Service, Region, Address, Domain, contact_proxmaster from ..models import User, Permission, Transaction, Deployment, Service, Region, Address, Domain, contact_proxmaster
@ -34,17 +34,22 @@ def createvm():
flash('Please update profile info for this operation.') flash('Please update profile info for this operation.')
return redirect(url_for('settings.profile')) return redirect(url_for('settings.profile'))
deployment_seeds = Deployment.query.filter_by(protected=False).all() deployment_seeds = current_user.inv_deployments.filter_by(cancelled=False).filter_by(protected=False).all()
if deployment_seeds != []: if deployment_seeds != []:
flash('Offline deployments exist.') flash('Offline deployments still exist.')
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
form = CreateForm()
if current_user.confirmed and form.validate_on_submit(): if current_user.confirmed and form.validate_on_submit():
selected_region = Region.query.filter_by(pid=int(form.region.data)).first()
###
#flash('Region: {}'.format(str(selected_region.description)))
#return redirect(url_for('main.dashboard'))
data = { 'clientid': str(current_user.pid), data = { 'clientid': str(current_user.pid),
'clientname': str(current_user.name),
'clientemail': str(current_user.email), 'clientemail': str(current_user.email),
'hostname': str(form.deployname.data), 'hostname': str(form.servername.data),
'region': form.region.data, 'region': str(selected_region.name),
'type': 'kvm', 'type': 'kvm',
'cpu': '1', 'cpu': '1',
'mem': '512', 'mem': '512',
@ -57,21 +62,20 @@ def createvm():
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
if query is not None: if query is not None:
deployment = Deployment(user_id=client_id, product_id=product_id, machine_alias=form.servername.data, machine_id=query['cube'], machine_cpu=form.cpu.data, machine_mem=form.mem.data, machine_hdd=form.hdd.data, enabled=True) deployment = Deployment(user_id=int(current_user.pid), machine_alias=query['hostname'], machine_id=query['cube'], machine_cpu=data['cpu'], machine_mem=data['mem'], machine_hdd=data['hdd'], enabled=True, protected=False, daysleft=15, warning=True)
db.session.add(deployment) db.session.add(deployment)
db.session.commit() db.session.commit()
flash('Deploy created successfully in region "{}".'.format(str(selected_region.description)))
flash('Deploy requested.')
else: else:
flash('Deploy cancelled! Please try again later...') flash('Deploy cancelled! Please try again later...')
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
return render_template('vmanager/create.html', form=form)
@vmanager.route('/activate/<int:itemid>', methods=['GET', 'POST']) @vmanager.route('/activate/<int:itemid>', methods=['GET', 'POST'])
@login_required @login_required
def activate(itemid=0): def activate(itemid=0):
result = current_user.inv_deployments.all() result = current_user.inv_deployments.filter_by(cancelled=False).all()
inventory = [] inventory = []
for invcls in result: for invcls in result:
inventory.extend([invcls.machine_id]) inventory.extend([invcls.machine_id])
@ -88,7 +92,13 @@ def activate(itemid=0):
mem_cost = ( deploy.machine_mem / 1024 ) * current_app.config['MEM_RATIO'] mem_cost = ( deploy.machine_mem / 1024 ) * current_app.config['MEM_RATIO']
hdd_cost = deploy.machine_hdd * current_app.config['HDD_RATIO'] hdd_cost = deploy.machine_hdd * current_app.config['HDD_RATIO']
ppm = round(cpu_cost + mem_cost + hdd_cost) ppm = round(cpu_cost + mem_cost + hdd_cost)
if deploy.period is None:
form = ActivateForm(period=1)
total = ppm * 1
else:
form = ActivateForm(period=int(deploy.period)) form = ActivateForm(period=int(deploy.period))
total = ppm * deploy.period
owner = deploy.owner owner = deploy.owner
if owner.confirmed and form.validate_on_submit(): if owner.confirmed and form.validate_on_submit():
@ -106,21 +116,20 @@ def activate(itemid=0):
deploy.daysleft = daysleft.days + extradays.days deploy.daysleft = daysleft.days + extradays.days
deploy.warning = False deploy.warning = False
deploy.enabled = True deploy.enabled = True
deploy.protected = True
db.session.commit() db.session.commit()
transaction = Transaction(user_id=int(owner.pid), description='Deployment {} activated for {} month(s)'.format(str(deploy.machine_alias), form.period.data), value=-total) transaction = Transaction(user_id=int(owner.pid), description='Deployment {} activated for {} month(s)'.format(str(deploy.machine_alias), form.period.data), value=-total)
db.session.add(transaction) db.session.add(transaction)
db.session.commit() db.session.commit()
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 owner.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'))
return render_template('vmanager/activate.html', form=form, deploy=deploy, cpu_cost=cpu_cost, mem_cost=mem_cost, hdd_cost=hdd_cost, ppm=ppm, total=(ppm * deploy.period), currency=owner.currency) return render_template('vmanager/activate.html', form=form, deploy=deploy, cpu_cost=cpu_cost, mem_cost=mem_cost, hdd_cost=hdd_cost, ppm=ppm, total=total, currency=owner.currency)
@vmanager.route('/<cmd>/<int:vmid>') @vmanager.route('/<cmd>/<int:vmid>')

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
scriptdir=`dirname $0` scriptdir=`dirname $0`
cd $scriptdir cd $scriptdir
/bin/bash -c "source ../bin/activate; python3 manage.py autodisable ; python3 manage.py autowarn" /bin/bash -c "source ../bin/activate; python3 manage.py autodisable ; python3 manage.py autowarn ; python3 manage.py autoremove"

View file

@ -36,16 +36,31 @@ def deploy():
# create user roles # create user roles
Role.insert_roles() Role.insert_roles()
@manager.command
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))
drafts = Deployment.query.filter_by(cancelled=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))
db.session.commit()
@manager.command @manager.command
def autodisable(): def autodisable():
from app.models import User, Deployment, Service, Domain from app.models import User, Deployment, Service, Domain
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('\nScan for active expired items and set them as inactive. Script started at {}'.format(today))
dep_c = 0 dep_c = 0
srv_c = 0 srv_c = 0
dom_c = 0 dom_c = 0
deployments_ena = Deployment.query.filter_by(enabled=True).all() deployments = Deployment.query.filter_by(cancelled=False).filter_by(enabled=True).filter_by(protected=True).all()
for deploy in deployments_ena: for deploy in deployments:
#print('Found {}.'.format(str(deploy.machine_alias)))
lastcharge = deploy.date_last_charge lastcharge = deploy.date_last_charge
expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period)) expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
if today > expiry: if today > expiry:
@ -56,7 +71,7 @@ def autodisable():
db.session.commit() db.session.commit()
else: else:
dep_c += 1 dep_c += 1
services_ena = Service.query.filter_by(enabled=True).all() services_ena = Service.query.filter_by(cancelled=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
expiry = lastcharge + relativedelta(lastcharge, months=+(service.period)) expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
@ -68,7 +83,7 @@ def autodisable():
db.session.commit() db.session.commit()
else: else:
srv_c += 1 srv_c += 1
domains_ena = Domain.query.filter_by(enabled=True).all() domains_ena = Domain.query.filter_by(cancelled=False).filter_by(enabled=True).all()
for domain in domains_ena: for domain in domains_ena:
expiry = domain.date_expire expiry = domain.date_expire
if today > expiry: if today > expiry:
@ -86,7 +101,7 @@ 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('\nScan for items that will expire soon and enable the warning flag. Script started at {}'.format(today))
deployments_ena = Deployment.query.filter_by(enabled=True).all() deployments_ena = Deployment.query.filter_by(cancelled=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
expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period)) expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
@ -102,7 +117,7 @@ def autowarn():
deploy.warning = False deploy.warning = False
db.session.commit() db.session.commit()
services_ena = Service.query.filter_by(enabled=True).all() services_ena = Service.query.filter_by(cancelled=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
expiry = lastcharge + relativedelta(lastcharge, months=+(service.period)) expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
@ -118,7 +133,7 @@ def autowarn():
service.warning = False service.warning = False
db.session.commit() db.session.commit()
domains_ena = Domain.query.filter_by(enabled=True).all() domains_ena = Domain.query.filter_by(cancelled=False).filter_by(enabled=True).all()
for domain in domains_ena: for domain in domains_ena:
expiry = domain.date_expire expiry = domain.date_expire
daysleft = expiry - today daysleft = expiry - today