diff --git a/app/admin/routes.py b/app/admin/routes.py
index a0430c9..a734bb7 100644
--- a/app/admin/routes.py
+++ b/app/admin/routes.py
@@ -39,28 +39,37 @@ def index():
@login_required
@admin_required
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)
@admin.route("/listservices", methods=['GET'])
@login_required
@admin_required
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)
@admin.route("/listdomains", methods=['GET'])
@login_required
@admin_required
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)
+@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'])
@login_required
@admin_required
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)
@admin.route("/addr2pool", methods=['GET', 'POST'])
@@ -143,7 +152,7 @@ def transaction(user_pid=0):
def dashboard(user_pid=0):
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_deployments_list = []
for invcls in inv_deployments:
@@ -151,13 +160,13 @@ def dashboard(user_pid=0):
inv_deploycubeids.extend([invcls.machine_id])
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 = []
for invcls in inv_services:
if invcls.user_id == cuser.pid and invcls.enabled == True:
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 = []
for invcls in inv_domains:
if invcls.user_id == cuser.pid and invcls.enabled == True:
diff --git a/app/main/routes.py b/app/main/routes.py
index 4d1d237..d2ef055 100644
--- a/app/main/routes.py
+++ b/app/main/routes.py
@@ -39,7 +39,7 @@ def terms():
def dashboard():
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_deployments_list = []
for invcls in inv_deployments:
@@ -47,13 +47,13 @@ def dashboard():
inv_deploycubeids.extend([invcls.machine_id])
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 = []
for invcls in inv_services:
if invcls.user_id == cuser.pid and invcls.enabled == True:
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 = []
for invcls in inv_domains:
if invcls.user_id == cuser.pid and invcls.enabled == True:
diff --git a/app/models.py b/app/models.py
index bca1e9e..ab0053d 100644
--- a/app/models.py
+++ b/app/models.py
@@ -208,19 +208,38 @@ def contact_proxmaster(data, method, cubeid=0):
url = current_app.config['PROXMASTER_URL']
data['apikey'] = current_app.config['APIKEY']
data_json = json.dumps(data)
-
if method == 'vmcreate':
url = '{}/{}'.format(url, method)
else:
url = '{}/{}/{}'.format(url, method, cubeid)
-
try:
+ db_result = requests.post( url, data=data_json, headers={"content-type": "application/json"}, timeout=30 )
proxjson = db_result.json()
- #print('proxmaster query {}'.format(str(proxjson)))
return proxjson
except:
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):
__tablename__ = 'services'
pid = db.Column(db.Integer, primary_key=True) #PK
@@ -237,27 +256,6 @@ class Service(db.Model):
description = db.Column(db.Unicode)
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):
__tablename__ = 'regions'
pid = db.Column(db.Integer, primary_key=True)
diff --git a/app/smanager/routes.py b/app/smanager/routes.py
index 1454b13..27d1741 100644
--- a/app/smanager/routes.py
+++ b/app/smanager/routes.py
@@ -61,7 +61,7 @@ def activate(itemid=0):
service.enabled = True
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.commit()
diff --git a/app/templates/admin/list_cancelled.html b/app/templates/admin/list_cancelled.html
new file mode 100644
index 0000000..74b7869
--- /dev/null
+++ b/app/templates/admin/list_cancelled.html
@@ -0,0 +1,65 @@
+{% extends "base.html" %}
+
+{% block styles %}
+{{ super() }}
+
+{% endblock %}
+
+{% block page_content %}
+
+ {% include "admin/admin_tasks.html" %}
+
+
+
+
Deployments
+
+
+
+
+ Owner |
+ Cube ID |
+ Alias |
+ CPU |
+ Mem |
+ HDD |
+ Price |
+ Last Charged |
+ Days Left |
+
+
+
+ {% for deploy in deployments %}
+ {% if deploy.enabled == False %}
+
+ {% else %}
+ {% if deploy.warning == True %}
+
+ {% else %}
+
+ {% endif %}
+ {% endif %}
+ {{ deploy.owner.email }} |
+ {{ deploy.machine_id }} |
+ {{ deploy.machine_alias }} |
+ {{ deploy.machine_cpu }} |
+ {{ deploy.machine_mem }} MB |
+ {{ deploy.machine_hdd }} GB |
+ {{ deploy.price }} |
+ {{ moment(deploy.date_last_charge).format('lll') }} ({{ moment(deploy.date_last_charge).fromNow() }}) |
+ {{ deploy.daysleft }} |
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
diff --git a/app/templates/main/dashboard.html b/app/templates/main/dashboard.html
index f72ceb2..6736f8b 100644
--- a/app/templates/main/dashboard.html
+++ b/app/templates/main/dashboard.html
@@ -133,27 +133,33 @@ addEventListener("DOMContentLoaded", function() {
- Name |
- CPU |
- Mem |
- HDD |
- Network |
- Control |
- Remote |
- Time Left |
+
+ |
+
+ |
+
+ |
+
+
+ |
+
+
+ |
+
+ |
+
+ |
{% for deploy in inv_deployments %}
{% if deploy.enabled == False %}
- {% if status[deploy.machine_id] == 'running' %}{% else %}{% endif %}{{ deploy.machine_alias }} |
- {{ deploy.machine_cpu }} Cores |
+ {% if deploy.enabled == True %}{% else %}{% endif %} {{ deploy.machine_alias }} |
+ {{ deploy.machine_cpu }} {% if deploy.machine_cpu > 1 %}cores{% else %}core{% endif %} |
{{ deploy.machine_mem }} MB |
{{ deploy.machine_hdd }} GB |
- {% for addr in deploy.machine_addresses %} {{ addr.ip }} {% endfor %} |
|
- |
|
{% else %}
{% if deploy.warning == True %}
@@ -161,25 +167,23 @@ addEventListener("DOMContentLoaded", function() {
{% else %}
{% endif %}
- {% if status[deploy.machine_id] == 'running' %}{% else %}{% endif %}{{ deploy.machine_alias }} |
- {{ deploy.machine_cpu }} Cores |
+ {% if deploy.protected == True %}{% else %}{% endif %}{{ deploy.machine_alias }} |
+ {% for addr in deploy.machine_addresses %} {% endfor %} |
+ {{ deploy.machine_cpu }} {% if deploy.machine_cpu > 1 %}cores{% else %}core{% endif %} |
{{ deploy.machine_mem }} MB |
{{ deploy.machine_hdd }} GB |
- {% for addr in deploy.machine_addresses %}{{ addr.ip }} {% endfor %} |
{% if status[deploy.machine_id] == 'running' %}
{% else %}
- {% endif %} |
- {% if status[deploy.machine_id] == 'running' %}
- {% endif %}
+ {% endif %}
+ {% if status[deploy.machine_id] == 'running' %}{% endif %} |
{% if deploy.warning == True %}
- |
+ |
{% else %}
{{ deploy.daysleft }} day(s) |
{% endif %}
-
{% endif %}
{% endfor %}
diff --git a/app/templates/vmanager/deploy.html b/app/templates/vmanager/create.html
similarity index 53%
rename from app/templates/vmanager/deploy.html
rename to app/templates/vmanager/create.html
index 1b9021b..0b069fe 100644
--- a/app/templates/vmanager/deploy.html
+++ b/app/templates/vmanager/create.html
@@ -1,6 +1,6 @@
{% extends "base.html" %}
-{% block title %}Deploy{% endblock %}
+{% block title %}Create{% endblock %}
{% block page_content %}
@@ -33,79 +33,37 @@
-
-
-
{{ product_name }}
-
-
- {{ product_description }}
-
-
-
-
-
+
-
+
{{ form.csrf_token() }}
{{ form.submit }}
-
-
-
+
+
diff --git a/app/vmanager/forms.py b/app/vmanager/forms.py
index df22924..feea6c4 100644
--- a/app/vmanager/forms.py
+++ b/app/vmanager/forms.py
@@ -3,24 +3,20 @@ from wtforms import StringField, PasswordField, BooleanField, SubmitField, Selec
from wtforms import validators, ValidationError
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):
if field.data != 'inv1919':
raise ValidationError('Denied')
-
- submit = SubmitField('Deploy')
+ submit = SubmitField('Create')
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)
submit = SubmitField('Activate')
+
diff --git a/app/vmanager/routes.py b/app/vmanager/routes.py
index 9249ae9..40ff50b 100644
--- a/app/vmanager/routes.py
+++ b/app/vmanager/routes.py
@@ -3,7 +3,7 @@ from flask_login import login_required, login_user, logout_user, current_user
from flask_sqlalchemy import get_debug_queries
from . import vmanager
-from .forms import DeployForm, ActivateForm
+from .forms import CreateForm, ActivateForm
from .. import db
from ..email import send_email
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.')
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 != []:
- flash('Offline deployments exist.')
+ flash('Offline deployments still exist.')
return redirect(url_for('main.dashboard'))
+ form = CreateForm()
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),
- 'clientname': str(current_user.name),
'clientemail': str(current_user.email),
- 'hostname': str(form.deployname.data),
- 'region': form.region.data,
+ 'hostname': str(form.servername.data),
+ 'region': str(selected_region.name),
'type': 'kvm',
'cpu': '1',
'mem': '512',
@@ -57,21 +62,20 @@ def createvm():
return redirect(url_for('main.dashboard'))
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.commit()
-
- flash('Deploy requested.')
+ flash('Deploy created successfully in region "{}".'.format(str(selected_region.description)))
else:
flash('Deploy cancelled! Please try again later...')
return redirect(url_for('main.dashboard'))
-
+ return render_template('vmanager/create.html', form=form)
@vmanager.route('/activate/', methods=['GET', 'POST'])
@login_required
def activate(itemid=0):
- result = current_user.inv_deployments.all()
+ result = current_user.inv_deployments.filter_by(cancelled=False).all()
inventory = []
for invcls in result:
inventory.extend([invcls.machine_id])
@@ -88,7 +92,13 @@ def activate(itemid=0):
mem_cost = ( deploy.machine_mem / 1024 ) * current_app.config['MEM_RATIO']
hdd_cost = deploy.machine_hdd * current_app.config['HDD_RATIO']
ppm = round(cpu_cost + mem_cost + hdd_cost)
- form = ActivateForm(period=int(deploy.period))
+
+ if deploy.period is None:
+ form = ActivateForm(period=1)
+ total = ppm * 1
+ else:
+ form = ActivateForm(period=int(deploy.period))
+ total = ppm * deploy.period
owner = deploy.owner
if owner.confirmed and form.validate_on_submit():
@@ -106,21 +116,20 @@ def activate(itemid=0):
deploy.daysleft = daysleft.days + extradays.days
deploy.warning = False
deploy.enabled = True
+ deploy.protected = True
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)
db.session.add(transaction)
db.session.commit()
-
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:
return redirect(url_for('admin.list_deployments'))
else:
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('//')
diff --git a/cronexec.sh b/cronexec.sh
index 1fed76b..be99172 100755
--- a/cronexec.sh
+++ b/cronexec.sh
@@ -1,4 +1,4 @@
#!/bin/bash
scriptdir=`dirname $0`
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"
diff --git a/manage.py b/manage.py
index 6957927..fb99b28 100644
--- a/manage.py
+++ b/manage.py
@@ -36,16 +36,31 @@ def deploy():
# create user 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
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))
dep_c = 0
srv_c = 0
dom_c = 0
- deployments_ena = Deployment.query.filter_by(enabled=True).all()
- for deploy in deployments_ena:
+ deployments = Deployment.query.filter_by(cancelled=False).filter_by(enabled=True).filter_by(protected=True).all()
+ for deploy in deployments:
+ #print('Found {}.'.format(str(deploy.machine_alias)))
lastcharge = deploy.date_last_charge
expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
if today > expiry:
@@ -56,7 +71,7 @@ def autodisable():
db.session.commit()
else:
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:
lastcharge = service.date_last_charge
expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
@@ -68,7 +83,7 @@ def autodisable():
db.session.commit()
else:
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:
expiry = domain.date_expire
if today > expiry:
@@ -86,7 +101,7 @@ 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))
- 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:
lastcharge = deploy.date_last_charge
expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
@@ -102,7 +117,7 @@ def autowarn():
deploy.warning = False
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:
lastcharge = service.date_last_charge
expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
@@ -118,7 +133,7 @@ def autowarn():
service.warning = False
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:
expiry = domain.date_expire
daysleft = expiry - today