diff --git a/README.md b/README.md
index 9e381d6..f1a6c37 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,38 @@
# GoCloud
+_Containers_
+
+Statuses:
+
+- 0: Неактивен
+- 1: Активен
+- 2: Процесс активации
+- 3: Процесс деактивации
+- 4: Создание...
+- 5: Удаление...
+
+_Tasks_
+
+Statuses:
+
+- 0: new
+- 1: working
+- 2: completed
+
## Develop
### Public to local PyPI server
`python setup.py sdist upload -r local`
+
+## Test
+
+### User API
+
+### Server API
+
+_Get containers status_
+
+`curl -X GET http://127.0.0.1:5000/server_api/containers/status/ -u f411b7d6-bf93-4fcd-91ee-03e5343d0187:b3c9a8b0-95ca-11e5-bec1-28d244e159e9`
+
+`curl -X POST http://127.0.0.1:5000/server_api/containers/status/663b31b4-22b1-4846-bfaf-27d6389beef4 -u f411b7d6-bf93-4fcd-91ee-03e5343d0187:b3c9a8b0-95ca-11e5-bec1-28d244e159e9 -d 'status=0&message="test"'`
\ No newline at end of file
diff --git a/SWSCloudCore/controllers/containers/server.py b/SWSCloudCore/controllers/containers/server.py
index 6ae8a5c..68f810e 100644
--- a/SWSCloudCore/controllers/containers/server.py
+++ b/SWSCloudCore/controllers/containers/server.py
@@ -5,6 +5,9 @@ from SWSCloudCore import models
class ControllerContainersServer:
def status_set(self, container_id, status):
+ return self.set_container_status(container_id, status)
+
+ def set_container_status(self, container_id, status):
ns = models.Containers.update(status=status).where(
models.Containers.id == container_id
)
@@ -12,6 +15,40 @@ class ControllerContainersServer:
return True
def exists(self, container_id):
- if models.Containers.select().where(models.Containers.id == container_id).count() == 0:
+ if models.Containers.select().where(
+ models.Containers.id == container_id
+ ).count() == 0:
return False
return True
+
+ def get_container(self, container_id):
+ x = models.Containers.select().where(
+ models.Containers.id == container_id
+ ).get()
+
+ return {
+ 'id': str(x.id),
+ 'datacenter_id': str(x.datacenter.id),
+ 'server_id': str(x.server.id),
+ 'ipv4': x.ipv4,
+ 'ipv6': x.ipv6,
+ 'status': x.status
+ }
+
+ def get_containers_by_server(self, server_id):
+ x = models.Containers.select().where(
+ models.Containers.server == server_id
+ ).execute()
+ containers = list()
+ for i in x:
+ containers.append({
+ 'id': str(i.id),
+ 'datacenter_id': str(i.datacenter.id),
+ 'server_id': str(i.server.id),
+ 'ipv4': i.ipv4,
+ 'ipv6': i.ipv6,
+ 'status': i.status
+ })
+ return containers
+
+
diff --git a/SWSCloudCore/controllers/servers/server.py b/SWSCloudCore/controllers/servers/server.py
index c707f03..afffebf 100644
--- a/SWSCloudCore/controllers/servers/server.py
+++ b/SWSCloudCore/controllers/servers/server.py
@@ -3,6 +3,20 @@ import datetime
from SWSCloudCore import models
+class ControllerServerServers:
+ def get_secret(self, server_id):
+ return models.Servers.select(models.Servers.secret).where(models.Servers.id == server_id).get().secret
+
+ def exists(self, server_id):
+ try:
+ if models.Servers.select().where(models.Servers.id == server_id).count() == 0:
+ return False
+ except Exception as e:
+ return False
+ else:
+ return True
+
+
class ControllerServerStatistics:
def write(self, container_id, cpu, memory, size, net_tx, net_rx, net_total):
models.ContainersStatistics.create(
diff --git a/SWSCloudCore/controllers/tasks/server.py b/SWSCloudCore/controllers/tasks/server.py
index 519f2b1..1f512f4 100644
--- a/SWSCloudCore/controllers/tasks/server.py
+++ b/SWSCloudCore/controllers/tasks/server.py
@@ -1,31 +1,29 @@
# coding: utf-8
import json
-
from SWSCloudCore import models
from SWSCloudCore.controllers.containers.server import ControllerContainersServer
-# from peewee import fn
-
-
class ControllerTasksServer:
- def __init__(self, server_id, secret):
+ def __init__(self, server_id):
self.server_id = server_id
- self.secret = secret
- def auth(self):
- if models.Servers.select().where(
- models.Servers.id == self.server_id,
- models.Servers.secret == self.secret
- ).count() == 0:
- return False
- return True
+ def queue_item_oldest_get(self, status=0):
+ """
+ Вытащить самую старую задачу из всех активных
+ :param status:
+ :return:
+ """
+ return models.Tasks.select().where(
+ models.Tasks.server == self.server_id,
+ models.Tasks.status == status
+ ).order_by(models.Tasks.created.asc()).get()
- def count(self):
- return models.Tasks.select(
- models.Servers.id == self.server_id,
- models.Servers.secret == self.secret
+ def count(self, status=0):
+ return models.Tasks.select().where(
+ models.Tasks.server == self.server_id,
+ models.Tasks.status == status
).count()
def get(self, status=0):
@@ -106,7 +104,7 @@ class ControllerTasksServer:
return True
def get_item(self, task_id):
- get_task = models.Tasks.select().where(models.Tasks.id == task_id)[0]
+ get_task = models.Tasks.select().where(models.Tasks.id == task_id).get()
return {
'id': get_task.id,
'datacenter': get_task.datacenter.id,
diff --git a/SWSCloudCore/models.py b/SWSCloudCore/models.py
index 73f016e..9732127 100644
--- a/SWSCloudCore/models.py
+++ b/SWSCloudCore/models.py
@@ -171,9 +171,7 @@ class Tasks(PgSQLModel):
user = ForeignKeyField(Users)
created = DateTimeField(default=datetime.datetime.now)
task = CharField(null=False)
- # 0 - new
- # 1 - working
- # 2 - completed
+ # 0 - new, 1 - working, 2 - completed
status = IntegerField(null=False, default=0)
plain = TextField()
diff --git a/SWSCloudCore/templates/administrator/servers/edit.html b/SWSCloudCore/templates/administrator/servers/edit.html
index 52cd039..c1a71af 100644
--- a/SWSCloudCore/templates/administrator/servers/edit.html
+++ b/SWSCloudCore/templates/administrator/servers/edit.html
@@ -26,6 +26,10 @@
Hostname |
|
+
+ Secret |
+ |
+
Status |
@@ -37,5 +41,5 @@
|
- Cancel
+ Cancel
{% endblock %}
\ No newline at end of file
diff --git a/SWSCloudCore/views/account/__init__.py b/SWSCloudCore/views/account/__init__.py
index f941c05..dbca80d 100644
--- a/SWSCloudCore/views/account/__init__.py
+++ b/SWSCloudCore/views/account/__init__.py
@@ -6,7 +6,6 @@ from flask import request, flash
from sshpubkeys import SSHKey
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerMessagesEmail
-from SWSCloudCore.controllers.common import special_match
from SWSCloudCore.controllers.users import ControllerAPI
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
diff --git a/SWSCloudCore/views/administrator/__init__.py b/SWSCloudCore/views/administrator/__init__.py
index 6d222b5..b899224 100644
--- a/SWSCloudCore/views/administrator/__init__.py
+++ b/SWSCloudCore/views/administrator/__init__.py
@@ -371,7 +371,7 @@ def servers_create():
)
-@viewAdministrator.route('/servers/edit/', methods=['GET', 'POST'])
+@viewAdministrator.route('/servers/edit/.html', methods=['GET', 'POST'])
def servers_edit(server_id):
# check session
if not ControllerAdministrators().check_session():
@@ -383,7 +383,7 @@ def servers_edit(server_id):
if models.Servers.select().where(models.Servers.id == server_id).count() == 0:
return redirect(url_for('administrator.servers'))
- server_details = models.Servers.select().where(models.Servers.id == server_id).limit(1)[0]
+ server_details = models.Servers.select().where(models.Servers.id == server_id).get()
return render_template('administrator/servers/edit.html', server=server_details)
diff --git a/SWSCloudCore/views/api/__init__.py b/SWSCloudCore/views/api/__init__.py
index d18cc67..97cc9d3 100644
--- a/SWSCloudCore/views/api/__init__.py
+++ b/SWSCloudCore/views/api/__init__.py
@@ -1,6 +1,5 @@
# coding: utf-8
-
from flask import Blueprint, jsonify, request
from SWSCloudCore.controllers.containers import ControllerContainers
from SWSCloudCore.controllers.datacenters import ControllerDataCenters
@@ -24,7 +23,6 @@ def auth():
"""
email = request.form['email']
secret = request.form['secret']
- # expire = request.form['expire']
if not ControllerAPI().auth(email, secret):
return jsonify(status=1)
@@ -44,14 +42,13 @@ def datacenter_list():
secret = request.form['secret']
#
if not ControllerAPI().auth(email, secret):
- return jsonify(status=1)
+ return jsonify(status=403), 403
#
user_id = ControllerUsers().get_id_by_email(email)
# get containers list
datacenters = ControllerDataCenters().get()
#
return jsonify(
- status=0,
total=datacenters['total'],
items=datacenters['items']
)
diff --git a/SWSCloudCore/views/containers/__init__.py b/SWSCloudCore/views/containers/__init__.py
index dfaeed4..25c3c76 100644
--- a/SWSCloudCore/views/containers/__init__.py
+++ b/SWSCloudCore/views/containers/__init__.py
@@ -2,7 +2,7 @@
import uuid
from flask import Blueprint, g, redirect, render_template, request, session
-from flask import url_for
+from flask import url_for, flash
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerCommon
@@ -15,7 +15,6 @@ from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
-from SWSCloudCore import models
viewContainers = Blueprint('containers', __name__, url_prefix='/containers')
diff --git a/SWSCloudCore/views/server_api/__init__.py b/SWSCloudCore/views/server_api/__init__.py
index 1e16066..7ba9273 100644
--- a/SWSCloudCore/views/server_api/__init__.py
+++ b/SWSCloudCore/views/server_api/__init__.py
@@ -1,28 +1,48 @@
# coding: utf-8
import json
-from flask import Blueprint, jsonify, request
+from flask import Blueprint, jsonify, request, g
+from flask_httpauth import HTTPBasicAuth
from SWSCloudCore.controllers.servers.server import ControllerServerStatistics
+from SWSCloudCore.controllers.servers.server import ControllerServerServers
from SWSCloudCore.controllers.tasks.server import ControllerTasksServer
from SWSCloudCore.controllers.containers.server import ControllerContainersServer
+api_auth = HTTPBasicAuth()
viewServerAPI = Blueprint('server_api', __name__, url_prefix='/server_api')
+@api_auth.get_password
+def get_pw(server_id):
+ if ControllerServerServers().exists(server_id):
+ g.server_id = server_id
+ return ControllerServerServers().get_secret(g.server_id)
+ return None
+
+
+@api_auth.error_handler
+def auth_error():
+ return jsonify(status='error', description='Unauthorized'), 403
+
+
+@viewServerAPI.route('/ping')
+@api_auth.login_required
+def ping():
+ """
+ Тест. Проверка соединения и авторизации
+ """
+ return jsonify(ping='pong', server_id=g.server_id), 200
+
+
+# TASKS
@viewServerAPI.route('/tasks', methods=['GET'])
+@api_auth.login_required
def tasks_list():
- node_id = request.args.get('node_id')
- node_secret = request.args.get('node_secret')
- server_api = ControllerTasksServer(node_id, node_secret)
-
- # auth request
- if not server_api.auth():
- # status: 403 - access denied
- return jsonify({'status': 403})
-
- result = dict()
- result['status'] = 0
- result['results'] = []
+ """
+ Список
+ """
+ server_api = ControllerTasksServer(g.server_id)
+ result = dict(tasks=list())
for task in server_api.get():
result['results'].append({
@@ -38,39 +58,56 @@ def tasks_list():
return jsonify(result)
-@viewServerAPI.route('/task_status_update', methods=['GET'])
-def task_status_update():
- node_id = request.args.get('node_id')
- node_secret = request.args.get('node_secret')
- server_api = ControllerTasksServer(node_id, node_secret)
+@viewServerAPI.route('/task', methods=['GET'])
+@api_auth.login_required
+def task_item():
+ """
+ Самая первая задача в очереди
+ """
+ sapi = ControllerTasksServer(g.server_id)
- # auth request
- if not server_api.auth():
- # status: 403 - access denied
- return jsonify({'status': 403})
+ # Если задач нет, то надо вернуть ответ с кодом 204 (no content)
+ if sapi.count() == 0:
+ return '', 204
- task_id = request.args.get('task_id')
- status = int(request.args.get('status'))
+ task = sapi.queue_item_oldest_get(status=0)
- server_api.update(task_id, status)
+ result = dict(
+ id=task.id,
+ datacenter=task.datacenter.id,
+ server=task.server.id,
+ user=task.user.id,
+ task=task.task,
+ created=task.created,
+ status=task.status,
+ plain=json.loads(task.plain),
+ )
+ return jsonify(
+ task=result,
+ status='success'
+ )
+
+@viewServerAPI.route('/tasks/', methods=['PUT'])
+@api_auth.login_required
+def task_update(task_id):
+ """
+ Обновление статуса задачи
+ """
+ server_api = ControllerTasksServer(g.server_id)
+
+ if 'status' in request.form:
+ status = int(request.form['status'])
+ server_api.update(task_id, status)
return jsonify({'status': 0})
-@viewServerAPI.route('/report/container_status', methods=['POST'])
-def report_container_status():
- node_id = request.form['node_id']
- node_secret = request.form['node_secret']
-
- # print request.form['node_id']
- # auth request
- if not ControllerTasksServer(node_id, node_secret).auth():
- # status: 403 - access denied
- return jsonify({'status': 403})
-
+# CONTAINERS
+@viewServerAPI.route('/containers/stats/', methods=['POST'])
+@api_auth.login_required
+def report_container_status(container_id):
"""
{
- "container_id": "16459f60-a1ee-11e5-9108-28d244e159e9",
"cpu_use": 644394623336,
"memory_use": 614473728,
"link": "vethB2RLMU"
@@ -79,9 +116,8 @@ def report_container_status():
"total_bytes": 1097776429
}
"""
+
statistics = json.loads(request.form['status'])
- # print statistics
- container_id = statistics['container_id']
if 'cpu_use' not in statistics:
return jsonify({})
@@ -110,5 +146,52 @@ def report_container_status():
int(statistics['rx_bytes']),
int(statistics['total_bytes'])
)
+ return jsonify(status='success')
- return jsonify({})
+
+@viewServerAPI.route('/containers/status/', methods=['GET'])
+@api_auth.login_required
+def containers_status():
+ """
+ Состояние всех контейнеров в биллинге, и привести контейнеры к указанному состоянию
+ На случай, когда нода была перезагружена.
+ """
+ # Get container list (with status) located on node
+ return jsonify(
+ status='success',
+ containers=ControllerContainersServer().get_containers_by_server(g.server_id)
+ )
+
+
+@viewServerAPI.route('/containers/status/', methods=['GET', 'POST'])
+@api_auth.login_required
+def container_status_update(container_id):
+ """
+ Если на ноде при работе с контейнером что-то поло не так,
+ то нода отправляет сообщение об ошибке и изменяет статус контейнера.
+ Отправленное сообщение может быть прочитано администратором или владельцем контейнера
+ """
+ # Check exists container
+ if not ControllerContainersServer().exists(container_id):
+ return '', 404
+
+ # Get information about container
+ if request.method == 'GET':
+ return jsonify(
+ status='success',
+ container=ControllerContainersServer().get_container(container_id)
+ )
+
+ # Set container status
+ if 'status' in request.form:
+ ControllerContainersServer().set_container_status(
+ container_id,
+ request.form['status']
+ )
+ # TODO: 0000001
+
+ return jsonify(status='success')
+ return jsonify(
+ status='error',
+ message='must contain parameter: status'
+ )