diff --git a/SWSCloudAPI/API/compute/v1/api.py b/SWSCloudAPI/API/compute/v1/api.py deleted file mode 100644 index 7d14c62..0000000 --- a/SWSCloudAPI/API/compute/v1/api.py +++ /dev/null @@ -1,17 +0,0 @@ -# coding: utf-8 - -from flask import Blueprint, jsonify, g - -from SWSCloudAPI.API.compute.v1.common import auth - -api_v1 = Blueprint('api', __name__, url_prefix='/api/compute/v1') - - -@api_v1.route('/') -@auth.login_required -def index(): - """ - curl -X POST http://localhost:5000/api/v1/ -u : - :return: - """ - return jsonify(user_id=g.user_id) diff --git a/SWSCloudAPI/API/compute/v1/common.py b/SWSCloudAPI/API/compute/v1/common.py index 901393e..edcdefc 100644 --- a/SWSCloudAPI/API/compute/v1/common.py +++ b/SWSCloudAPI/API/compute/v1/common.py @@ -2,6 +2,7 @@ from SWSCloudCore.controllers.users import ControllerAPI from SWSCloudCore.controllers.users import ControllerUsers +from flask import g from flask_httpauth import HTTPBasicAuth auth = HTTPBasicAuth() diff --git a/SWSCloudAPI/API/compute/v1/views/__init__.py b/SWSCloudAPI/API/compute/v1/views/__init__.py new file mode 100644 index 0000000..3632f5e --- /dev/null +++ b/SWSCloudAPI/API/compute/v1/views/__init__.py @@ -0,0 +1,4 @@ +from .containers import api_v1_containers +from .datacenters import api_v1_datacenters +from .pricing import api_v1_pricing +from .vms import api_v1_vms diff --git a/SWSCloudAPI/API/compute/v1/containers.py b/SWSCloudAPI/API/compute/v1/views/containers.py similarity index 100% rename from SWSCloudAPI/API/compute/v1/containers.py rename to SWSCloudAPI/API/compute/v1/views/containers.py diff --git a/SWSCloudAPI/API/compute/v1/datacenters.py b/SWSCloudAPI/API/compute/v1/views/datacenters.py similarity index 100% rename from SWSCloudAPI/API/compute/v1/datacenters.py rename to SWSCloudAPI/API/compute/v1/views/datacenters.py diff --git a/SWSCloudAPI/API/compute/v1/pricing.py b/SWSCloudAPI/API/compute/v1/views/pricing.py similarity index 100% rename from SWSCloudAPI/API/compute/v1/pricing.py rename to SWSCloudAPI/API/compute/v1/views/pricing.py diff --git a/SWSCloudAPI/API/compute/v1/vms.py b/SWSCloudAPI/API/compute/v1/views/vms.py similarity index 100% rename from SWSCloudAPI/API/compute/v1/vms.py rename to SWSCloudAPI/API/compute/v1/views/vms.py diff --git a/SWSCloudAPI/API/compute/v2/common.py b/SWSCloudAPI/API/compute/v2/common.py index 1a10d2b..e40193e 100644 --- a/SWSCloudAPI/API/compute/v2/common.py +++ b/SWSCloudAPI/API/compute/v2/common.py @@ -1,3 +1,4 @@ TOKEN_TTL = 1800 TOKEN_PREFIX = 'token_' + diff --git a/SWSCloudAPI/API/compute/v2/utils/__init__.py b/SWSCloudAPI/API/compute/v2/utils/__init__.py new file mode 100644 index 0000000..3264e5b --- /dev/null +++ b/SWSCloudAPI/API/compute/v2/utils/__init__.py @@ -0,0 +1 @@ +from .tokens import Tokens diff --git a/SWSCloudAPI/API/compute/v2/utils/decorators.py b/SWSCloudAPI/API/compute/v2/utils/decorators.py new file mode 100644 index 0000000..27d9178 --- /dev/null +++ b/SWSCloudAPI/API/compute/v2/utils/decorators.py @@ -0,0 +1,34 @@ + + +from functools import wraps +from flask import g, request, redirect, url_for, jsonify + + +# def login_required(f): +# @wraps(f) +# def decorated_function(*args, **kwargs): +# if g.user is None: +# return redirect(url_for('login', next=request.url)) +# return f(*args, **kwargs) +# return decorated_function + +def content_type(f): + @wraps(f) + def decorated_function(*args, **kwargs): + if request.headers.get('Content-Type') != 'application/json': + return jsonify(status='error', message='content-type must be application/json') + return f(*args, **kwargs) + return decorated_function + + +def auth_token(f): + @wraps(f) + def decorated_function(*args, **kwargs): + g.auth_token = request.headers.get('X-Auth-Token', None) + if not g.auth_token: + return jsonify(status='error', message='X-Auth-Token not specified') + # check exists token + if not g.tokens.exists(g.auth_token): + return jsonify(status='error', message='token not exists') + return f(*args, **kwargs) + return decorated_function diff --git a/SWSCloudAPI/API/compute/v2/utils/tokens.py b/SWSCloudAPI/API/compute/v2/utils/tokens.py new file mode 100644 index 0000000..b316ea0 --- /dev/null +++ b/SWSCloudAPI/API/compute/v2/utils/tokens.py @@ -0,0 +1,72 @@ +import json +import uuid +from flask import g +from ..common import TOKEN_PREFIX + + +class Tokens(object): + @staticmethod + def set(token, payload, ttl=1800): + """Create new token + + Example + >>> Tokens.set('d0dd3bfa-e0f2-11e6-a2ce-17cec9ffa761', {'user_id': 1}, 1800) + + :param token: UUID + :param payload: dict + :param ttl: int + :return: boolean + """ + g.tokens.set(TOKEN_PREFIX + token, json.dumps(payload), ttl) + return True + + @staticmethod + def get(token): + """Get token data + + >>> Tokens.get('d0dd3bfa-e0f2-11e6-a2ce-17cec9ffa761') + """ + return json.loads(g.tokens.get(TOKEN_PREFIX + token)) + + @staticmethod + def expire(token, ttl=1800): + """ + + >>> Tokens.expire('d0dd3bfa-e0f2-11e6-a2ce-17cec9ffa761', 1800) + + :param token: uuid + :param ttl: int + :return: boolean + """ + g.tokens.expire(TOKEN_PREFIX + token, ttl) + return True + + @staticmethod + def exists(token): + """Check exists token in redis + + :param token: uuid + :return: boolean + """ + if g.tokens.exists(TOKEN_PREFIX + token): + return True + return False + + @staticmethod + def delete(token): + try: + g.tokens.delete(TOKEN_PREFIX + token) + except: + return False + else: + return True + + @staticmethod + def generate_id(): + """Generate UUID strinfg + + >>> Tokens.generate_id() + + :return: str + """ + return str(uuid.uuid4()) diff --git a/SWSCloudAPI/API/compute/v2/views/__init__.py b/SWSCloudAPI/API/compute/v2/views/__init__.py new file mode 100644 index 0000000..9be0b29 --- /dev/null +++ b/SWSCloudAPI/API/compute/v2/views/__init__.py @@ -0,0 +1,4 @@ +from .datacenters import api_v2_datacenters +from .pricing import api_v2_pricing +from .token import api_v2_token +from .vms import api_v2_vms diff --git a/SWSCloudAPI/API/compute/v2/views/containers.py b/SWSCloudAPI/API/compute/v2/views/containers.py new file mode 100644 index 0000000..54b6147 --- /dev/null +++ b/SWSCloudAPI/API/compute/v2/views/containers.py @@ -0,0 +1,251 @@ +# coding: utf-8 + +from uuid import uuid4 +from flask import Blueprint, jsonify, request, g +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) +from SWSCloudAPI.API.compute.v2.utils import Tokens, decorators + +api_v2_containers = Blueprint('v2containers', __name__, url_prefix='/api/compute/v2/containers') + + +@api_v2_containers.route('/', methods=['GET']) +@decorators.content_type +@decorators.auth_token +def containers_list(): + """ + curl -X GET http://localhost:5000/api/v1/containers/ -u : + :return: + """ + tokens = Tokens() + + # get containers list + containers = ControllerContainers(g.user_id).get_items() + # + return jsonify(total=containers['total'], items=containers['items']) + + +@api_v2_containers.route('/', methods=['POST']) +@decorators.content_type +@decorators.auth_token +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') + + tokens = Tokens() + + # 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_v2_containers.route('/container/', methods=['DELETE']) +@decorators.content_type +@decorators.auth_token +def container_delete(container_id): + """ + curl -X DELETE http://gocloud.ru/api/v1/container/ -u : -d "container_id=" + :return: + """ + auth_token = request.headers.get('X-Auth-Token') + tokens = Tokens() + + 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_v2_containers.route('/', methods=['GET']) +@decorators.content_type +@decorators.auth_token +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_v2_containers.route('/', methods=['POST']) +@decorators.content_type +@decorators.auth_token +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/compute/v2/datacenters.py b/SWSCloudAPI/API/compute/v2/views/datacenters.py similarity index 52% rename from SWSCloudAPI/API/compute/v2/datacenters.py rename to SWSCloudAPI/API/compute/v2/views/datacenters.py index 9e933c4..0667faf 100644 --- a/SWSCloudAPI/API/compute/v2/datacenters.py +++ b/SWSCloudAPI/API/compute/v2/views/datacenters.py @@ -3,27 +3,24 @@ from flask import Blueprint, jsonify, request, g from SWSCloudAPI.API.compute.v2.common import * from SWSCloudCore.models import DataCenters - +from SWSCloudAPI.API.compute.v2.utils import Tokens, decorators api_v2_datacenters = Blueprint('v2datacenters', __name__, url_prefix='/api/compute/v2/datacenters') @api_v2_datacenters.route('/', methods=['GET']) +@decorators.content_type +@decorators.auth_token def datacenter_list(): - """ - get containers list - curl -X http://localhost:5000/api/compute/v1/datacenters/ -u : + """Get containers list + curl -X http://localhost:5000/api/compute/v2/datacenters/ -H "X-Auth-Token: a90bb6cd-681f-4f87-b1ca-ea30921e3440" -H "Content-Type: application/json" + :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) + tokens.expire(g.token_auth, TOKEN_TTL) # dc_list = DataCenters.get_available() diff --git a/SWSCloudAPI/API/compute/v2/pricing.py b/SWSCloudAPI/API/compute/v2/views/pricing.py similarity index 61% rename from SWSCloudAPI/API/compute/v2/pricing.py rename to SWSCloudAPI/API/compute/v2/views/pricing.py index 5ed720a..b4974b7 100644 --- a/SWSCloudAPI/API/compute/v2/pricing.py +++ b/SWSCloudAPI/API/compute/v2/views/pricing.py @@ -1,28 +1,26 @@ # coding: utf-8 from flask import Blueprint, jsonify, request, g -from SWSCloudAPI.API.compute.v2.common import * from SWSCloudCore.controllers.plans import ControllerPlans +from SWSCloudAPI.API.compute.v2.common import * +from SWSCloudAPI.API.compute.v2.utils import Tokens, decorators api_v2_pricing = Blueprint('v2pricing', __name__, url_prefix='/api/compute/v2/pricing') @api_v2_pricing.route('/') +@decorators.content_type +@decorators.auth_token def pricing(): """get pricing list curl -XGET http://localhost:5001/api/compute/v2/pricing/ -H "X-Auth-Token: ad89abee-49bc-4434-98ee-c7598c2f0adc" -H "Content-Type: application/json" :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') - + # + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) - + tokens.expire(g.auth_token, TOKEN_TTL) + # payload = ControllerPlans().get_plans(status='active') return jsonify(status='ok', payload=payload) diff --git a/SWSCloudAPI/API/compute/v2/token.py b/SWSCloudAPI/API/compute/v2/views/token.py similarity index 55% rename from SWSCloudAPI/API/compute/v2/token.py rename to SWSCloudAPI/API/compute/v2/views/token.py index c48635d..d42e055 100644 --- a/SWSCloudAPI/API/compute/v2/token.py +++ b/SWSCloudAPI/API/compute/v2/views/token.py @@ -1,16 +1,16 @@ # coding: utf-8 -import json import validators -from uuid import uuid4 -from flask import Blueprint, jsonify, g, request +from flask import Blueprint, jsonify, request, g from SWSCloudCore.models import Users from SWSCloudAPI.API.compute.v2.common import * +from SWSCloudAPI.API.compute.v2.utils import Tokens, decorators api_v2_token = Blueprint('v2token', __name__, url_prefix='/api/compute/v2/token') @api_v2_token.route('/', methods=['POST']) +@decorators.content_type def token_post(): """Get token @@ -25,9 +25,6 @@ def token_post(): } :return: """ - # - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') # validate email if not validators.email(request.json.get('email')): return jsonify(status='fail', message='invalid email format') @@ -36,30 +33,35 @@ def token_post(): return jsonify(status='fail', message='invalid auth') # get user data user = Users.get_by_email(request.json.get('email')) - token = str(uuid4()) - g.tokens.set(TOKEN_PREFIX + token, json.dumps(dict(user_id=str(user.id))), TOKEN_TTL) + + token = Tokens.generate_id() + Tokens.set(token, dict(user_id=str(user.id)), TOKEN_TTL) + return jsonify(status='ok', payload=dict(token=token)) @api_v2_token.route('/', methods=['GET']) +@decorators.content_type +@decorators.auth_token def token_get(): """Get token data curl -XGET http://localhost:5001/api/compute/v2/token/ -H "X-Auth-Token: 422f45a4-eab9-4a79-9954-61c568bae0eb" -H "Content-Type: application/json" :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tok = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) + tok.expire(g.auth_token, TOKEN_TTL) - return jsonify( - status='ok', - # ttl=g.tokens.ttl('token_'+request.headers.get('X-Auth-Token')), - # pttl=g.tokens.pttl('token_'+request.headers.get('X-Auth-Token')), - payload=json.loads(g.tokens.get(TOKEN_PREFIX + request.headers.get('X-Auth-Token'))) - ) + # ttl=g.tokens.ttl('token_'+request.headers.get('X-Auth-Token')), + # pttl=g.tokens.pttl('token_'+request.headers.get('X-Auth-Token')), + return jsonify(status='ok', payload=tok.get(g.auth_token)) + + +@api_v2_token.route('/', methods=['DELETE']) +@decorators.content_type +@decorators.auth_token +def token_delete(): + tok = Tokens() + tok.delete(g.auth_token) + return jsonify(status='ok') diff --git a/SWSCloudAPI/API/compute/v2/vms.py b/SWSCloudAPI/API/compute/v2/views/vms.py similarity index 77% rename from SWSCloudAPI/API/compute/v2/vms.py rename to SWSCloudAPI/API/compute/v2/views/vms.py index f3088d6..eb64979 100644 --- a/SWSCloudAPI/API/compute/v2/vms.py +++ b/SWSCloudAPI/API/compute/v2/views/vms.py @@ -1,9 +1,7 @@ # coding: utf-8 -import json from uuid import uuid4 from flask import Blueprint, jsonify, request, g -from SWSCloudAPI.API.compute.v2.common import * from SWSCloudCore.controllers.ips import ControllerIps from SWSCloudCore.controllers.plans import ControllerPlans from SWSCloudCore.controllers.users import ControllerUsers @@ -12,52 +10,48 @@ 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 +from SWSCloudCore import models +from SWSCloudAPI.API.compute.v2.common import * +from SWSCloudAPI.API.compute.v2.utils import Tokens, decorators api_v2_vms = Blueprint('v2vms', __name__, url_prefix='/api/compute/v2/vms') @api_v2_vms.route('/', methods=['GET']) +@decorators.content_type +@decorators.auth_token def vms_list(): """ get virtual servers list curl -X POST http://localhost:5000/api/v1/vms/ -u : :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) + tokens.expire(g.auth_token, TOKEN_TTL) - user = json.loads(g.tokens.get(TOKEN_PREFIX + request.headers.get('X-Auth-Token'))) + user = tokens.get(g.auth_token) return jsonify(status='ok', payload=ControllerVMS(user.get('user_id')).get_items()) @api_v2_vms.route('/', methods=['POST']) +@decorators.content_type +@decorators.auth_token def vms_create(): """ curl -XPOST /api/v1/vms/ -u : -d 'plan=&datacenter=' :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) + tokens.expire(g.auth_token, TOKEN_TTL) - user = json.loads(g.tokens.get(TOKEN_PREFIX + request.headers.get('X-Auth-Token'))) + user = tokens.get(g.auth_token) # - user_balance = ControllerBilling().get(user.get('user_id')) user_ssh = ControllerSSHKey(user.get('user_id')) controller_plans = ControllerPlans() @@ -200,19 +194,16 @@ def vms_create(): @api_v2_vms.route('/', methods=['POST']) +@decorators.content_type +@decorators.auth_token def vm_actions(vm_id): """ """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) - user = json.loads(g.tokens.get(TOKEN_PREFIX + request.headers.get('X-Auth-Token'))) + tokens.expire(g.auth_token, TOKEN_TTL) + user = tokens.get(g.auth_token) # init ... vm = ControllerVMS(user.get('user_id')) @@ -244,47 +235,41 @@ def vm_actions(vm_id): vm_details.server.id, 'vm_stop', 0, - vm_id=vm_id - ) + vm_id=vm_id) @api_v2_vms.route('/', methods=['DELETE']) +@decorators.content_type +@decorators.auth_token def vm_delete(vm_id): """ Удаление виртуального сервера :param vm_id: :return: """ - if request.headers.get('Content-Type') != 'application/json': - return jsonify(status='fail', message='content-type must be application/json') - - # check exists token - if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')): - return jsonify(status='fail', message='token not exists') + tokens = Tokens() # TODO: move to different endpoint - g.tokens.expire(TOKEN_PREFIX + request.headers.get('X-Auth-Token'), TOKEN_TTL) + tokens.expire(g.auth_token, TOKEN_TTL) - user = json.loads(g.tokens.get(TOKEN_PREFIX + request.headers.get('X-Auth-Token'))) + user = tokens.get(g.auth_token) # vms = ControllerVMS(user.get('user_id')) tasks = ControllerTasks(user.get('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 - ) + models.Tasks.set_task(vm_details.datacenter.id, vm_details.server.id, vm_details.user.id, 'vm_delete', 0, vm_id=vm_id) + return jsonify(status=0, message='ok') diff --git a/SWSCloudAPI/application.py b/SWSCloudAPI/application.py index 60583b2..695a505 100644 --- a/SWSCloudAPI/application.py +++ b/SWSCloudAPI/application.py @@ -1,22 +1,17 @@ # coding: utf-8 import redis - -from SWSCloudAPI.API.compute.v1.datacenters import api_v1_datacenters -from SWSCloudAPI.API.compute.v1.containers import api_v1_containers -from SWSCloudAPI.API.compute.v1.pricing import api_v1_pricing -from SWSCloudAPI.API.compute.v1.vms import api_v1_vms -from SWSCloudAPI.API.compute.v2.token import api_v2_token -from SWSCloudAPI.API.compute.v2.pricing import api_v2_pricing -from SWSCloudAPI.API.compute.v2.datacenters import api_v2_datacenters -from SWSCloudAPI.API.compute.v2.vms import api_v2_vms - from flask import Flask, g, jsonify from SWSCloudCore import models from SWSCloudCore.config import config from SWSCloudCore.models import database +# v1 +from SWSCloudAPI.API.compute.v1.views import * +# v2 +from SWSCloudAPI.API.compute.v2.views import * + app = Flask(__name__) # Думал, что получится сделать автопрефик для всего приложения, но это не сработало # app.config["APPLICATION_ROOT"] = "/api/v1" @@ -24,13 +19,17 @@ app = Flask(__name__) app.config['DEBUG'] = config.getboolean('Application', 'DEBUG') app.config['SECRET_KEY'] = config.get("Application", "SECRET_KEY") +# V1 app.register_blueprint(api_v1_vms) app.register_blueprint(api_v1_containers) app.register_blueprint(api_v1_pricing) app.register_blueprint(api_v1_datacenters) + +# V2 app.register_blueprint(api_v2_token) app.register_blueprint(api_v2_pricing) app.register_blueprint(api_v2_datacenters) +app.register_blueprint(api_v2_vms) @app.errorhandler(404) diff --git a/SWSCloudCore/compute/__init__.py b/SWSCloudCore/compute/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/SWSCloudCore/models.py b/SWSCloudCore/models.py index 1834b51..2ff2379 100644 --- a/SWSCloudCore/models.py +++ b/SWSCloudCore/models.py @@ -1,5 +1,6 @@ # coding: utf-8 +import json from hashlib import md5 import datetime import uuid @@ -314,22 +315,21 @@ class Tasks(PgSQLModel): Tasks.select().where(Tasks.status == status).count() return Tasks.select().count() - # @staticmethod - # def set_task(datacenter_id, server_id, task, status, **args): - # task_id = uuid.uuid4() - # plain = dict() - # for arg in args: - # plain[arg] = str(args[arg]) - # - # Tasks.create( - # id=task_id, - # datacenter=datacenter_id, - # server=server_id, - # task=task, - # status=status, - # user=self.user_id, - # plain=json.dumps(plain) - # ) + @staticmethod + def set_task(datacenter_id, server_id, user_id, task, status, **args): + task_id = uuid.uuid4() + plain = dict() + for arg in args: + plain[arg] = str(args[arg]) + + Tasks.create( + id=task_id, + datacenter=datacenter_id, + server=server_id, + task=task, + status=status, + user=user_id, + plain=json.dumps(plain)) class Settings(PgSQLModel):