console/SWSCloudWeb/views/compute/vms/__init__.py
2016-10-17 02:10:57 +03:00

425 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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')