This commit is contained in:
Vyacheslav Anzhiganov 2016-04-20 03:39:13 +03:00
parent ad1aca5838
commit 4813152679
11 changed files with 232 additions and 72 deletions

View file

@ -1,7 +1,38 @@
# GoCloud # GoCloud
_Containers_
Statuses:
- 0: Неактивен
- 1: Активен
- 2: Процесс активации
- 3: Процесс деактивации
- 4: Создание...
- 5: Удаление...
_Tasks_
Statuses:
- 0: new
- 1: working
- 2: completed
## Develop ## Develop
### Public to local PyPI server ### Public to local PyPI server
`python setup.py sdist upload -r local` `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"'`

View file

@ -5,6 +5,9 @@ from SWSCloudCore import models
class ControllerContainersServer: class ControllerContainersServer:
def status_set(self, container_id, status): 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( ns = models.Containers.update(status=status).where(
models.Containers.id == container_id models.Containers.id == container_id
) )
@ -12,6 +15,40 @@ class ControllerContainersServer:
return True return True
def exists(self, container_id): 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 False
return True 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

View file

@ -3,6 +3,20 @@ import datetime
from SWSCloudCore import models 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: class ControllerServerStatistics:
def write(self, container_id, cpu, memory, size, net_tx, net_rx, net_total): def write(self, container_id, cpu, memory, size, net_tx, net_rx, net_total):
models.ContainersStatistics.create( models.ContainersStatistics.create(

View file

@ -1,31 +1,29 @@
# coding: utf-8 # coding: utf-8
import json import json
from SWSCloudCore import models from SWSCloudCore import models
from SWSCloudCore.controllers.containers.server import ControllerContainersServer from SWSCloudCore.controllers.containers.server import ControllerContainersServer
# from peewee import fn
class ControllerTasksServer: class ControllerTasksServer:
def __init__(self, server_id, secret): def __init__(self, server_id):
self.server_id = server_id self.server_id = server_id
self.secret = secret
def auth(self): def queue_item_oldest_get(self, status=0):
if models.Servers.select().where( """
models.Servers.id == self.server_id, Вытащить самую старую задачу из всех активных
models.Servers.secret == self.secret :param status:
).count() == 0: :return:
return False """
return True 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): def count(self, status=0):
return models.Tasks.select( return models.Tasks.select().where(
models.Servers.id == self.server_id, models.Tasks.server == self.server_id,
models.Servers.secret == self.secret models.Tasks.status == status
).count() ).count()
def get(self, status=0): def get(self, status=0):
@ -106,7 +104,7 @@ class ControllerTasksServer:
return True return True
def get_item(self, task_id): 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 { return {
'id': get_task.id, 'id': get_task.id,
'datacenter': get_task.datacenter.id, 'datacenter': get_task.datacenter.id,

View file

@ -171,9 +171,7 @@ class Tasks(PgSQLModel):
user = ForeignKeyField(Users) user = ForeignKeyField(Users)
created = DateTimeField(default=datetime.datetime.now) created = DateTimeField(default=datetime.datetime.now)
task = CharField(null=False) task = CharField(null=False)
# 0 - new # 0 - new, 1 - working, 2 - completed
# 1 - working
# 2 - completed
status = IntegerField(null=False, default=0) status = IntegerField(null=False, default=0)
plain = TextField() plain = TextField()

View file

@ -26,6 +26,10 @@
<th>Hostname</th> <th>Hostname</th>
<td><input type="text" name="hostname" value="{{ server.hostname }}" class="form-control" /></td> <td><input type="text" name="hostname" value="{{ server.hostname }}" class="form-control" /></td>
</tr> </tr>
<tr>
<th>Secret</th>
<td nowrap><input type="text" name="secret" id="secret" value="{{ server.secret }}" class="form-control" /></td>
</tr>
<tr> <tr>
<th>Status</th> <th>Status</th>
<td> <td>
@ -37,5 +41,5 @@
</tr> </tr>
</table> </table>
<input type="submit" value="Save changes" class="btn btn-success" /> <input type="submit" value="Save changes" class="btn btn-success" />
<a href="{{ url_for('administrator.servers') }}">Cancel</a> <a href="{{ url_for('administrator.servers_index') }}">Cancel</a>
{% endblock %} {% endblock %}

View file

@ -6,7 +6,6 @@ from flask import request, flash
from sshpubkeys import SSHKey from sshpubkeys import SSHKey
from SWSCloudCore.controllers.billing import ControllerBilling from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerMessagesEmail from SWSCloudCore.controllers.common import ControllerMessagesEmail
from SWSCloudCore.controllers.common import special_match
from SWSCloudCore.controllers.users import ControllerAPI from SWSCloudCore.controllers.users import ControllerAPI
from SWSCloudCore.controllers.users import ControllerSSHKey from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers from SWSCloudCore.controllers.users import ControllerUsers

View file

@ -371,7 +371,7 @@ def servers_create():
) )
@viewAdministrator.route('/servers/edit/<uuid:server_id>', methods=['GET', 'POST']) @viewAdministrator.route('/servers/edit/<uuid:server_id>.html', methods=['GET', 'POST'])
def servers_edit(server_id): def servers_edit(server_id):
# check session # check session
if not ControllerAdministrators().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: if models.Servers.select().where(models.Servers.id == server_id).count() == 0:
return redirect(url_for('administrator.servers')) 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) return render_template('administrator/servers/edit.html', server=server_details)

View file

@ -1,6 +1,5 @@
# coding: utf-8 # coding: utf-8
from flask import Blueprint, jsonify, request from flask import Blueprint, jsonify, request
from SWSCloudCore.controllers.containers import ControllerContainers from SWSCloudCore.controllers.containers import ControllerContainers
from SWSCloudCore.controllers.datacenters import ControllerDataCenters from SWSCloudCore.controllers.datacenters import ControllerDataCenters
@ -24,7 +23,6 @@ def auth():
""" """
email = request.form['email'] email = request.form['email']
secret = request.form['secret'] secret = request.form['secret']
# expire = request.form['expire']
if not ControllerAPI().auth(email, secret): if not ControllerAPI().auth(email, secret):
return jsonify(status=1) return jsonify(status=1)
@ -44,14 +42,13 @@ def datacenter_list():
secret = request.form['secret'] secret = request.form['secret']
# #
if not ControllerAPI().auth(email, secret): if not ControllerAPI().auth(email, secret):
return jsonify(status=1) return jsonify(status=403), 403
# #
user_id = ControllerUsers().get_id_by_email(email) user_id = ControllerUsers().get_id_by_email(email)
# get containers list # get containers list
datacenters = ControllerDataCenters().get() datacenters = ControllerDataCenters().get()
# #
return jsonify( return jsonify(
status=0,
total=datacenters['total'], total=datacenters['total'],
items=datacenters['items'] items=datacenters['items']
) )

View file

@ -2,7 +2,7 @@
import uuid import uuid
from flask import Blueprint, g, redirect, render_template, request, session 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.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerCommon 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.tasks import ControllerTasks
from SWSCloudCore.controllers.users import ControllerSSHKey from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers from SWSCloudCore.controllers.users import ControllerUsers
from SWSCloudCore import models
viewContainers = Blueprint('containers', __name__, url_prefix='/containers') viewContainers = Blueprint('containers', __name__, url_prefix='/containers')

View file

@ -1,28 +1,48 @@
# coding: utf-8 # coding: utf-8
import json 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 ControllerServerStatistics
from SWSCloudCore.controllers.servers.server import ControllerServerServers
from SWSCloudCore.controllers.tasks.server import ControllerTasksServer from SWSCloudCore.controllers.tasks.server import ControllerTasksServer
from SWSCloudCore.controllers.containers.server import ControllerContainersServer from SWSCloudCore.controllers.containers.server import ControllerContainersServer
api_auth = HTTPBasicAuth()
viewServerAPI = Blueprint('server_api', __name__, url_prefix='/server_api') 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']) @viewServerAPI.route('/tasks', methods=['GET'])
@api_auth.login_required
def tasks_list(): def tasks_list():
node_id = request.args.get('node_id') """
node_secret = request.args.get('node_secret') Список
server_api = ControllerTasksServer(node_id, node_secret) """
server_api = ControllerTasksServer(g.server_id)
# auth request result = dict(tasks=list())
if not server_api.auth():
# status: 403 - access denied
return jsonify({'status': 403})
result = dict()
result['status'] = 0
result['results'] = []
for task in server_api.get(): for task in server_api.get():
result['results'].append({ result['results'].append({
@ -38,39 +58,56 @@ def tasks_list():
return jsonify(result) return jsonify(result)
@viewServerAPI.route('/task_status_update', methods=['GET']) @viewServerAPI.route('/task', methods=['GET'])
def task_status_update(): @api_auth.login_required
node_id = request.args.get('node_id') def task_item():
node_secret = request.args.get('node_secret') """
server_api = ControllerTasksServer(node_id, node_secret) Самая первая задача в очереди
"""
sapi = ControllerTasksServer(g.server_id)
# auth request # Если задач нет, то надо вернуть ответ с кодом 204 (no content)
if not server_api.auth(): if sapi.count() == 0:
# status: 403 - access denied return '', 204
return jsonify({'status': 403})
task_id = request.args.get('task_id') task = sapi.queue_item_oldest_get(status=0)
status = int(request.args.get('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/<task_id>', 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) server_api.update(task_id, status)
return jsonify({'status': 0}) return jsonify({'status': 0})
@viewServerAPI.route('/report/container_status', methods=['POST']) # CONTAINERS
def report_container_status(): @viewServerAPI.route('/containers/stats/<uuid:container_id>', methods=['POST'])
node_id = request.form['node_id'] @api_auth.login_required
node_secret = request.form['node_secret'] def report_container_status(container_id):
# print request.form['node_id']
# auth request
if not ControllerTasksServer(node_id, node_secret).auth():
# status: 403 - access denied
return jsonify({'status': 403})
""" """
{ {
"container_id": "16459f60-a1ee-11e5-9108-28d244e159e9",
"cpu_use": 644394623336, "cpu_use": 644394623336,
"memory_use": 614473728, "memory_use": 614473728,
"link": "vethB2RLMU" "link": "vethB2RLMU"
@ -79,9 +116,8 @@ def report_container_status():
"total_bytes": 1097776429 "total_bytes": 1097776429
} }
""" """
statistics = json.loads(request.form['status']) statistics = json.loads(request.form['status'])
# print statistics
container_id = statistics['container_id']
if 'cpu_use' not in statistics: if 'cpu_use' not in statistics:
return jsonify({}) return jsonify({})
@ -110,5 +146,52 @@ def report_container_status():
int(statistics['rx_bytes']), int(statistics['rx_bytes']),
int(statistics['total_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/<uuid:container_id>', 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'
)