diff --git a/SWSCloudAPI/API/__init__.py b/SWSCloudAPI/API/__init__.py index 3ec0b26..aa67939 100644 --- a/SWSCloudAPI/API/__init__.py +++ b/SWSCloudAPI/API/__init__.py @@ -1,23 +1,12 @@ # coding: utf-8 -from uuid import uuid4 -from flask import Blueprint, jsonify, request, g +from flask import Blueprint, jsonify, g from flask_httpauth import HTTPBasicAuth -from SWSCloudCore.controllers.datacenters import ControllerDataCenters -from SWSCloudCore.controllers.ips import ControllerIps -from SWSCloudCore.controllers.plans import ControllerPlans -from SWSCloudCore.controllers.containers import ControllerContainers -from SWSCloudCore.controllers.vms import ControllerVMS from SWSCloudCore.controllers.users import ControllerAPI from SWSCloudCore.controllers.users import ControllerUsers -from SWSCloudCore.controllers.users import ControllerSSHKey -from SWSCloudCore.controllers.billing import ControllerBilling -from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessagesEmail -from SWSCloudCore.controllers.containers import ControllerContainersStatisticsState, ControllerContainersStatistics -from SWSCloudCore.controllers.tasks import ControllerTasks -api = Blueprint('api', __name__, url_prefix='/api/v1') +api = Blueprint('api', __name__, url_prefix='') auth = HTTPBasicAuth() """ @@ -44,487 +33,3 @@ def index(): :return: """ return jsonify(user_id=g.user_id) - - -@api.route('/datacenters/') -@auth.login_required -def datacenters_index(): - """ - get containers list - curl -X http://localhost:5000/api/v1/datacenters/ -u : - :return: - """ - dc_list = ControllerDataCenters().get() - return jsonify(total=dc_list.get('total'), items=dc_list.get('items')) - - -@api.route('/pricing/vms/') -@auth.login_required -def pricing_vms(): - """ - get pricing list - curl -X http://localhost:5000/api/v1/pricing/vms/ -u : - :return: - """ - return jsonify(pricing=ControllerPlans().get_plans(status='active')) - - -@api.route('/pricing/containers/') -@auth.login_required -def pricing_containers(): - """ - get pricing list - curl -X GET http://localhost:5000/api/v1/pricing/containers/ -u : - :return: - """ - return jsonify(pricing=100) - - -@api.route('/containers/', methods=['GET']) -@auth.login_required -def containers_list(): - """ - curl -X GET http://localhost:5000/api/v1/containers/ -u : - :return: - """ - # get containers list - containers = ControllerContainers(g.user_id).get_items() - # - return jsonify(total=containers['total'], items=containers['items']) - - -@api.route('/containers/', methods=['POST']) -@auth.login_required -def container_create(): - """ - curl -X POST http://localhost:5000/api/v1/containers/ -u : -d "datacenter_id=123" - :return: - """ - # Check exists data center - if not ControllerDataCenters().exists(request.form.get('datacenter')): - return jsonify(message='datacenter not exists') - # Check money - if ControllerBilling().get(g.user_id) <= 0: - return jsonify(message='no money') - - # select server from selected region with available ip-addresses - # select IP - select_ip = ControllerIps().getfree(request.form.get('datacenter')) - # mark ip as busy (taken) - ControllerIps().setbusy(select_ip.id) - # generate password for container user - password = ControllerCommon().generate_password(size=14) - - user_ssh = ControllerSSHKey(g.user_id) - - new_container = dict( - container_id=str(uuid4()), - datacenter_id=str(select_ip.datacenter.id), - server_id=str(select_ip.server.id), - ipv4=select_ip.ipv4, - ipv6=select_ip.ipv6, - ipv4_gateway=select_ip.ipv4_gateway, - ipv6_gateway=select_ip.ipv6_gateway, - username='ubuntu', - password=password, - ssh_key='', - ) - - # SSH key - if user_ssh.check(): - new_container['ssh_key'] = user_ssh.get() - - # create container record in database - # status 4: creation - status = 4 - container_create = ControllerContainers(g.user_id).create( - new_container['container_id'], - new_container['datacenter_id'], - new_container['server_id'], - new_container['ipv4'], - new_container['ipv6'], - status - ) - # create default state data - ControllerContainersStatisticsState().set(new_container['container_id'], dict()) - if container_create: - # create task for create new container - ControllerTasks(g.user_id).create( - new_container['datacenter_id'], - new_container['server_id'], - 'container_create', - 0, - container_id=new_container['container_id'], - ipv4=new_container['ipv4'], - ipv6=new_container['ipv6'], - ipv4_gateway=new_container['ipv4_gateway'], - ipv6_gateway=new_container['ipv6_gateway'], - username=new_container['username'], - password=new_container['password'], - ssh_key=new_container['ssh_key'] - ) - - # send mail message with recovery code - message_parts = [] - - if new_container['ipv4']: - message_parts.append(u"IPv4: %s" % new_container['ipv4']) - if new_container['ipv6']: - message_parts.append(u"IPv6: %s" % new_container['ipv6']) - message_parts.append(u"Пользователь: %s" % new_container['username']) - message_parts.append(u"Пароль: %s" % new_container['password']) - if new_container['ssh_key']: - message_parts.append(u"SSH ключ: добавлен") - - message = '
\n'.join(message_parts) - subject = u'GoCloud.ru: Новый контейнер' - lead = u"""Поздравляем с новым контейнером.""" - callout = u""" - Для входа в личный кабинет воспользуйтесь - страницей авторизации. - """ - - user_data = ControllerUsers(g.user_id).get() - - email = ControllerMessagesEmail() - email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout) - - # - return jsonify(message='ok') - - -@api.route('/container/', methods=['DELETE']) -@auth.login_required -def container_delete(container_id): - """ - curl -X DELETE http://localhost:5000/api/v1/container/ -u : -d "container_id=" - :return: - """ - containers = ControllerContainers(g.user_id) - # check the user have a selected rule - # if user not have a container then redirect to the container list - if not containers.check_exists_item(container_id): - return jsonify(message='container_not_exists') - - # get container details - container_details = ControllerContainers(g.user_id).get_item(container_id) - - # Обновляем статус "5" для правила - containers.set_status(container_id, 5) - # Создание задания - ControllerTasks(g.user_id).create( - container_details.datacenter.id, - container_details.server.id, - 'container_delete', - 0, - container_id=container_id - ) - # TODO: send email container was deleted about - return jsonify(status=0, message='container has been deleted') - - -@api.route('/container/', methods=['GET']) -@auth.login_required -def container_info(container_id): - """ - curl -X GET http://localhost:5000/api/v1/container/ -u : - :return: - """ - # init - containers = ControllerContainers(g.user_id) - # check the user have a selected rule - # if user not have a container then redirect to the container list - if not containers.check_exists_item(container_id): - return jsonify(message='container_not_found') - # get container details - container_details = containers.get_item(container_id) - # print ControllerContainersStatisticsState().get(container_id) - - statistics = list() - for s in ControllerContainersStatistics(container_id).size_get(1): - created = s.created - statistics.append({ - 'year': created.strftime('%Y'), - 'month': created.strftime('%m'), - 'day': created.strftime('%d'), - 'hour': created.strftime('%H'), - 'minute': created.strftime('%M'), - 'data': s.memory - }) - # return - return jsonify(container=container_details, stats_memory=statistics) - - -@api.route('/container/', methods=['POST']) -@auth.login_required -def container_actions(container_id): - """ - curl -X POST http://localhost:5000/api/v1/container/ -u : -d "status=inactive" - curl -X POST http://localhost:5000/api/v1/container/ -u : -d "action=active" - :return: - """ - containers = ControllerContainers(g.user_id) - # check the user have a selected rule - # if user not have a container then redirect to the container list - if not containers.check_exists_item(container_id): - return jsonify(message='container_not_found') - - # get container details - container_details = containers.get_item(container_id) - - if request.form.get('status') == "inactive": - containers.set_status(container_id, 3) - # Создание задания - ControllerTasks(g.user_id).create( - container_details.datacenter.id, - container_details.server.id, - 'container_stop', - 0, - container_id=container_id - ) - elif request.form.get('status') == 'active': - balance = ControllerBilling().get(g.user_id) - - if balance <= 0: - return jsonify(message='no money') - - containers.set_status(container_id, 2) - # Создание задания - ControllerTasks(g.user_id).create( - container_details.datacenter.id, - container_details.server.id, - 'container_start', - 0, - container_id=container_details.id - ) - return jsonify(message='ok') - else: - return jsonify(status=1, message='require action') - - -@api.route('/vms/') -@auth.login_required -def vms_list(): - """ - get virtual servers list - curl -X POST http://localhost:5000/api/v1/vms/ -u : - :return: - """ - return jsonify(vms=ControllerVMS(g.user_id).get_items()) - - -@api.route('/vms', methods=['POST']) -@auth.login_required -def vms_create(): - """ - curl -XPOST /api/v1/vms/ -u : -d 'plan=&datacenter=' - :return: - """ - user_balance = ControllerBilling().get(g.user_id) - user_ssh = ControllerSSHKey(g.user_id) - controller_plans = ControllerPlans() - - # check user money - if user_balance <= 0: - return jsonify(message='no money') - - new_vm = dict() - new_vm['vm_id'] = str(uuid4()) - - # check exists plan - if not controller_plans.exists(request.form.get('plan')): - return jsonify(message='plan not exists') - - # 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.get('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(g.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(g.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'], - ) - - # 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" % 'root') - # 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 = '
\n'.join(message_parts) - subject = u'GoCloud.ru: Новый виртуальный сервер' - lead = u"""Поздравляем с новым виртуальным сервером.""" - callout = u""" - Для входа в личный кабинет воспользуйтесь - страницей авторизации. - """ - - user_data = ControllerUsers(g.user_id).get() - - email = ControllerMessagesEmail() - email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout) - - return jsonify(status=0, message='ok', - user='root', password=new_vm['password'], ipv4=new_vm['ipv4'], - public_ssh_key='added' if new_vm['ssh_key'] else 'empty') - else: - # mark ip as free - ControllerIps().setfree(select_ip.id) - return jsonify(status=1, message='fail') - - -@api.route('/vms/', methods=['POST']) -@auth.login_required -def vm_actions(vm_id): - """ - """ - # init ... - vm = ControllerVMS(g.user_id) - # get container details - vm_details = vm.get(vm_id=vm_id) - - if request.form.get('action') == "start": - if ControllerBilling().get(g.user_id) <= 0: - return jsonify(message='no money') - - vm.set_status(vm_id, 2) - # Создание задания - ControllerTasks(g.user_id).create( - datacenter_id=vm_details.datacenter.id, - server_id=vm_details.server.id, - task='vm_start', - status=0, - vm_id=vm_details.id - ) - - if request.form.get('action') == "restart": - return jsonify(message='not supported') - - if request.form.get('action') == "stop": - vm.status_set(vm_id, 3) - # Создание задания - ControllerTasks(g.user_id).create( - vm_details.datacenter.id, - vm_details.server.id, - 'vm_stop', - 0, - vm_id=vm_id - ) - - -@api.route('/vms/', methods=['DELETE']) -@auth.login_required -def vm_delete(vm_id): - """ - Удаление виртуального сервера - :param vm_id: - :return: - """ - # - vms = ControllerVMS(g.user_id) - tasks = ControllerTasks(g.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 jsonify(message='not exists') - # 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 - ) - return jsonify(status=0, message='ok') diff --git a/SWSCloudAPI/API/containers.py b/SWSCloudAPI/API/containers.py new file mode 100644 index 0000000..cca7826 --- /dev/null +++ b/SWSCloudAPI/API/containers.py @@ -0,0 +1,238 @@ +# coding: utf-8 + +from uuid import uuid4 +from flask import Blueprint, jsonify, request, g +from SWSCloudAPI.API import auth +from SWSCloudCore.controllers.datacenters import ControllerDataCenters +from SWSCloudCore.controllers.ips import ControllerIps +from SWSCloudCore.controllers.users import ControllerUsers +from SWSCloudCore.controllers.users import ControllerSSHKey +from SWSCloudCore.controllers.billing import ControllerBilling +from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessagesEmail +from SWSCloudCore.controllers.tasks import ControllerTasks +from SWSCloudCore.controllers.containers import ( + ControllerContainers, ControllerContainersStatistics, ControllerContainersStatisticsState) + +api_v1_containers = Blueprint('containers', __name__, url_prefix='/containers') + + +@api_v1_containers.route('/', methods=['GET']) +@auth.login_required +def containers_list(): + """ + curl -X GET http://localhost:5000/api/v1/containers/ -u : + :return: + """ + # get containers list + containers = ControllerContainers(g.user_id).get_items() + # + return jsonify(total=containers['total'], items=containers['items']) + + +@api_v1_containers.route('/', methods=['POST']) +@auth.login_required +def container_create(): + """ + curl -X POST http://localhost:5000/api/v1/containers/ -u : -d "datacenter_id=123" + :return: + """ + # Check exists data center + if not ControllerDataCenters().exists(request.form.get('datacenter')): + return jsonify(message='datacenter not exists') + # Check money + if ControllerBilling().get(g.user_id) <= 0: + return jsonify(message='no money') + + # select server from selected region with available ip-addresses + # select IP + select_ip = ControllerIps().getfree(request.form.get('datacenter')) + # mark ip as busy (taken) + ControllerIps().setbusy(select_ip.id) + # generate password for container user + password = ControllerCommon().generate_password(size=14) + + user_ssh = ControllerSSHKey(g.user_id) + + new_container = dict( + container_id=str(uuid4()), + datacenter_id=str(select_ip.datacenter.id), + server_id=str(select_ip.server.id), + ipv4=select_ip.ipv4, + ipv6=select_ip.ipv6, + ipv4_gateway=select_ip.ipv4_gateway, + ipv6_gateway=select_ip.ipv6_gateway, + username='ubuntu', + password=password, + ssh_key='', + ) + + # SSH key + if user_ssh.check(): + new_container['ssh_key'] = user_ssh.get() + + # create container record in database + # status 4: creation + status = 4 + container_create = ControllerContainers(g.user_id).create( + new_container['container_id'], + new_container['datacenter_id'], + new_container['server_id'], + new_container['ipv4'], + new_container['ipv6'], + status + ) + # create default state data + ControllerContainersStatisticsState().set(new_container['container_id'], dict()) + if container_create: + # create task for create new container + ControllerTasks(g.user_id).create( + new_container['datacenter_id'], + new_container['server_id'], + 'container_create', + 0, + container_id=new_container['container_id'], + ipv4=new_container['ipv4'], + ipv6=new_container['ipv6'], + ipv4_gateway=new_container['ipv4_gateway'], + ipv6_gateway=new_container['ipv6_gateway'], + username=new_container['username'], + password=new_container['password'], + ssh_key=new_container['ssh_key'] + ) + + # send mail message with recovery code + message_parts = [] + + if new_container['ipv4']: + message_parts.append(u"IPv4: %s" % new_container['ipv4']) + if new_container['ipv6']: + message_parts.append(u"IPv6: %s" % new_container['ipv6']) + message_parts.append(u"Пользователь: %s" % new_container['username']) + message_parts.append(u"Пароль: %s" % new_container['password']) + if new_container['ssh_key']: + message_parts.append(u"SSH ключ: добавлен") + + message = '
\n'.join(message_parts) + subject = u'GoCloud.ru: Новый контейнер' + lead = u"""Поздравляем с новым контейнером.""" + callout = u""" + Для входа в личный кабинет воспользуйтесь + страницей авторизации. + """ + + user_data = ControllerUsers(g.user_id).get() + + email = ControllerMessagesEmail() + email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout) + + # + return jsonify(message='ok') + + +@api_v1_containers.route('/container/', methods=['DELETE']) +@auth.login_required +def container_delete(container_id): + """ + curl -X DELETE http://gocloud.ru/api/v1/container/ -u : -d "container_id=" + :return: + """ + containers = ControllerContainers(g.user_id) + # check the user have a selected rule + # if user not have a container then redirect to the container list + if not containers.check_exists_item(container_id): + return jsonify(message='container_not_exists') + + # get container details + container_details = ControllerContainers(g.user_id).get_item(container_id) + + # Обновляем статус "5" для правила + containers.set_status(container_id, 5) + # Создание задания + ControllerTasks(g.user_id).create( + container_details.datacenter.id, + container_details.server.id, + 'container_delete', + 0, + container_id=container_id + ) + # TODO: send email container was deleted about + return jsonify(status=0, message='container has been deleted') + + +@api_v1_containers.route('/', methods=['GET']) +@auth.login_required +def container_info(container_id): + """ + curl -X GET http://localhost:5000/api/v1/container/ -u : + :return: + """ + # init + containers = ControllerContainers(g.user_id) + # check the user have a selected rule + # if user not have a container then redirect to the container list + if not containers.check_exists_item(container_id): + return jsonify(message='container_not_found') + # get container details + container_details = containers.get_item(container_id) + # print ControllerContainersStatisticsState().get(container_id) + + statistics = list() + for s in ControllerContainersStatistics(container_id).size_get(1): + created = s.created + statistics.append({ + 'year': created.strftime('%Y'), + 'month': created.strftime('%m'), + 'day': created.strftime('%d'), + 'hour': created.strftime('%H'), + 'minute': created.strftime('%M'), + 'data': s.memory + }) + # return + return jsonify(container=container_details, stats_memory=statistics) + + +@api_v1_containers.route('/', methods=['POST']) +@auth.login_required +def container_actions(container_id): + """ + curl -X POST http://localhost:5000/api/v1/container/ -u : -d "status=inactive" + curl -X POST http://localhost:5000/api/v1/container/ -u : -d "action=active" + :return: + """ + containers = ControllerContainers(g.user_id) + # check the user have a selected rule + # if user not have a container then redirect to the container list + if not containers.check_exists_item(container_id): + return jsonify(message='container_not_found') + + # get container details + container_details = containers.get_item(container_id) + + if request.form.get('status') == "inactive": + containers.set_status(container_id, 3) + # Создание задания + ControllerTasks(g.user_id).create( + container_details.datacenter.id, + container_details.server.id, + 'container_stop', + 0, + container_id=container_id + ) + elif request.form.get('status') == 'active': + balance = ControllerBilling().get(g.user_id) + + if balance <= 0: + return jsonify(message='no money') + + containers.set_status(container_id, 2) + # Создание задания + ControllerTasks(g.user_id).create( + container_details.datacenter.id, + container_details.server.id, + 'container_start', + 0, + container_id=container_details.id + ) + return jsonify(message='ok') + else: + return jsonify(status=1, message='require action') diff --git a/SWSCloudAPI/API/datacenters.py b/SWSCloudAPI/API/datacenters.py new file mode 100644 index 0000000..7f980ad --- /dev/null +++ b/SWSCloudAPI/API/datacenters.py @@ -0,0 +1,20 @@ +# coding: utf-8 + +from flask import Blueprint, jsonify +from SWSCloudAPI.API import auth +from SWSCloudCore.controllers.datacenters import ControllerDataCenters + + +api_v1_datacenters = Blueprint('datacenters', __name__, url_prefix='/datacenters') + + +@api_v1_datacenters.route('/', methods=['GET']) +@auth.login_required +def index(): + """ + get containers list + curl -X http://localhost:5000/api/v1/datacenters/ -u : + :return: + """ + dc_list = ControllerDataCenters().get() + return jsonify(total=dc_list.get('total'), items=dc_list.get('items')) diff --git a/SWSCloudAPI/API/pricing.py b/SWSCloudAPI/API/pricing.py new file mode 100644 index 0000000..3f025d0 --- /dev/null +++ b/SWSCloudAPI/API/pricing.py @@ -0,0 +1,29 @@ +# coding: utf-8 + +from flask import Blueprint, jsonify +from SWSCloudAPI.API import auth +from SWSCloudCore.controllers.plans import ControllerPlans + +api_v1_pricing = Blueprint('pricing', __name__, url_prefix='/pricing') + + +@api_v1_pricing.route('/pricing/vms/') +@auth.login_required +def pricing_vms(): + """ + get pricing list + curl -X http://localhost:5000/api/v1/pricing/vms/ -u : + :return: + """ + return jsonify(pricing=ControllerPlans().get_plans(status='active')) + + +@api_v1_pricing.route('/pricing/containers/') +@auth.login_required +def pricing_containers(): + """ + get pricing list + curl -X GET http://localhost:5000/api/v1/pricing/containers/ -u : + :return: + """ + return jsonify(pricing=100) diff --git a/SWSCloudAPI/API/vms.py b/SWSCloudAPI/API/vms.py new file mode 100644 index 0000000..7544243 --- /dev/null +++ b/SWSCloudAPI/API/vms.py @@ -0,0 +1,243 @@ +# coding: utf-8 + +from uuid import uuid4 +from flask import Blueprint, jsonify, request, g +from SWSCloudAPI.API import auth +from SWSCloudCore.controllers.ips import ControllerIps +from SWSCloudCore.controllers.plans import ControllerPlans +from SWSCloudCore.controllers.users import ControllerUsers +from SWSCloudCore.controllers.users import ControllerSSHKey +from SWSCloudCore.controllers.billing import ControllerBilling +from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessagesEmail +from SWSCloudCore.controllers.tasks import ControllerTasks +from SWSCloudCore.controllers.vms import ControllerVMS + +api_v1_vms = Blueprint('vms', __name__, url_prefix='/vms') + + +@api_v1_vms.route('/', methods=['GET']) +@auth.login_required +def vms_list(): + """ + get virtual servers list + curl -X POST http://localhost:5000/api/v1/vms/ -u : + :return: + """ + return jsonify(vms=ControllerVMS(g.user_id).get_items()) + + +@api_v1_vms.route('/', methods=['POST']) +@auth.login_required +def vms_create(): + """ + curl -XPOST /api/v1/vms/ -u : -d 'plan=&datacenter=' + :return: + """ + user_balance = ControllerBilling().get(g.user_id) + user_ssh = ControllerSSHKey(g.user_id) + controller_plans = ControllerPlans() + + # check user money + if user_balance <= 0: + return jsonify(message='no money') + + new_vm = dict() + new_vm['vm_id'] = str(uuid4()) + + # check exists plan + if not controller_plans.exists(request.form.get('plan')): + return jsonify(message='plan not exists') + + # 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.get('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(g.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(g.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'], + ) + + # 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" % 'root') + # 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 = '
\n'.join(message_parts) + subject = u'GoCloud.ru: Новый виртуальный сервер' + lead = u"""Поздравляем с новым виртуальным сервером.""" + callout = u""" + Для входа в личный кабинет воспользуйтесь + страницей авторизации. + """ + + user_data = ControllerUsers(g.user_id).get() + + email = ControllerMessagesEmail() + email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout) + + return jsonify(status=0, message='ok', + user='root', password=new_vm['password'], ipv4=new_vm['ipv4'], + public_ssh_key='added' if new_vm['ssh_key'] else 'empty') + else: + # mark ip as free + ControllerIps().setfree(select_ip.id) + return jsonify(status=1, message='fail') + + +@api_v1_vms.route('/', methods=['POST']) +@auth.login_required +def vm_actions(vm_id): + """ + """ + # init ... + vm = ControllerVMS(g.user_id) + # get container details + vm_details = vm.get(vm_id=vm_id) + + if request.form.get('action') == "start": + if ControllerBilling().get(g.user_id) <= 0: + return jsonify(message='no money') + + vm.set_status(vm_id, 2) + # Создание задания + ControllerTasks(g.user_id).create( + datacenter_id=vm_details.datacenter.id, + server_id=vm_details.server.id, + task='vm_start', + status=0, + vm_id=vm_details.id + ) + + if request.form.get('action') == "restart": + return jsonify(message='not supported') + + if request.form.get('action') == "stop": + vm.status_set(vm_id, 3) + # Создание задания + ControllerTasks(g.user_id).create( + vm_details.datacenter.id, + vm_details.server.id, + 'vm_stop', + 0, + vm_id=vm_id + ) + + +@api_v1_vms.route('/vms/', methods=['DELETE']) +@auth.login_required +def vm_delete(vm_id): + """ + Удаление виртуального сервера + :param vm_id: + :return: + """ + # + vms = ControllerVMS(g.user_id) + tasks = ControllerTasks(g.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 jsonify(message='not exists') + # 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 + ) + return jsonify(status=0, message='ok') diff --git a/SWSCloudAPI/application.py b/SWSCloudAPI/application.py index 57c3839..89f5d72 100644 --- a/SWSCloudAPI/application.py +++ b/SWSCloudAPI/application.py @@ -2,16 +2,25 @@ from flask import Flask, g, jsonify from SWSCloudAPI.API import api +from SWSCloudAPI.API.vms import api_v1_vms +from SWSCloudAPI.API.containers import api_v1_containers +from SWSCloudAPI.API.datacenters import api_v1_datacenters +from SWSCloudAPI.API.pricing import api_v1_pricing from SWSCloudCore import models from SWSCloudCore.models import database from SWSCloudCore.config import config app = Flask(__name__) +app.config["APPLICATION_ROOT"] = "/api/v1" # app.config['SERVER_NAME'] = settings.get('Application', 'SERVER_NAME') app.config['DEBUG'] = config.getboolean('Application', 'DEBUG') app.config['SECRET_KEY'] = config.get("Application", "SECRET_KEY") app.register_blueprint(api) +app.register_blueprint(api_v1_vms) +app.register_blueprint(api_v1_containers) +app.register_blueprint(api_v1_pricing) +app.register_blueprint(api_v1_datacenters) @app.errorhandler(404) diff --git a/SWSCloudCore/templates/default/payment/robokassa/result.html b/SWSCloudCore/templates/default/payment/robokassa/result.html deleted file mode 100644 index e69de29..0000000 diff --git a/SWSCloudCore/templates/default/vms/details.html b/SWSCloudCore/templates/default/vms/details.html deleted file mode 100644 index e69de29..0000000 diff --git a/SWSCloudCore/views/account/decorators.py b/SWSCloudCore/views/account/decorators.py deleted file mode 100644 index e69de29..0000000