refactoting and new apiv2
This commit is contained in:
parent
9261b24730
commit
999452a488
20 changed files with 462 additions and 130 deletions
|
@ -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 <email>:<secret>
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
return jsonify(user_id=g.user_id)
|
|
|
@ -2,6 +2,7 @@
|
||||||
from SWSCloudCore.controllers.users import ControllerAPI
|
from SWSCloudCore.controllers.users import ControllerAPI
|
||||||
from SWSCloudCore.controllers.users import ControllerUsers
|
from SWSCloudCore.controllers.users import ControllerUsers
|
||||||
|
|
||||||
|
from flask import g
|
||||||
from flask_httpauth import HTTPBasicAuth
|
from flask_httpauth import HTTPBasicAuth
|
||||||
|
|
||||||
auth = HTTPBasicAuth()
|
auth = HTTPBasicAuth()
|
||||||
|
|
4
SWSCloudAPI/API/compute/v1/views/__init__.py
Normal file
4
SWSCloudAPI/API/compute/v1/views/__init__.py
Normal file
|
@ -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
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
TOKEN_TTL = 1800
|
TOKEN_TTL = 1800
|
||||||
TOKEN_PREFIX = 'token_'
|
TOKEN_PREFIX = 'token_'
|
||||||
|
|
||||||
|
|
1
SWSCloudAPI/API/compute/v2/utils/__init__.py
Normal file
1
SWSCloudAPI/API/compute/v2/utils/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from .tokens import Tokens
|
34
SWSCloudAPI/API/compute/v2/utils/decorators.py
Normal file
34
SWSCloudAPI/API/compute/v2/utils/decorators.py
Normal file
|
@ -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
|
72
SWSCloudAPI/API/compute/v2/utils/tokens.py
Normal file
72
SWSCloudAPI/API/compute/v2/utils/tokens.py
Normal file
|
@ -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())
|
4
SWSCloudAPI/API/compute/v2/views/__init__.py
Normal file
4
SWSCloudAPI/API/compute/v2/views/__init__.py
Normal file
|
@ -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
|
251
SWSCloudAPI/API/compute/v2/views/containers.py
Normal file
251
SWSCloudAPI/API/compute/v2/views/containers.py
Normal file
|
@ -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 <email>:<secret>
|
||||||
|
: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 <email>:<secret> -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 = '<br/>\n'.join(message_parts)
|
||||||
|
subject = u'GoCloud.ru: Новый контейнер'
|
||||||
|
lead = u"""Поздравляем с новым контейнером."""
|
||||||
|
callout = u"""
|
||||||
|
Для входа в личный кабинет воспользуйтесь
|
||||||
|
<a href="https://gocloud.ru/account/login">страницей авторизации</a>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
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/<uuid:container_id>', methods=['DELETE'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
|
def container_delete(container_id):
|
||||||
|
"""
|
||||||
|
curl -X DELETE http://gocloud.ru/api/v1/container/<uuid:container_id> -u <email>:<secret> -d "container_id=<uuid: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('/<uuid:container_id>', methods=['GET'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
|
def container_info(container_id):
|
||||||
|
"""
|
||||||
|
curl -X GET http://localhost:5000/api/v1/container/<uuid:container_id> -u <email>:<secret>
|
||||||
|
: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('/<uuid:container_id>', methods=['POST'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
|
def container_actions(container_id):
|
||||||
|
"""
|
||||||
|
curl -X POST http://localhost:5000/api/v1/container/<uuid:container_id> -u <email>:<secret> -d "status=inactive"
|
||||||
|
curl -X POST http://localhost:5000/api/v1/container/<uuid:container_id> -u <email>:<secret> -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')
|
|
@ -3,27 +3,24 @@
|
||||||
from flask import Blueprint, jsonify, request, g
|
from flask import Blueprint, jsonify, request, g
|
||||||
from SWSCloudAPI.API.compute.v2.common import *
|
from SWSCloudAPI.API.compute.v2.common import *
|
||||||
from SWSCloudCore.models import DataCenters
|
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 = Blueprint('v2datacenters', __name__, url_prefix='/api/compute/v2/datacenters')
|
||||||
|
|
||||||
|
|
||||||
@api_v2_datacenters.route('/', methods=['GET'])
|
@api_v2_datacenters.route('/', methods=['GET'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def datacenter_list():
|
def datacenter_list():
|
||||||
"""
|
"""Get containers list
|
||||||
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"
|
||||||
curl -X http://localhost:5000/api/compute/v1/datacenters/ -u <email>:<secret>
|
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tokens = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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()
|
dc_list = DataCenters.get_available()
|
|
@ -1,28 +1,26 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from flask import Blueprint, jsonify, request, g
|
from flask import Blueprint, jsonify, request, g
|
||||||
from SWSCloudAPI.API.compute.v2.common import *
|
|
||||||
from SWSCloudCore.controllers.plans import ControllerPlans
|
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 = Blueprint('v2pricing', __name__, url_prefix='/api/compute/v2/pricing')
|
||||||
|
|
||||||
|
|
||||||
@api_v2_pricing.route('/')
|
@api_v2_pricing.route('/')
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def pricing():
|
def pricing():
|
||||||
"""get pricing list
|
"""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"
|
curl -XGET http://localhost:5001/api/compute/v2/pricing/ -H "X-Auth-Token: ad89abee-49bc-4434-98ee-c7598c2f0adc" -H "Content-Type: application/json"
|
||||||
|
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
#
|
||||||
return jsonify(status='fail', message='content-type must be application/json')
|
tokens = Tokens()
|
||||||
|
|
||||||
# check exists token
|
|
||||||
if not g.tokens.exists(TOKEN_PREFIX + request.headers.get('X-Auth-Token')):
|
|
||||||
return jsonify(status='fail', message='token not exists')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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')
|
payload = ControllerPlans().get_plans(status='active')
|
||||||
return jsonify(status='ok', payload=payload)
|
return jsonify(status='ok', payload=payload)
|
|
@ -1,16 +1,16 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
import json
|
|
||||||
import validators
|
import validators
|
||||||
from uuid import uuid4
|
from flask import Blueprint, jsonify, request, g
|
||||||
from flask import Blueprint, jsonify, g, request
|
|
||||||
from SWSCloudCore.models import Users
|
from SWSCloudCore.models import Users
|
||||||
from SWSCloudAPI.API.compute.v2.common import *
|
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 = Blueprint('v2token', __name__, url_prefix='/api/compute/v2/token')
|
||||||
|
|
||||||
|
|
||||||
@api_v2_token.route('/', methods=['POST'])
|
@api_v2_token.route('/', methods=['POST'])
|
||||||
|
@decorators.content_type
|
||||||
def token_post():
|
def token_post():
|
||||||
"""Get token
|
"""Get token
|
||||||
|
|
||||||
|
@ -25,9 +25,6 @@ def token_post():
|
||||||
}
|
}
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
#
|
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
|
||||||
return jsonify(status='fail', message='content-type must be application/json')
|
|
||||||
# validate email
|
# validate email
|
||||||
if not validators.email(request.json.get('email')):
|
if not validators.email(request.json.get('email')):
|
||||||
return jsonify(status='fail', message='invalid email format')
|
return jsonify(status='fail', message='invalid email format')
|
||||||
|
@ -36,30 +33,35 @@ def token_post():
|
||||||
return jsonify(status='fail', message='invalid auth')
|
return jsonify(status='fail', message='invalid auth')
|
||||||
# get user data
|
# get user data
|
||||||
user = Users.get_by_email(request.json.get('email'))
|
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))
|
return jsonify(status='ok', payload=dict(token=token))
|
||||||
|
|
||||||
|
|
||||||
@api_v2_token.route('/', methods=['GET'])
|
@api_v2_token.route('/', methods=['GET'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def token_get():
|
def token_get():
|
||||||
"""Get token data
|
"""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"
|
curl -XGET http://localhost:5001/api/compute/v2/token/ -H "X-Auth-Token: 422f45a4-eab9-4a79-9954-61c568bae0eb" -H "Content-Type: application/json"
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tok = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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(
|
# ttl=g.tokens.ttl('token_'+request.headers.get('X-Auth-Token')),
|
||||||
status='ok',
|
# pttl=g.tokens.pttl('token_'+request.headers.get('X-Auth-Token')),
|
||||||
# ttl=g.tokens.ttl('token_'+request.headers.get('X-Auth-Token')),
|
return jsonify(status='ok', payload=tok.get(g.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')))
|
|
||||||
)
|
@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')
|
|
@ -1,9 +1,7 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
import json
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from flask import Blueprint, jsonify, request, g
|
from flask import Blueprint, jsonify, request, g
|
||||||
from SWSCloudAPI.API.compute.v2.common import *
|
|
||||||
from SWSCloudCore.controllers.ips import ControllerIps
|
from SWSCloudCore.controllers.ips import ControllerIps
|
||||||
from SWSCloudCore.controllers.plans import ControllerPlans
|
from SWSCloudCore.controllers.plans import ControllerPlans
|
||||||
from SWSCloudCore.controllers.users import ControllerUsers
|
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.common import ControllerCommon, ControllerMessagesEmail
|
||||||
from SWSCloudCore.controllers.tasks import ControllerTasks
|
from SWSCloudCore.controllers.tasks import ControllerTasks
|
||||||
from SWSCloudCore.controllers.vms import ControllerVMS
|
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 = Blueprint('v2vms', __name__, url_prefix='/api/compute/v2/vms')
|
||||||
|
|
||||||
|
|
||||||
@api_v2_vms.route('/', methods=['GET'])
|
@api_v2_vms.route('/', methods=['GET'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def vms_list():
|
def vms_list():
|
||||||
"""
|
"""
|
||||||
get virtual servers list
|
get virtual servers list
|
||||||
curl -X POST http://localhost:5000/api/v1/vms/ -u <email>:<secret>
|
curl -X POST http://localhost:5000/api/v1/vms/ -u <email>:<secret>
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tokens = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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())
|
return jsonify(status='ok', payload=ControllerVMS(user.get('user_id')).get_items())
|
||||||
|
|
||||||
|
|
||||||
@api_v2_vms.route('/', methods=['POST'])
|
@api_v2_vms.route('/', methods=['POST'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def vms_create():
|
def vms_create():
|
||||||
"""
|
"""
|
||||||
curl -XPOST /api/v1/vms/ -u <email>:<secret> -d 'plan=<uuid>&datacenter=<uuid>'
|
curl -XPOST /api/v1/vms/ -u <email>:<secret> -d 'plan=<uuid>&datacenter=<uuid>'
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tokens = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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_balance = ControllerBilling().get(user.get('user_id'))
|
||||||
user_ssh = ControllerSSHKey(user.get('user_id'))
|
user_ssh = ControllerSSHKey(user.get('user_id'))
|
||||||
controller_plans = ControllerPlans()
|
controller_plans = ControllerPlans()
|
||||||
|
@ -200,19 +194,16 @@ def vms_create():
|
||||||
|
|
||||||
|
|
||||||
@api_v2_vms.route('/<uuid:vm_id>', methods=['POST'])
|
@api_v2_vms.route('/<uuid:vm_id>', methods=['POST'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def vm_actions(vm_id):
|
def vm_actions(vm_id):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tokens = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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)
|
||||||
|
|
||||||
# init ...
|
# init ...
|
||||||
vm = ControllerVMS(user.get('user_id'))
|
vm = ControllerVMS(user.get('user_id'))
|
||||||
|
@ -244,47 +235,41 @@ def vm_actions(vm_id):
|
||||||
vm_details.server.id,
|
vm_details.server.id,
|
||||||
'vm_stop',
|
'vm_stop',
|
||||||
0,
|
0,
|
||||||
vm_id=vm_id
|
vm_id=vm_id)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@api_v2_vms.route('/<uuid:vm_id>', methods=['DELETE'])
|
@api_v2_vms.route('/<uuid:vm_id>', methods=['DELETE'])
|
||||||
|
@decorators.content_type
|
||||||
|
@decorators.auth_token
|
||||||
def vm_delete(vm_id):
|
def vm_delete(vm_id):
|
||||||
"""
|
"""
|
||||||
Удаление виртуального сервера
|
Удаление виртуального сервера
|
||||||
:param vm_id:
|
:param vm_id:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if request.headers.get('Content-Type') != 'application/json':
|
tokens = Tokens()
|
||||||
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')
|
|
||||||
|
|
||||||
# TODO: move to different endpoint
|
# 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'))
|
vms = ControllerVMS(user.get('user_id'))
|
||||||
tasks = ControllerTasks(user.get('user_id'))
|
tasks = ControllerTasks(user.get('user_id'))
|
||||||
|
|
||||||
# check the user have a selected rule
|
# check the user have a selected rule
|
||||||
# if user not have a container then redirect to the container list
|
# if user not have a container then redirect to the container list
|
||||||
if not vms.exists(vm_id):
|
if not vms.exists(vm_id):
|
||||||
return jsonify(message='not exists')
|
return jsonify(message='not exists')
|
||||||
|
|
||||||
# get container details
|
# get container details
|
||||||
vm_details = vms.get(vm_id)
|
vm_details = vms.get(vm_id)
|
||||||
|
|
||||||
# Обновляем статус "5" для правила
|
# Обновляем статус "5" для правила
|
||||||
vms.set_status(vm_id, 5)
|
vms.set_status(vm_id, 5)
|
||||||
|
|
||||||
# Создание задания
|
# Создание задания
|
||||||
tasks.create(
|
models.Tasks.set_task(vm_details.datacenter.id, vm_details.server.id, vm_details.user.id, 'vm_delete', 0, vm_id=vm_id)
|
||||||
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')
|
return jsonify(status=0, message='ok')
|
|
@ -1,22 +1,17 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
import redis
|
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 flask import Flask, g, jsonify
|
||||||
|
|
||||||
from SWSCloudCore import models
|
from SWSCloudCore import models
|
||||||
from SWSCloudCore.config import config
|
from SWSCloudCore.config import config
|
||||||
from SWSCloudCore.models import database
|
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 = Flask(__name__)
|
||||||
# Думал, что получится сделать автопрефик для всего приложения, но это не сработало
|
# Думал, что получится сделать автопрефик для всего приложения, но это не сработало
|
||||||
# app.config["APPLICATION_ROOT"] = "/api/v1"
|
# app.config["APPLICATION_ROOT"] = "/api/v1"
|
||||||
|
@ -24,13 +19,17 @@ app = Flask(__name__)
|
||||||
app.config['DEBUG'] = config.getboolean('Application', 'DEBUG')
|
app.config['DEBUG'] = config.getboolean('Application', 'DEBUG')
|
||||||
app.config['SECRET_KEY'] = config.get("Application", "SECRET_KEY")
|
app.config['SECRET_KEY'] = config.get("Application", "SECRET_KEY")
|
||||||
|
|
||||||
|
# V1
|
||||||
app.register_blueprint(api_v1_vms)
|
app.register_blueprint(api_v1_vms)
|
||||||
app.register_blueprint(api_v1_containers)
|
app.register_blueprint(api_v1_containers)
|
||||||
app.register_blueprint(api_v1_pricing)
|
app.register_blueprint(api_v1_pricing)
|
||||||
app.register_blueprint(api_v1_datacenters)
|
app.register_blueprint(api_v1_datacenters)
|
||||||
|
|
||||||
|
# V2
|
||||||
app.register_blueprint(api_v2_token)
|
app.register_blueprint(api_v2_token)
|
||||||
app.register_blueprint(api_v2_pricing)
|
app.register_blueprint(api_v2_pricing)
|
||||||
app.register_blueprint(api_v2_datacenters)
|
app.register_blueprint(api_v2_datacenters)
|
||||||
|
app.register_blueprint(api_v2_vms)
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
|
|
0
SWSCloudCore/compute/__init__.py
Normal file
0
SWSCloudCore/compute/__init__.py
Normal file
|
@ -1,5 +1,6 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
|
import json
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
import datetime
|
import datetime
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -314,22 +315,21 @@ class Tasks(PgSQLModel):
|
||||||
Tasks.select().where(Tasks.status == status).count()
|
Tasks.select().where(Tasks.status == status).count()
|
||||||
return Tasks.select().count()
|
return Tasks.select().count()
|
||||||
|
|
||||||
# @staticmethod
|
@staticmethod
|
||||||
# def set_task(datacenter_id, server_id, task, status, **args):
|
def set_task(datacenter_id, server_id, user_id, task, status, **args):
|
||||||
# task_id = uuid.uuid4()
|
task_id = uuid.uuid4()
|
||||||
# plain = dict()
|
plain = dict()
|
||||||
# for arg in args:
|
for arg in args:
|
||||||
# plain[arg] = str(args[arg])
|
plain[arg] = str(args[arg])
|
||||||
#
|
|
||||||
# Tasks.create(
|
Tasks.create(
|
||||||
# id=task_id,
|
id=task_id,
|
||||||
# datacenter=datacenter_id,
|
datacenter=datacenter_id,
|
||||||
# server=server_id,
|
server=server_id,
|
||||||
# task=task,
|
task=task,
|
||||||
# status=status,
|
status=status,
|
||||||
# user=self.user_id,
|
user=user_id,
|
||||||
# plain=json.dumps(plain)
|
plain=json.dumps(plain))
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
class Settings(PgSQLModel):
|
class Settings(PgSQLModel):
|
||||||
|
|
Loading…
Add table
Reference in a new issue