425 lines
14 KiB
Python
425 lines
14 KiB
Python
# coding: utf-8
|
||
|
||
import uuid
|
||
import dateutil.parser
|
||
import datetime
|
||
from flask import Blueprint, g, redirect, render_template, request, session, jsonify, url_for, flash
|
||
|
||
from SWSCloudCore.controllers.billing import ControllerBilling
|
||
from SWSCloudCore.controllers.common import ControllerCommon
|
||
from SWSCloudCore.controllers.common import ControllerMessagesEmail
|
||
from SWSCloudCore.controllers.vms import ControllerVMS
|
||
from SWSCloudCore.controllers.datacenters import ControllerDataCenters
|
||
from SWSCloudCore.controllers.ips import ControllerIps
|
||
from SWSCloudCore.controllers.tasks import ControllerTasks
|
||
from SWSCloudCore.controllers.users import ControllerSSHKey
|
||
from SWSCloudCore.controllers.users import ControllerUsers
|
||
from SWSCloudCore.controllers.plans import ControllerPlans
|
||
from SWSCloudWeb.common import requires_login
|
||
|
||
from SWSStatisticsClient import SWSStatisticsClient
|
||
from SWSCloudCore.models import Vms, Tasks
|
||
|
||
viewVMs = Blueprint('vms', __name__, url_prefix='/compute/vms')
|
||
|
||
|
||
@viewVMs.route('/')
|
||
@requires_login
|
||
def index():
|
||
return render_template(
|
||
'default/compute/vms/index.html',
|
||
# get containers list
|
||
vms=ControllerVMS(session['user_id']).get())
|
||
|
||
|
||
@viewVMs.route('/create.html', methods=['GET'])
|
||
@requires_login
|
||
def create():
|
||
datacenters = ControllerDataCenters().get()
|
||
plans = ControllerPlans().get('active')
|
||
#
|
||
return render_template(
|
||
'default/compute/vms/create.html',
|
||
datacenters=datacenters, plans=plans)
|
||
|
||
|
||
@viewVMs.route('/create.html', methods=['POST'])
|
||
@requires_login
|
||
def create_action():
|
||
user_balance = ControllerBilling().get(session.get('user_id'))
|
||
user_ssh = ControllerSSHKey(session.get('user_id'))
|
||
controller_plans = ControllerPlans()
|
||
|
||
# check user money
|
||
if user_balance <= 0:
|
||
flash(u'Недостаточно средств на аккаунте')
|
||
return redirect(url_for('vms.create'))
|
||
|
||
new_vm = dict()
|
||
new_vm['vm_id'] = str(uuid.uuid4())
|
||
|
||
# check exists plan
|
||
if not controller_plans.exists(request.form.get('plan')):
|
||
flash(u'Необходимо выбрать план')
|
||
return redirect(url_for('vms.create'))
|
||
|
||
# load plan details
|
||
plan_details = controller_plans.plan_get(request.form.get('plan'))
|
||
|
||
new_vm['plan'] = request.form.get('plan')
|
||
|
||
# select server from selected region with available ip-addresses
|
||
# select IP
|
||
select_ip = ControllerIps().getfree(request.form['datacenter'])
|
||
# mark ip as busy (taken)
|
||
ControllerIps().setbusy(select_ip.id)
|
||
|
||
# generate password for container user
|
||
new_vm['password'] = ControllerCommon().generate_password(size=14)
|
||
new_vm['hostname'] = ControllerCommon().generate_password(size=7)
|
||
|
||
new_vm['datacenter_id'] = str(select_ip.datacenter.id)
|
||
new_vm['server_id'] = str(select_ip.server.id)
|
||
|
||
new_vm['platform'] = 'x86_64'
|
||
new_vm['ipv4'] = select_ip.ipv4
|
||
new_vm['ipv6'] = select_ip.ipv6
|
||
|
||
new_vm['ipv4_gateway'] = select_ip.ipv4_gateway
|
||
new_vm['ipv6_gateway'] = select_ip.ipv6_gateway
|
||
|
||
# TODO: remove hardcore
|
||
new_vm['dns1'] = '8.8.8.8'
|
||
new_vm['dns2'] = '8.8.4.4'
|
||
|
||
new_vm['cores'] = plan_details.cores
|
||
new_vm['storage'] = plan_details.storage
|
||
new_vm['swap'] = plan_details.swap
|
||
new_vm['memory'] = plan_details.memory
|
||
|
||
new_vm['os_name'] = 'ubuntu'
|
||
new_vm['os_suite'] = 'trusty'
|
||
|
||
# sshkey
|
||
new_vm['ssh_key'] = None
|
||
if user_ssh.check():
|
||
new_vm['ssh_key'] = user_ssh.get()
|
||
|
||
# create container record in database
|
||
# status 4: creation
|
||
status = 4
|
||
container_create = ControllerVMS(session['user_id']).create(
|
||
vm_id=new_vm['vm_id'],
|
||
datacenter_id=new_vm['datacenter_id'],
|
||
server_id=new_vm['server_id'],
|
||
hostname=new_vm['hostname'],
|
||
ipv4=new_vm['ipv4'],
|
||
ipv6=new_vm['ipv6'],
|
||
plan=new_vm['plan'],
|
||
platform=new_vm['platform'],
|
||
os_name=new_vm['os_name'],
|
||
os_suite=new_vm['os_suite'],
|
||
status=status
|
||
)
|
||
# create default state data
|
||
# ControllerContainersStatisticsState().set(new_container['container_id'], dict())
|
||
if container_create:
|
||
# create task for create new container
|
||
ControllerTasks(session['user_id']).create(
|
||
new_vm['datacenter_id'],
|
||
new_vm['server_id'],
|
||
'vm_create',
|
||
0,
|
||
vm_id=new_vm['vm_id'],
|
||
ipv4=new_vm['ipv4'],
|
||
ipv4_gateway=new_vm['ipv4_gateway'],
|
||
ipv6=new_vm['ipv6'],
|
||
ipv6_gateway=new_vm['ipv6_gateway'],
|
||
password=new_vm['password'],
|
||
hostname=new_vm['hostname'],
|
||
platform=new_vm['platform'],
|
||
# TODO: remove hardcore
|
||
dns1=new_vm['dns1'],
|
||
dns2=new_vm['dns2'],
|
||
|
||
cores=new_vm['cores'],
|
||
storage=new_vm['storage'],
|
||
swap=new_vm['swap'],
|
||
memory=new_vm['memory'],
|
||
|
||
os_name=new_vm['os_name'],
|
||
os_suite=new_vm['os_suite'],
|
||
|
||
ssh_key=new_vm['ssh_key'],
|
||
)
|
||
|
||
# Show login/password on page
|
||
flash(u'Виртуальный сервер будет доступен через несколько минут.')
|
||
|
||
# send mail message with recovery code
|
||
message_parts = []
|
||
|
||
if new_vm['ipv4']:
|
||
message_parts.append(u"IPv4: %s" % new_vm['ipv4'])
|
||
if new_vm['ipv6']:
|
||
message_parts.append(u"IPv6: %s" % new_vm['ipv6'])
|
||
message_parts.append(u"Пользователь: %s" % 'administrator')
|
||
# message_parts.append(u"Пользователь: %s" % new_vm['username'])
|
||
message_parts.append(u"Пароль: %s" % new_vm['password'])
|
||
if new_vm['ssh_key']:
|
||
message_parts.append(u"SSH ключ: добавлен")
|
||
|
||
message = '<br/>\n'.join(message_parts)
|
||
subject = u'GoCloud.ru: Новый виртуальный сервер'
|
||
lead = u"""Поздравляем с новым виртуальным сервером."""
|
||
callout = u"""
|
||
Для входа в личный кабинет воспользуйтесь
|
||
<a href="https://gocloud.ru/account/login">страницей авторизации</a>.
|
||
"""
|
||
|
||
user_data = ControllerUsers(session['user_id']).get()
|
||
|
||
email = ControllerMessagesEmail()
|
||
email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout)
|
||
|
||
return redirect(url_for('vms.index'))
|
||
else:
|
||
# mark ip as free
|
||
flash(u'Виртуальный сервер не был создан.')
|
||
ControllerIps().setfree(select_ip.id)
|
||
return redirect(url_for('vms.index'))
|
||
|
||
|
||
@viewVMs.route('/delete/<uuid:vm_id>.html', methods=['GET'])
|
||
@requires_login
|
||
def delete(vm_id):
|
||
#
|
||
vms = ControllerVMS(session['user_id'])
|
||
tasks = ControllerTasks(session['user_id'])
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not vms.exists(vm_id):
|
||
return redirect(url_for('vms.index'))
|
||
|
||
# get container details
|
||
return render_template('default/compute/vms/delete.html', vm=vms.get(vm_id))
|
||
|
||
|
||
@viewVMs.route('/delete/<uuid:vm_id>.html', methods=['POST'])
|
||
@requires_login
|
||
def delete_action(vm_id):
|
||
#
|
||
vms = ControllerVMS(session['user_id'])
|
||
tasks = ControllerTasks(session['user_id'])
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not vms.exists(vm_id):
|
||
return redirect(url_for('vms.index'))
|
||
|
||
# get container details
|
||
vm_details = vms.get(vm_id)
|
||
|
||
# Обновляем статус "5" для правила
|
||
vms.set_status(vm_id, 5)
|
||
# Создание задания
|
||
tasks.create(
|
||
datacenter_id=vm_details.datacenter.id,
|
||
server_id=vm_details.server.id,
|
||
task='vm_delete',
|
||
status=0,
|
||
vm_id=vm_id,
|
||
# hostname=vm_details.hostname
|
||
)
|
||
# TODO: send email container was deleted about
|
||
# Редиректим на страницу со всеми правилами
|
||
flash(u'Виртуальная машина будет удалена')
|
||
return redirect(url_for('vms.index'))
|
||
|
||
|
||
@viewVMs.route('/settings/<uuid:vm_id>.html', methods=['GET', 'POST'])
|
||
@requires_login
|
||
def settings(vm_id):
|
||
vm = ControllerVMS(session['user_id'])
|
||
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not vm.exists(vm_id):
|
||
return redirect(url_for('vms.index'))
|
||
|
||
# get container details
|
||
return render_template(
|
||
'default/compute/vms/settings.html',
|
||
vm=vm.get(vm_id=vm_id))
|
||
|
||
|
||
@viewVMs.route('/settings/<uuid:vm_id>.html', methods=['POST'])
|
||
@requires_login
|
||
def settings_action(vm_id):
|
||
vm = ControllerVMS(session['user_id'])
|
||
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not vm.exists(vm_id):
|
||
return redirect(url_for('vms.index'))
|
||
|
||
# get container details
|
||
vm_details = vm.get(vm_id=vm_id)
|
||
|
||
if request.form['action'] == 'set_status':
|
||
if request.form['action'] == 'stop':
|
||
vm.status_set(vm_id, 3)
|
||
# Создание задания
|
||
ControllerTasks(session['user_id']).create(
|
||
vm_details.datacenter.id,
|
||
vm_details.server.id,
|
||
'vm_stop',
|
||
0,
|
||
vm_id=vm_id
|
||
)
|
||
return redirect(url_for('vms.settings', vm_id=vm_id))
|
||
|
||
if request.form.get('action') == 'start':
|
||
balance = ControllerBilling().get(session['user_id'])
|
||
|
||
if balance <= 0:
|
||
flash(u'Недостаточно средств на балансе.')
|
||
return redirect(url_for('vms.settings', vm_id=vm_id))
|
||
|
||
vm.set_status(vm_id, 2)
|
||
# Создание задания
|
||
ControllerTasks(session.get('user_id')).create(
|
||
vm_details.datacenter.id,
|
||
vm_details.server.id,
|
||
'vm_start',
|
||
0,
|
||
vm_id=vm_details.id
|
||
)
|
||
return redirect(url_for('vms.settings', vm_id=vm_id))
|
||
|
||
return render_template(
|
||
'default/compute/vms/settings.html',
|
||
vm=vm_details)
|
||
|
||
|
||
@viewVMs.route('/stats/<uuid:vm_id>.html')
|
||
@requires_login
|
||
def stats(vm_id):
|
||
# init
|
||
vms = ControllerVMS(session['user_id'])
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not vms.exists(vm_id):
|
||
return redirect(url_for('.index'))
|
||
# get container details
|
||
vm_details = vms.get_item(vm_id)
|
||
return render_template(
|
||
'default/compute/vms/stats.html',
|
||
vm_details=vm_details)
|
||
|
||
|
||
def calc_diff_list(data_list):
|
||
"""
|
||
:param data_list:
|
||
:return:
|
||
"""
|
||
# массив с результатами вычисления
|
||
diff = list()
|
||
# добавля
|
||
# diff.append(data_list[0])
|
||
for cur, prev in zip(data_list, data_list[1:]):
|
||
# print prev, cur
|
||
a = cur['read_bytes'] if cur['read_bytes'] else 0
|
||
b = prev['read_bytes'] if prev['read_bytes'] else 0
|
||
|
||
calc = int(b) - int(a)
|
||
# diff.append(calc if calc > 0 else calc * -1)
|
||
cur['read_bytes_diff'] = (calc if calc > 0 else calc * -1)
|
||
diff.append(cur)
|
||
# diff.__delitem__(0)
|
||
return diff
|
||
|
||
|
||
@viewVMs.route('/stats/<uuid:vm_id>.json')
|
||
@requires_login
|
||
def stats_json(vm_id):
|
||
# check the user have a selected rule
|
||
# if user not have a container then redirect to the container list
|
||
if not ControllerVMS(session['user_id']).exists(vm_id):
|
||
return jsonify(status=1, message='instance not exists')
|
||
|
||
# stats_items = list()
|
||
statistics = list()
|
||
for s in SWSStatisticsClient().get_vm(vm_id).get('items'):
|
||
reported = dateutil.parser.parse(s.get('time'))
|
||
read_bytes = int(s.get('stats', {}).get('network', {}).get('read_bytes', 0))
|
||
# stats_items.append(read_bytes)
|
||
|
||
statistics.append(dict(
|
||
year=reported.strftime('%Y'),
|
||
month=reported.strftime('%m'),
|
||
day=reported.strftime('%d'),
|
||
hour=reported.strftime('%H'),
|
||
minute=reported.strftime('%M'),
|
||
read_bytes=read_bytes / 1024 / 1024,
|
||
))
|
||
return jsonify(network=calc_diff_list(statistics), status=0)
|
||
|
||
|
||
@viewVMs.route('/state.json')
|
||
@requires_login
|
||
def state_json():
|
||
user_id = session.get('user_id')
|
||
vm_id = request.args.get('vm_id')
|
||
if not ControllerVMS(user_id).exists(vm_id):
|
||
return jsonify(status=1, message='instance not exists')
|
||
return jsonify(state=Vms.get_state(vm_id), status=0)
|
||
|
||
|
||
@viewVMs.route('/state.json', methods=['POST'])
|
||
@requires_login
|
||
def state_json_set():
|
||
user_id = session.get('user_id')
|
||
vm_id = request.form.get('vm_id')
|
||
# start, stop, destroy
|
||
state = request.form.get('action')
|
||
if not ControllerVMS(user_id).exists(vm_id):
|
||
return jsonify(status=1, message='instance not exists')
|
||
|
||
vm = ControllerVMS(session['user_id'])
|
||
# get container details
|
||
vm_details = vm.get(vm_id=vm_id)
|
||
|
||
if Tasks.exists_active_tasks(user_id):
|
||
flash('Task already exists in queue')
|
||
return jsonify(status=3, message='Task already exists in queue')
|
||
|
||
if state == 'stop':
|
||
vm.status_set(vm_id, 3)
|
||
# Создание задания
|
||
ControllerTasks(session['user_id']).create(
|
||
vm_details.datacenter.id,
|
||
vm_details.server.id,
|
||
'vm_stop',
|
||
0,
|
||
vm_id=vm_id
|
||
)
|
||
return jsonify(status=0)
|
||
|
||
if state == 'start':
|
||
balance = ControllerBilling().get(session['user_id'])
|
||
|
||
if balance <= 0:
|
||
flash(u'Недостаточно средств на балансе.', category='info')
|
||
return jsonify(status=1, message=u'Недостаточно средств на балансе.')
|
||
|
||
vm.set_status(vm_id, 2)
|
||
# Создание задания
|
||
ControllerTasks(session.get('user_id')).create(
|
||
vm_details.datacenter.id,
|
||
vm_details.server.id,
|
||
'vm_start',
|
||
0,
|
||
vm_id=vm_details.id)
|
||
return jsonify(status=0)
|
||
return jsonify(status=2, messages='Method undefined')
|
||
|