Compare commits

..

14 commits

Author SHA1 Message Date
vanzhiganov
1e35e778f0 #2 добавил страницу иниализации установки 2025-02-09 02:36:55 +03:00
974e35cfc3 init new version 3.0 2025-01-28 23:38:11 +03:00
viacheslav anzhiganov
7655b8b97a validations implemeented 2025-01-05 08:07:49 +03:00
viacheslav anzhiganov
6a11181075 update 2025-01-05 07:55:28 +03:00
viacheslav anzhiganov
bfe906a1cf fix broken import 2024-12-11 22:16:38 +03:00
viacheslav anzhiganov
25444811aa #1 fix 2024-12-11 21:53:54 +03:00
viacheslav anzhiganov
c7286dc164 #1 fix 2024-12-11 20:42:33 +03:00
viacheslav anzhiganov
fceb922d94 update dependencies and porting for python3 2024-12-10 21:05:37 +03:00
4c4202b346 refactoting and new apiv2 2017-01-26 01:53:51 +03:00
999452a488 refactoting and new apiv2 2017-01-23 04:08:13 +03:00
9261b24730 refactoting and new apiv2 2017-01-18 11:07:29 +03:00
ef3933802e up 2016-12-29 10:44:27 +03:00
60241f9ea8 up 2016-12-29 10:44:10 +03:00
15c1a81831 fix missing style and support page 2016-12-07 02:20:26 +03:00
94 changed files with 1431 additions and 429 deletions

2
.gitignore vendored
View file

@ -1,6 +1,6 @@
settings.ini
.idea/
.venv/
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files

5
.rsyncignore Normal file
View file

@ -0,0 +1,5 @@
.venv
.git
__pycache__/
*.egg-info/
venv

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

4
Makefile Normal file
View file

@ -0,0 +1,4 @@
DEST:=/opt/nativecloud
sync:
rsync -rvz --exclude-from .rsyncignore --delete ./ root@192.168.11.11:/opt/nativecloud/

View file

@ -1,4 +1,17 @@
# GoCloud
# nativecloud
## install
```shell
git clone https://git.org.ru/vmbuilder/console.git /opt/nativecloud
python -m venv /opt/nativecloud/.venv
. /opt/nativecloud/.venv/bin/activate
pip install -r /opt/nativecloud/requrements.txt
```
##
_Containers_
@ -10,6 +23,7 @@ Statuses:
- 3: Процесс деактивации
- 4: Создание...
- 5: Удаление...
- 6: Перезапуск
_Tasks_
@ -33,6 +47,12 @@ Statuses:
_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`
```shell
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"'`
```shell
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

@ -1,35 +0,0 @@
# coding: utf-8
from flask import Blueprint, jsonify, g
from flask_httpauth import HTTPBasicAuth
from SWSCloudCore.controllers.users import ControllerAPI
from SWSCloudCore.controllers.users import ControllerUsers
api = Blueprint('api', __name__, url_prefix='/api/v1')
auth = HTTPBasicAuth()
"""
TODO: Реализовать Процесс авторизации в версии API 2.0
- получаем емейл и секретный ключ
- создаём временный токен
- выдаём токен
"""
@auth.verify_password
def verify_password(username, password):
if not ControllerAPI().auth(username, password):
return False
g.user_id = ControllerUsers().get_id_by_email(username)
return True
@api.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)

View file

View file

@ -0,0 +1,2 @@
from .token import api_v2_token

View file

@ -0,0 +1,59 @@
# coding: utf-8
from flask import Blueprint, jsonify, request, g
from SWSCloudCore.models import Users
from SWSCloudAPI.API.compute.v2.common import *
from SWSCloudAPI.Utils import decorators, Tokens
api_v2_token = Blueprint('v2token', __name__, url_prefix='/api/auth/v2')
@api_v2_token.route('/token', methods=['POST'])
@decorators.content_type
@decorators.login_required
def token_post():
"""Get token
_Example_
curl -X POST http://localhost:5001/api/auth/v2/token -d '{"email":"vanzhiganov@ya.ru","password":"qwepoi123"}' -H "Content-Type: application/json"
{
"status": "ok",
"payload": {
"token": "422f45a4-eab9-4a79-9954-61c568bae0eb",
"email": "email@my.com"
}
}
:return:
"""
# get user data
user = Users.get_by_email(request.json.get('email'))
#
new_token = Tokens().set(dict(user_id=str(user.id), email=user.email), TOKEN_TTL)
#
return jsonify(status='ok', payload={'token': new_token})
@api_v2_token.route('/token', methods=['GET'])
@decorators.content_type
@decorators.auth_token
def token_get():
"""Get token data
curl -X GET http://localhost:5001/api/auth/v2/token -H "X-Auth-Token: 422f45a4-eab9-4a79-9954-61c568bae0eb" -H "Content-Type: application/json"
:return:
"""
return jsonify(status='ok', payload=g.tokens.get(g.auth_token))
@api_v2_token.route('/token', methods=['DELETE'])
@decorators.content_type
@decorators.auth_token
def token_delete():
"""
curl -X DELETE http://localhost:5001/api/auth/v2/token -H "X-Auth-Token: 422f45a4-eab9-4a79-9954-61c568bae0eb" -H "Content-Type: application/json"
:return:
"""
g.tokens.delete(g.auth_token)
return jsonify(status='ok')

View file

View file

@ -0,0 +1 @@
# coding: utf-8

View file

@ -0,0 +1,16 @@
from SWSCloudCore.controllers.users import ControllerAPI
from SWSCloudCore.controllers.users import ControllerUsers
from flask import g
from flask_httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()
@auth.verify_password
def verify_password(username, password):
if not ControllerAPI().auth(username, password):
return False
g.user_id = ControllerUsers().get_id_by_email(username)
return True

View 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

View file

@ -2,7 +2,7 @@
from uuid import uuid4
from flask import Blueprint, jsonify, request, g
from SWSCloudAPI.API import auth
from SWSCloudAPI.API.compute.v1.common import auth
from SWSCloudCore.controllers.datacenters import ControllerDataCenters
from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.users import ControllerUsers
@ -13,7 +13,7 @@ from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.containers import (
ControllerContainers, ControllerContainersStatistics, ControllerContainersStatisticsState)
api_v1_containers = Blueprint('containers', __name__, url_prefix='/api/v1/containers')
api_v1_containers = Blueprint('containers', __name__, url_prefix='/api/compute/v1/containers')
@api_v1_containers.route('/', methods=['GET'])

View file

@ -0,0 +1,24 @@
# coding: utf-8
from flask import Blueprint, jsonify
from SWSCloudAPI.API.compute.v1.common import auth
from SWSCloudCore.models import DataCenters
api_v1_datacenters = Blueprint('datacenters', __name__, url_prefix='/api/compute/v1/datacenters')
@api_v1_datacenters.route('/', methods=['GET'])
@auth.login_required
def index():
"""
get containers list
curl -X http://localhost:5000/api/compute/v1/datacenters/ -u <email>:<secret>
:return:
"""
# dc_list = ControllerDataCenters().get()
dc_list = DataCenters.get_available()
items = list()
for x in dc_list:
items.append(x)
return jsonify(total=len(dc_list), items=items)

View file

@ -1,13 +1,13 @@
# coding: utf-8
from flask import Blueprint, jsonify
from SWSCloudAPI.API import auth
from SWSCloudAPI.API.compute.v1.common import auth
from SWSCloudCore.controllers.plans import ControllerPlans
api_v1_pricing = Blueprint('pricing', __name__, url_prefix='/api/v1/pricing')
api_v1_pricing = Blueprint('pricing', __name__, url_prefix='/api/compute/v1/pricing')
@api_v1_pricing.route('/pricing/vms/')
@api_v1_pricing.route('/vms')
@auth.login_required
def pricing_vms():
"""
@ -18,7 +18,7 @@ def pricing_vms():
return jsonify(pricing=ControllerPlans().get_plans(status='active'))
@api_v1_pricing.route('/pricing/containers/')
@api_v1_pricing.route('/containers')
@auth.login_required
def pricing_containers():
"""

View file

@ -2,7 +2,7 @@
from uuid import uuid4
from flask import Blueprint, jsonify, request, g
from SWSCloudAPI.API import auth
from SWSCloudAPI.API.compute.v1.common import auth
from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.plans import ControllerPlans
from SWSCloudCore.controllers.users import ControllerUsers
@ -12,7 +12,7 @@ from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessages
from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.vms import ControllerVMS
api_v1_vms = Blueprint('vms', __name__, url_prefix='/api/v1/vms')
api_v1_vms = Blueprint('vms', __name__, url_prefix='/api/compute/v1/vms')
@api_v1_vms.route('/', methods=['GET'])

View file

@ -0,0 +1,3 @@
from .views.datacenters import api_v2_datacenters
from .views.pricing import api_v2_pricing
from .views.vms import api_v2_vms

View file

@ -0,0 +1,4 @@
TOKEN_TTL = 1800
TOKEN_PREFIX = 'token_'

View file

@ -0,0 +1,254 @@
# coding: utf-8
from uuid import uuid4
from flask import Blueprint, jsonify, request, g
from SWSCloudAPI.Utils import Tokens
from SWSCloudAPI.Utils import decorators
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessagesEmail
from SWSCloudCore.controllers.containers import (
ControllerContainers, ControllerContainersStatistics, ControllerContainersStatisticsState)
from SWSCloudCore.controllers.datacenters import ControllerDataCenters
from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
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(status='error', 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')

View file

@ -0,0 +1,25 @@
# coding: utf-8
from flask import Blueprint, jsonify, g
from SWSCloudAPI.Utils import decorators
from SWSCloudCore.models import DataCenters
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/v2/datacenters/ -H "X-Auth-Token: a90bb6cd-681f-4f87-b1ca-ea30921e3440" -H "Content-Type: application/json"
:return:
"""
#
dc_list = DataCenters.get_available()
items = list()
for x in dc_list:
items.append(dict(id=str(x.id), name=x.name, country=x.country, city=x.city))
return jsonify(status='ok', payload=items, total=len(dc_list))

View file

@ -0,0 +1,22 @@
# coding: utf-8
from flask import Blueprint, jsonify, g
from SWSCloudAPI.Utils import decorators
from SWSCloudCore.controllers.plans import ControllerPlans
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:
"""
#
payload = ControllerPlans().get_plans(status='active')
return jsonify(status='ok', payload=payload)

View file

@ -0,0 +1,245 @@
# coding: utf-8
from uuid import uuid4
from flask import Blueprint, jsonify, request, g
from SWSCloudCore import models
from SWSCloudAPI.Utils import decorators
from SWSCloudCore.controllers.billing import ControllerBilling
from SWSCloudCore.controllers.common import ControllerCommon, ControllerMessagesEmail
from SWSCloudCore.controllers.ips import ControllerIps
from SWSCloudCore.controllers.plans import ControllerPlans
from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore.controllers.users import ControllerSSHKey
from SWSCloudCore.controllers.users import ControllerUsers
from SWSCloudCore.controllers.vms import ControllerVMS
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"""
return jsonify(status='ok', payload=models.Vms.get_user_items(g.user.get('user_id')))
@api_v2_vms.route('/', methods=['POST'])
@decorators.content_type
@decorators.auth_token
def vms_create():
"""Create virtual server"""
user_balance = ControllerBilling().get(g.user.get('user_id'))
user_ssh = ControllerSSHKey(g.user.get('user_id'))
controller_plans = ControllerPlans()
# check user money
if user_balance <= 0:
return jsonify(status='error', message='no money')
new_vm = dict()
new_vm['vm_id'] = str(uuid4())
# check exists plan
if not controller_plans.exists(request.json.get('plan')):
return jsonify(status='error', message='plan not exists')
# load plan details
plan_details = controller_plans.plan_get(request.json.get('plan'))
new_vm['plan'] = request.json.get('plan')
# select server from selected region with available ip-addresses
# select IP
select_ip = ControllerIps().getfree(request.json.get('datacenter'))
# mark ip as busy (taken)
ControllerIps().setbusy(select_ip.id)
# generate password for container user
new_vm['password'] = ControllerCommon().generate_password(size=14)
new_vm['hostname'] = ControllerCommon().generate_password(size=7)
new_vm['datacenter_id'] = str(select_ip.datacenter.id)
new_vm['server_id'] = str(select_ip.server.id)
new_vm['platform'] = 'x86_64'
new_vm['ipv4'] = select_ip.ipv4
new_vm['ipv6'] = select_ip.ipv6
new_vm['ipv4_gateway'] = select_ip.ipv4_gateway
new_vm['ipv6_gateway'] = select_ip.ipv6_gateway
# TODO: remove hardcore
new_vm['dns1'] = '8.8.8.8'
new_vm['dns2'] = '8.8.4.4'
new_vm['cores'] = plan_details.cores
new_vm['storage'] = plan_details.storage
new_vm['swap'] = plan_details.swap
new_vm['memory'] = plan_details.memory
new_vm['os_name'] = 'ubuntu'
new_vm['os_suite'] = 'trusty'
# sshkey
new_vm['ssh_key'] = None
if user_ssh.check():
new_vm['ssh_key'] = user_ssh.get()
# create container record in database
# status 4: creation
status = 4
container_create = ControllerVMS(g.user.get('user_id')).create(
vm_id=new_vm['vm_id'],
datacenter_id=new_vm['datacenter_id'],
server_id=new_vm['server_id'],
hostname=new_vm['hostname'],
ipv4=new_vm['ipv4'],
ipv6=new_vm['ipv6'],
plan=new_vm['plan'],
platform=new_vm['platform'],
os_name=new_vm['os_name'],
os_suite=new_vm['os_suite'],
status=status
)
# create default state data
# ControllerContainersStatisticsState().set(new_container['container_id'], dict())
if not container_create:
# mark ip as free
ControllerIps().setfree(select_ip.id)
return jsonify(status='error', message='fail')
# create task for create new container
ControllerTasks(g.user.get('user_id')).create(
new_vm['datacenter_id'],
new_vm['server_id'],
'vm_create',
0,
vm_id=new_vm['vm_id'],
ipv4=new_vm['ipv4'],
ipv4_gateway=new_vm['ipv4_gateway'],
ipv6=new_vm['ipv6'],
ipv6_gateway=new_vm['ipv6_gateway'],
password=new_vm['password'],
hostname=new_vm['hostname'],
platform=new_vm['platform'],
# TODO: remove hardcore
dns1=new_vm['dns1'],
dns2=new_vm['dns2'],
cores=new_vm['cores'],
storage=new_vm['storage'],
swap=new_vm['swap'],
memory=new_vm['memory'],
os_name=new_vm['os_name'],
os_suite=new_vm['os_suite'],
ssh_key=new_vm['ssh_key'],
)
# send mail message with recovery code
message_parts = []
if new_vm['ipv4']:
message_parts.append(u"IPv4: %s" % new_vm['ipv4'])
if new_vm['ipv6']:
message_parts.append(u"IPv6: %s" % new_vm['ipv6'])
message_parts.append(u"Пользователь: %s" % 'administrator')
# message_parts.append(u"Пользователь: %s" % new_vm['username'])
message_parts.append(u"Пароль: %s" % new_vm['password'])
if new_vm['ssh_key']:
message_parts.append(u"SSH ключ: добавлен")
message = '<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.get('user_id')).get()
email = ControllerMessagesEmail()
email.send(title=subject, to=user_data.email, lead=lead, message=message, callout=callout)
return jsonify(
status='ok', payload=dict(
user='root', password=new_vm['password'], ipv4=new_vm['ipv4'],
public_ssh_key='added' if new_vm['ssh_key'] else 'empty'))
@api_v2_vms.route('/<uuid:vm_id>/status', methods=['POST'])
@decorators.content_type
@decorators.auth_token
def vm_actions(vm_id):
"""
"""
# init ...
vm = ControllerVMS(g.user.get('user_id'))
# get container details
vm_details = vm.get(vm_id=vm_id)
if request.json.get('action') == "start":
if ControllerBilling().get(g.user.get('user_id')) <= 0:
return jsonify(message='no money')
vm.set_status(vm_id, 2)
# Создание задания
ControllerTasks(g.user.get('user_id')).create(
vm_details.datacenter.id, vm_details.server.id, 'vm_start', 0, vm_id=vm_details.id)
if request.json.get('action') == "restart":
#
vm.status_set(vm_id, 6)
# Создание задания
ControllerTasks(g.user.get('user_id')).create(
vm_details.datacenter.id, vm_details.server.id, 'vm_restart', 0, vm_id=vm_id)
if request.json.get('action') == "stop":
#
vm.status_set(vm_id, 3)
# Создание задания
ControllerTasks(g.user.get('user_id')).create(
vm_details.datacenter.id, vm_details.server.id, 'vm_stop', 0, vm_id=vm_id)
if request.json.get('action') == "delete":
# Обновляем статус "5" для правила
vm.set_status(vm_id, 5)
# Создание задания
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='ok')
@api_v2_vms.route('/<uuid:vm_id>', methods=['DELETE'])
@decorators.content_type
@decorators.auth_token
def vm_delete(vm_id):
"""Delete virtual machine
:param vm_id:
:return:
"""
vms = ControllerVMS(g.user.get('user_id'))
tasks = ControllerTasks(g.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(status='error', message='not exists')
# get container details
vm_details = models.Vms.get_item(vm_id)
# Обновляем статус "5" для правила
vms.set_status(vm_id, 5)
# Создание задания
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')

View file

@ -1,20 +0,0 @@
# coding: utf-8
from flask import Blueprint, jsonify
from SWSCloudAPI.API import auth
from SWSCloudCore.controllers.datacenters import ControllerDataCenters
api_v1_datacenters = Blueprint('datacenters', __name__, url_prefix='/api/v1/datacenters')
@api_v1_datacenters.route('/', methods=['GET'])
@auth.login_required
def index():
"""
get containers list
curl -X http://localhost:5000/api/v1/datacenters/ -u <email>:<secret>
:return:
"""
dc_list = ControllerDataCenters().get()
return jsonify(total=dc_list.get('total'), items=dc_list.get('items'))

102
SWSCloudAPI/README.md Normal file
View file

@ -0,0 +1,102 @@
# Compute API v1
...
# Compute API v2
## Auth
Create new Token
$ curl -X POST http://localhost:5001/api/auth/v2/token \
-d '{"email":"vanzhiganov@ya.ru","password":"qwepoi123"}' \
-H "Content-Type: application/json"
{
"payload": {
"token": true
},
"status": "ok"
}
Get token data
curl -X GET http://localhost:5001/api/auth/v2/token \
-H 'X-Auth-Token: e7a49627-1199-4c3a-a7d3-b482c00fa503' \
-H "Content-Type: application/json"
{
"payload": {
"email": "vanzhiganov@ya.ru",
"user_id": "1f3936af-be4c-43d5-b352-2f9c88c56857"
},
"status": "ok"
}
Delete token
curl -X DELETE http://localhost:5001/api/auth/v2/token \
-H 'X-Auth-Token: e7a49627-1199-4c3a-a7d3-b482c00fa503' \
-H "Content-Type: application/json"
{
"status": "ok"
}
## Data Centers
Get list data centers
curl -X GET http://localhost:5001/api/compute/v2/datacenters/ \
-H "X-Auth-Token: ef381b13-425d-4635-9d8a-bba91910dd26" \
-H "Content-Type: application/json"
{
"payload": [
{
"city": "moscow",
"country": "russia",
"id": "531511b2-dcf5-11e6-9175-a315ee8fdabf",
"name": "moscow 1"
}
],
"status": "ok",
"total": 1
}
## Pricing
curl -X GET http://localhost:5001/api/compute/v2/pricing/ \
-H "X-Auth-Token: ef381b13-425d-4635-9d8a-bba91910dd26" \
-H "Content-Type: application/json"
{
"payload": [],
"status": "ok"
}
## Virtual machines
Create new virtual achine
curl -X POST http://localhost:5001/api/compute/v2/vms/ \
-H "X-Auth-Token: ef381b13-425d-4635-9d8a-bba91910dd26" \
-H "Content-Type: application/json" '
-d '{"plan": "", "datacenter": "", }'
Errors
{
"message": "no money",
"status": "error"
}
Get list virtual achines
curl -X GET http://localhost:5001/api/compute/v2/vms/ \
-H "X-Auth-Token: ef381b13-425d-4635-9d8a-bba91910dd26" \
-H "Content-Type: application/json"
{
"payload": [],
"status": "ok"
}

View file

@ -0,0 +1 @@
from .tokens import Tokens

View file

@ -0,0 +1,48 @@
from functools import wraps
import validators
from flask import g, request, jsonify
from SWSCloudAPI.Utils import Tokens
from SWSCloudCore.models import Users
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
# validate email
if not validators.email(request.json.get('email')):
return jsonify(status='error', message='invalid email format')
# verify email/password
if not Users.auth(request.json.get('email'), request.json.get('password').encode()):
return jsonify(status='error', message='invalid auth')
#
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 Tokens.exists(g.auth_token):
return jsonify(status='error', message='token not exists')
#
g.tokens = Tokens()
g.user = g.tokens.get(g.auth_token)
return f(*args, **kwargs)
return decorated_function

View file

@ -0,0 +1,5 @@
from SWSCloudCore.config import config
from redis import StrictRedis
rediskc = StrictRedis(config.get('Redis', 'host'), config.get('Redis', 'port'), config.get('Redis', 'db'))

View file

@ -0,0 +1,74 @@
import json
import uuid
from flask import g
from SWSCloudAPI.API.compute.v2.common import TOKEN_PREFIX, TOKEN_TTL
class Tokens(object):
def set(self, payload, ttl=1800):
"""Create new token
Example
>>> Tokens().set({'user_id': 1, 'email': 'user@email.com'}, 1800)
:param payload: dict
:param ttl: int
:return: boolean
"""
token = self.generate_id()
g.redis_connect.set(TOKEN_PREFIX + token, json.dumps(payload), ttl)
return token
@staticmethod
def get(token, ttl=None):
"""Get token data
>>> Tokens.get('d0dd3bfa-e0f2-11e6-a2ce-17cec9ffa761')
>>> Tokens.get('d0dd3bfa-e0f2-11e6-a2ce-17cec9ffa761', 1800)
"""
if ttl and type(ttl) == int:
g.redis_connect.expire(TOKEN_PREFIX + token, ttl)
return json.loads(g.redis_connect.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.redis_connect.expire(TOKEN_PREFIX + token, ttl)
return True
@staticmethod
def exists(token):
"""Check exists token in redis
:param token: uuid
:return: boolean
"""
if g.redis_connect.exists(TOKEN_PREFIX + token):
return True
return False
@staticmethod
def delete(token):
try:
g.redis_connect.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())

View file

@ -1,55 +1,61 @@
# coding: utf-8
from flask import Flask, g, jsonify
from SWSCloudAPI.API import api
from SWSCloudAPI.API.vms import api_v1_vms
from SWSCloudAPI.API.containers import api_v1_containers
from SWSCloudAPI.API.datacenters import api_v1_datacenters
from SWSCloudAPI.API.pricing import api_v1_pricing
from SWSCloudCore import models
from SWSCloudCore.models import database
from SWSCloudCore.config import config
from SWSCloudCore.models import database
# v1
from SWSCloudAPI.API.compute.v1.views import *
# v2
from SWSCloudAPI.API.auth.v2 import *
from SWSCloudAPI.API.compute.v2 import *
#
from SWSCloudAPI.Utils.redisc import rediskc
app = Flask(__name__)
# Думал, что получится сделать автопрефик для всего приложения, но это не сработало
# app.config["APPLICATION_ROOT"] = "/api/v1"
# app.config['SERVER_NAME'] = settings.get('Application', 'SERVER_NAME')
app.config['DEBUG'] = config.getboolean('Application', 'DEBUG')
app.config['SECRET_KEY'] = config.get("Application", "SECRET_KEY")
app.register_blueprint(api)
# 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)
def page_not_found(e):
app.logger.error(e)
return jsonify(dict(message='resource not found')), 404
return jsonify(status='error', message='resource not found')
@app.errorhandler(403)
def access_deny(e):
app.logger.error(e)
return jsonify(dict(message='access deny')), 403
return jsonify(status='error', message='access deny'), 403
@app.errorhandler(410)
def page_not_found(e):
app.logger.error(e)
return jsonify(dict()), 410
return jsonify({})
@app.errorhandler(500)
def page_not_found(e):
app.logger.error(e)
return jsonify(dict(message='maintenance')), 500
return jsonify(status='maintenance')
@app.before_request
def before_request():
g.redis_connect = rediskc
g.settings = dict()
# извлекаем настройки и определяем их в глобальную переменную
for setting in models.Settings.select(models.Settings.key, models.Settings.val).execute():

View file

@ -1,8 +1,9 @@
# coding: utf-8
from uuid import uuid4
from hashlib import md5
import validators
from datetime import datetime
from flask import Blueprint, flash, g, jsonify, redirect, render_template, request, session, url_for
from SWSCloudAdministrator.Administrator.common import requires_login
@ -12,44 +13,49 @@ from SWSCloudCore.controllers.common import ControllerMessagesEmail
from SWSCloudCore.controllers.datacenters.manage import ControllerManageDatacenters
from SWSCloudCore.controllers.ips.manage import ControllerManageIPs
from SWSCloudCore.controllers.servers.manage import ControllerManageServer
from SWSCloudCore.controllers.settings import ControllerSettings
# from SWSCloudCore.controllers.users.manage import ControllerManageUsers
# from SWSCloudCore.controllers.users.manage import ControllerManageUsersBalance
# from SWSCloudCore.controllers.users.manage import ControllerManageUsersDetails
from SWSCloudCore.controllers.plans import ControllerPlans
from SWSCloudCore import models
viewAdministrator = Blueprint('administrator', __name__, url_prefix='/administrator')
@viewAdministrator.route('/login.html', methods=['GET', 'POST'])
@viewAdministrator.route('/login.html', methods=['GET'])
def login():
if request.method == 'POST':
admin_email = request.form.get('email').encode('utf-8')
admin_password = request.form.get('password').encode('utf-8')
# validation entered data
if not validators.email(admin_email):
flash('Invalid registration data')
return redirect(url_for('administrator.login'))
# try auth only active users (with status code 1)
if models.Admins.auth(admin_email, admin_password, 1):
# get user_id
user_id = ControllerAdministrators().get_id_by_email(admin_email)
# save user data to session
session['admin_id'] = str(user_id)
session['admin_email'] = admin_email
session['admin_password'] = admin_password
# redirect to rules list
return redirect(url_for('administrator.dashboard'))
else:
flash('Invalid login. Please try again.')
return redirect(url_for('administrator.login'))
return render_template('administrator/login.html')
@viewAdministrator.route('/login.html', methods=['POST'])
def login_post():
admin_email = request.form.get('email')
admin_password = request.form.get('password').encode('utf-8')
# validation entered data
if not validators.email(admin_email):
flash('Invalid registration data')
return redirect(url_for('administrator.login'))
# try auth only active users (with status code 1)
if not models.Admins.auth(admin_email, admin_password, 1):
flash('Invalid login. Please try again.')
return redirect(url_for('administrator.login'))
# get user_id
user_id = ControllerAdministrators().get_id_by_email(admin_email)
# save user data to session
session['admin_id'] = str(user_id)
session['admin_email'] = admin_email
session['admin_password'] = admin_password
# redirect to rules list
return redirect(url_for('administrator.dashboard'))
# return ""
@viewAdministrator.route('/logout.html')
def logout():
session.pop('admin_id', None)
@ -164,7 +170,7 @@ def ips_index():
def ips_create():
#
if request.method == "POST":
print request.form
print(request.form)
if ControllerManageIPs().is_valid_ipv4_address(request.form['ipv4'])\
and ControllerManageIPs().is_valid_ipv4_address(request.form['ipv4_gateway']):
ControllerManageIPs().item_create(
@ -200,7 +206,7 @@ def ips_create():
def ips_edit(ip_id):
#
if request.method == 'POST':
print request.form
print(request.form)
# if ControllerManageIPs().is_valid_ipv4_address(request.form['ipv4'])\
# and ControllerManageIPs().is_valid_ipv4_address(request.form['ipv4_gateway']):
ControllerManageIPs().item_update(
@ -232,7 +238,7 @@ def ips_delete():
@requires_login
def servers_create():
if request.method == "POST":
print request.form
print(request.form)
params = {
'datacenter_id': request.form['datacenter_id'],
'server_id': uuid4(),
@ -405,3 +411,40 @@ def plan_edit(plan_id):
return render_template(
'administrator/plans/edit.html',
plan_details=models.PlansVMs.select().where(models.PlansVMs.id == plan_id).get())
@viewAdministrator.route('/setup', methods=['GET', 'POST'])
# @requires_login
def setup():
# # check exists plan
# if models.PlansVMs.select().where(models.PlansVMs.id == plan_id).count() == 0:
# return redirect(url_for('administrator.plans_index'))
if request.method == 'POST':
admin_id = uuid4()
admin_email = request.form.get('email')
admin_password = md5(request.form.get('password').encode()).hexdigest()
# models.database.connect()
if models.Admins.select().where(models.Admins.email == admin_email).count() == 0:
models.Admins.create(id=admin_id, email=admin_email, password=admin_password, status=1)
cs = ControllerSettings()
cs.create('_setup_finish', str(datetime.now()))
return redirect(url_for('administrator.login'))
_setup_finish = models.Settings.select().where(
models.Settings.key == "_setup_finish"
).count()
if _setup_finish != 0:
return redirect(url_for('login'))
return render_template(
'administrator/setup/index.html'
)

View file

@ -7,15 +7,19 @@ from SWSCloudCore.controllers.tasks import ControllerTasks
from SWSCloudCore import models
from SWSCloudAdministrator.Administrator.common import requires_login
view_administrator_compute_vms = Blueprint('administrator_compute_vms', __name__, url_prefix='/administrator/compute/vms')
view_administrator_compute_vms = Blueprint(
'administrator_compute_vms',
__name__,
url_prefix='/administrator/compute/vms')
@view_administrator_compute_vms.route('/', methods=['GET'])
@requires_login
def index():
# формируем список правил
return render_template(
'administrator/compute/vms/index.html', vms=models.Vms.get_items())
"""Virtual Machines list"""
template = 'administrator/compute/vms/index.html'
items = models.Vms.get_items()
return render_template(template, vms=items)
@view_administrator_compute_vms.route('/<uuid:vm_id>', methods=['GET'])

View file

@ -1,16 +1,14 @@
# coding: utf-8
"""Stack Web Services LLC"""
# from uuid import uuid4
# import validators
from flask import Blueprint, flash, g, jsonify, redirect, render_template, request, session, url_for
from SWSCloudCore.controllers.administrators import ControllerAdministrators
import validators
from flask import Blueprint, redirect, render_template, request, url_for
from SWSCloudCore.controllers.tasks.manage import ControllerManageTasks
from SWSCloudAdministrator.Administrator.common import requires_login
from SWSCloudCore import models
view_administrator_tasks = Blueprint('administrator_tasks', __name__, url_prefix='/administrator/tasks')
view_administrator_tasks = Blueprint(
'administrator_tasks', __name__,
url_prefix='/administrator/tasks')
@view_administrator_tasks.route('/', methods=['GET'])
@ -25,23 +23,29 @@ def index():
@view_administrator_tasks.route('/edit.html', methods=['GET'])
@requires_login
def edit():
task_id = request.args.get('task_id')
# TODO: check exists
task_id = request.form.get('task_id')
if not validators.uuid(task_id) or not models.Tasks.exists(task_id):
return redirect(url_for('administrator_tasks.index'))
task = ControllerManageTasks().get_task(task_id)
return render_template(
'administrator/tasks/edit.html',
task=ControllerManageTasks().get_task(task_id))
task=task)
@view_administrator_tasks.route('/edit.html', methods=['POST'])
@requires_login
def edit_post():
task_id = request.form.get('task_id')
# todo: validate
status = request.form.get('status')
# TODO: check exists
x = models.Tasks.update(status=request.form.get('status')).where(models.Tasks.id == task_id)
x.execute()
if not validators.uuid(task_id) or not models.Tasks.exists(task_id):
return redirect(url_for('administrator_tasks.index'))
task = models.Tasks.update(
status=status
).where(models.Tasks.id == task_id)
task.execute()
return redirect(url_for('administrator_tasks.edit', task_id=task_id))
@ -51,11 +55,13 @@ def edit_post():
def delete():
task_id = request.args.get('task_id')
# TODO: check exists
if not validators.uuid(task_id) or not models.Tasks.exists(task_id):
return redirect(url_for('administrator_tasks.index'))
task = ControllerManageTasks().get_task(task_id)
return render_template(
'administrator/tasks/delete.html',
task=ControllerManageTasks().get_task(task_id)
task=task
)
@ -64,8 +70,10 @@ def delete():
def delete_post():
task_id = request.form.get('task_id')
# TODO: check exists
x = models.Tasks.delete().where(models.Tasks.id == task_id)
x.execute()
if not validators.uuid(task_id) or not models.Tasks.exists(task_id):
return redirect(url_for('administrator_tasks.index'))
task = models.Tasks.delete().where(models.Tasks.id == task_id)
task.execute()
return redirect(url_for('administrator_tasks.index'))

View file

@ -43,7 +43,7 @@ app.register_blueprint(view_administrator_compute_containers)
# @app.errorhandler(500)
# def page_not_found(e):
# print e
# print(e)
# return render_template('errors/500.html'), 500
@ -51,7 +51,11 @@ app.register_blueprint(view_administrator_compute_containers)
def before_request():
g.settings = dict()
# извлекаем настройки и определяем их в глобальную переменную
for setting in models.Settings.select(models.Settings.key, models.Settings.val).execute():
settings = models.Settings.select(
models.Settings.key,
models.Settings.val
).execute()
for setting in settings:
g.settings[setting.key] = setting.val

View file

@ -14,8 +14,8 @@
</div>
{% endif %}
{% endwith %}
<form action="{{ url_for('administrator.login') }}" method="post">
<label for="email">email</lable>
<form action="{{ url_for('administrator.login_post') }}" method="post">
<label for="email">email</label>
<input type="text" name="email" value="" id="email" />
<label for="password">password</label>
<input type="password" name="password" value="" id="password" />

View file

@ -0,0 +1,28 @@
{% extends 'administrator/_layout.noauth.html' %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h1>Setup</h1>
<h2>Create an administrator</h2>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert-box alert">
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<form action="{{ url_for('administrator.setup') }}" method="post">
<label for="email">email</label>
<input type="text" name="email" value="" id="email" />
<label for="password">password</label>
<input type="password" name="password" value="" id="password" />
<input type="submit" value="login" class="button" />
</form>
</div>
</div>
{% endblock %}

View file

View file

@ -1,13 +1,11 @@
# coding: utf-8
import sys
import os
import ConfigParser
from configparser import ConfigParser
__config_file__ = os.getenv('CLOUD_CONFIG_FILE', '/etc/sws/cloud/core.ini')
__config_file__ = os.getenv('CONFIG', '/etc/nativecloud/config.ini')
# setting file read
config = ConfigParser.ConfigParser()
config = ConfigParser()
if os.path.exists(__config_file__):
config.read(__config_file__)
@ -30,4 +28,4 @@ if os.path.exists(__config_file__):
if not config.has_option('Database', 'password'):
sys.exit(1)
else:
sys.exit('config file not found: %s' % __config_file__)
sys.exit(f'config file not found: {__config_file__}')

View file

@ -222,7 +222,7 @@ class Datacenters:
"status": i.status
}
dcs['items'].append(dc)
# print i
# print(i)
return dcs

View file

@ -23,7 +23,7 @@ class ControllerContainers:
)
except Exception as e:
# TODO: write to log
print e
print(e)
return False
return True

View file

@ -3,9 +3,14 @@ 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
return models.Servers.select(
models.Servers.secret
).where(
models.Servers.id == server_id
).get().secret
def exists(self, server_id):
try:

View file

@ -36,7 +36,7 @@ class ControllerUsers:
def update(self, user_id, **kwargs):
if 'password' in kwargs:
x = models.Users.update(
password=md5(kwargs['password']).hexdigest()
password=md5(kwargs['password'].encode()).hexdigest()
).where(
models.Users.id == user_id
)
@ -69,7 +69,7 @@ class ControllerUsers:
:param password:
:return:
"""
password_hash = md5(password).hexdigest()
password_hash = md5(password.encode()).hexdigest()
result = models.Users.select().where(
models.Users.email == email,
models.Users.password == password_hash,
@ -86,7 +86,7 @@ class ControllerUsers:
:param password:
:return:
"""
password_hash = md5(password).hexdigest()
password_hash = md5(password.encode()).hexdigest()
user_id = uuid.uuid4()
# TODO: add date registration and update of date - =datetime.datetime.now()
user = models.Users.create(id=user_id, email=email, password=password_hash, status=1)
@ -95,7 +95,7 @@ class ControllerUsers:
return False
def password_update(self, user_id, password):
password_hash = md5(password).hexdigest()
password_hash = md5(password.encode()).hexdigest()
u = models.Users.get(models.Users.id == user_id)
u.password = password_hash
u.save()

View file

@ -35,7 +35,7 @@ class ControllerManageUsers:
models.UsersBalance
)
for j in jj:
print j.usersbalance.balance
print(j.usersbalance.balance)
return {
'total': len(jj),
'items': jj

View file

@ -1,5 +1,6 @@
# coding: utf-8
import json
from hashlib import md5
import datetime
import uuid
@ -42,6 +43,16 @@ class DataCenters(PgSQLModel):
city = CharField()
status = IntegerField(default=0)
@staticmethod
def get_available():
return DataCenters.select().where(
DataCenters.status == 1 and
DataCenters.id << Servers.select(Servers.datacenter).where(
Servers.status == 1 and
Servers.id << Ips.select(Ips.server).where(
Ips.status == 0).group_by(Ips.server)
).group_by(Servers.datacenter)).execute()
class Servers(PgSQLModel):
id = UUIDField(unique=True, primary_key=True)
@ -110,7 +121,9 @@ class Users(PgSQLModel):
@staticmethod
def auth(email, password, status=1):
if Users.select().where(
Users.email == email, Users.password == Users.hash_password(password), Users.status == status
Users.email == email,
Users.password == Users.hash_password(password),
Users.status == status
).count() == 0:
return False
return True
@ -121,7 +134,11 @@ class Users(PgSQLModel):
@staticmethod
def get_by_id(user_id):
return Users.select().where(Users.id == user_id).get()
return Users.select().where(Users.id == user_id).first()
@staticmethod
def get_by_email(email):
return Users.select().where(Users.email == email).first()
class UsersRecoveryCodes(PgSQLModel):
@ -247,6 +264,14 @@ class Vms(PgSQLModel):
def get_items():
return Vms.select()
@staticmethod
def get_user_items(user_id):
items = list()
for x in Vms.select().where(Vms.user == user_id):
items.append(dict(id=str(x.id), datacenter=str(x.datacenter.id), plan=x.plan.id, hostname=x.hostname,
osname=x.os_name, ossuite=x.os_suite, ipv4=x.ipv4, ipv6=x.ipv6, status=x.status))
return items
@staticmethod
def get_item(vm_id):
return Vms.select().where(Vms.id == vm_id).first()
@ -298,22 +323,27 @@ 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))
@staticmethod
def exists(task_id):
if Tasks.select().where(Tasks.id == task_id).count() == 0:
return False
return True
class Settings(PgSQLModel):

View file

@ -1,6 +1,9 @@
# coding: utf-8
"""Stack Web Services LLC."""
import json
import logging
from flask import Blueprint, jsonify, request, g
from flask_httpauth import HTTPBasicAuth
from SWSCloudCore.controllers.servers.server import ControllerServerStatistics
@ -8,30 +11,52 @@ from SWSCloudCore.controllers.servers.server import ControllerServerServers
from SWSCloudCore.controllers.tasks.server import ControllerTasksServer
from SWSCloudCore.controllers.containers.server import ControllerContainersServer
FORMAT = '%(asctime)-15s NODEAGENT %(levelname)s: %(message)s'
logging.basicConfig(format=FORMAT)
logger = logging.getLogger('tcpserver')
api_auth = HTTPBasicAuth()
viewServerAPI = Blueprint('ServerAPI', __name__, url_prefix='/server_api')
@api_auth.get_password
def get_pw(server_id):
logger.error(f"{server_id}")
if ControllerServerServers().exists(server_id):
g.server_id = server_id
return ControllerServerServers().get_secret(g.server_id)
return ControllerServerServers().get_secret(server_id)
return None
@api_auth.error_handler
def auth_error():
return jsonify(status='error', description='Unauthorized'), 403
description = 'Unauthorized'
return jsonify(
status='error',
description=description
), 403
@viewServerAPI.route('/ping')
@api_auth.login_required
# @api_auth.login_required
def ping():
"""
Тест. Проверка соединения и авторизации
"""
return jsonify(ping='pong', server_id=g.server_id), 200
hhh = dict()
for i in request.headers:
hhh[i[0]] = str(i[1])
return jsonify(
ping='pong',
cnt='1',
h=hhh
), 200
# TASKS
@ -65,9 +90,10 @@ def task_item():
"""
sapi = ControllerTasksServer(g.server_id)
# Если задач нет, то надо вернуть ответ с кодом 204 (no content)
# Если задач нет,
# то надо вернуть ответ с кодом 204 (no content)
if sapi.count() == 0:
return '', 204
return jsonify(status='nothing'), 204
task = sapi.queue_item_oldest_get(status=0)

View file

@ -1,5 +1,5 @@
# coding: utf-8
import logging
import os
from flask import Flask, g, render_template
from flask_babel import Babel
@ -42,7 +42,7 @@ if app.config.get('THEME_STATIC_FOLDER', False):
static_folder = app.config['THEME_STATIC_FOLDER']
if static_folder[0] != '/':
static_folder = os.path.join(app.root_path, 'static', static_folder)
print static_folder
# print(static_folder)
# Unlike templates, to serve static files from multiples folders we
# need flask-multistatic
# app.static_folder = [static_folder, os.path.join(app.root_path, 'static')]
@ -72,7 +72,6 @@ app.register_blueprint(viewServerAPI)
# /administrator
app.register_blueprint(viewAdministrator)
@app.errorhandler(404)
def page_not_found(e):
return render_template('errors/404.html'), 404
@ -90,17 +89,20 @@ def page_not_found(e):
@app.errorhandler(500)
def page_not_found(e):
print e
print(e)
return render_template('errors/500.html'), 500
@app.before_request
def before_request():
g.settings = dict()
# извлекаем настройки и определяем их в глобальную переменную
for setting in models.Settings.select(models.Settings.key, models.Settings.val).execute():
g.settings[setting.key] = setting.val
try:
# извлекаем настройки и определяем их в глобальную переменную
for setting in models.Settings.select(models.Settings.key, models.Settings.val).execute():
g.settings[setting.key] = setting.val
except Exception as e:
logging.error(e)
# exit(1)
@app.before_first_request
def before_first_request():

View file

@ -16,7 +16,7 @@ def requires_login(f):
else:
return redirect(url_for("account.logout"))
if not Users.auth(session.get('email'), session.get('password'), 1):
if not Users.auth(session.get('email'), session.get('password').encode(), 1):
return redirect(url_for("account.logout"))
return f(*args, **kwargs)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -83,6 +83,5 @@
</div>
{% endblock %}
{% block footer %}
{% endblock %}

View file

@ -5,7 +5,7 @@
{% block content %}
<div class="row">
<div class="large-12 columns">
<h3>{{ _('Вход') }}</h3>
<h2>{{ _('Вход') }}</h2>
</div>
</div>
<div class="row">

View file

@ -8,18 +8,12 @@
<h2>Регистрация</h2>
<form action="{{ url_for('account.registration') }}" method="post">
<input type="hidden" name="method" value="member_add" />
<label for="email">
Адрес ел. почты
<input type="text" name="email" value="" class="email" id="email" />
</label>
<label for="password">
Пароль
<input type="password" name="password" value="" id="password" />
</label>
<label for="password2">
Пароль (повторно)
<input type="password" name="password2" value="" id="password2" />
</label>
<label for="email">Адрес электронной почты</label>
<input type="text" name="email" value="" class="email" id="email" />
<label for="password">Пароль</label>
<input type="password" name="password" value="" id="password" />
<label for="password2">Пароль (повторно)</label>
<input type="password" name="password2" value="" id="password2" />
<input type="submit" value="Зарегистрироваться" class="button success" />
</form>
</div>

View file

@ -1,11 +0,0 @@
{% extends "default/_layout.html" %}
{% block title %}База знаний{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
{% filter markdown %}{{ kb_markdown }}{% endfilter %}
</div>
</div>
{% endblock %}

View file

@ -4,7 +4,8 @@
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Облачный хостинг GoCloud</title>
<title>{% block title %}Облачный хостинг GoCloud{% endblock %}</title>
<meta name="description" content="{% block description %}GoCloud предлагает вам арендовать виртуальные серверные мощности{% endblock %}">
<link rel="stylesheet" href="{{ url_for('static', filename='assets/css/app.css') }}">
</head>
<body>

View file

@ -7,7 +7,7 @@
<h1>Облачный хостинг</h1>
<h2>Виртуальный сервер от 200 рублей в месяц</h2>
<h2>
<a href="{{ url_for('account.registration') }}" class="button success">Создать виртуальный сервер</a>
<a href="{{ url_for('account.registration') }}" class="button alert">Создать виртуальный сервер</a>
</h2>
</div>
</div>

View file

@ -1,5 +1,9 @@
{% extends "gocloud2016/layouts/default.html" %}
{% block title %}Стоимость аренды виртуального сервера - GoCloud{% endblock %}
{% block description %}Расценки на стоимость аренды виртуальных серверов различной конфигурации{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">

View file

@ -0,0 +1,30 @@
{% extends "gocloud2016/layouts/default.html" %}
{% block title %}Поддержка онлайн виртуального сервера - GoCloud{% endblock %}
{% block description %}Наши технические специалисты ответят на ваши вопросы{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h2>Поддержка</h2>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<form action="{{ url_for('support.index_post') }}" method="post">
{% if not session['email'] %}
<label for="email">Адрес электронной почты</label>
<input type="text" name="email" id="email" />
{% else %}
<input type="hidden" name="email" value="{{ session['email'] }}" />
{% endif %}
<label for="subject">Заголовок</label>
<input type="text" name="subject" id="subject" />
<label for="message">Сообщение</label>
<textarea name="message" id="message" rows="7"></textarea>
<input type="submit" class="button success large" value="Отправить сообщение" />
</form>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,21 @@
{% extends "gocloud2016/layouts/default.html" %}
{% block title %}Поддержка онлайн виртуального сервера - GoCloud{% endblock %}
{% block description %}Наши технические специалисты ответят на ваши вопросы{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h2>Поддержка</h2>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<h3>Спасибо!</h3>
</div>
<div class="large-12 columns">
<p>Спасибо за обращение в техническую поддержку. Мы ответим вам в кратчайшее время.</p>
</div>
</div>
{% endblock %}

View file

@ -114,14 +114,15 @@ def registration():
user_id = ControllerUsers().get_id_by_email(email)
ControllerUsersDetails(user_id).details_create()
ControllerBilling().create(user_id, g.settings['bonus'])
ControllerBilling().create(user_id, g.settings.get('bonus', 0))
ControllerAPI().set(user_id=user_id, secret=user_id, acl='', status=0)
# ControllerU
# send mail message with recovery code
message = u"""
Е-почта: %s
Пароль: %s
""" % (request.form['email'], request.form['password'])
""" % (request.form.get('email'), request.form.get('password'))
subject = u'GoCloud.ru: Успешная регистрация'
lead = u"""
Поздравляем с успешной регистрацией.
@ -130,10 +131,12 @@ def registration():
Для входа в личный кабинет воспользуйтесь
<a href="https://gocloud.ru/account/login">страницей авторизации</a>.
"""
email = ControllerMessagesEmail()
email.send(title=subject, to=request.form['email'], lead=lead, message=message, callout=callout)
try:
email = ControllerMessagesEmail()
email.send(title=subject, to=request.form['email'], lead=lead, message=message, callout=callout)
except Exception as e:
# TODO: write message
pass
# redirect to login page
flash(u'Учетная запись успешно зарегистрирована.', 'success')
return redirect(url_for('account.login'))

View file

@ -1,42 +1,38 @@
# coding: utf-8
import validators
from flask import Blueprint, g, redirect, render_template, request, url_for, flash
from SWSCloudCore.controllers.common import ControllerMessagesEmail
from flask import Blueprint
from flask import g
from flask import redirect
from flask import render_template
from flask import request
from flask import url_for
viewSupport = Blueprint('support', __name__, url_prefix='/support')
@viewSupport.route('/', methods=['GET', 'POST'])
@viewSupport.route('/', methods=['GET'])
def index():
# ControllerMessagesEmail().send()
# print session
if request.method == "POST":
print request.form
# TODO: validate
ticket_title = request.form['title']
ticket_message = request.form['message']
ticket_email = request.form['email']
# send mail message with recovery code
subject = ticket_title
message = ticket_message
lead = u'Отправитель: %s' % ticket_email
callout = u''
email = ControllerMessagesEmail()
# email.send(title=subject, to=ticket_email, lead=lead, message=message, callout=callout)
email.send(title=subject, to=g.settings['contacts.email'], lead=lead, message=message, callout=callout)
return redirect(url_for('support.thank'))
return render_template('default/support/index.html')
return render_template('gocloud2016/pages/support/index.html')
@viewSupport.route('/thank')
@viewSupport.route('/', methods=['POST'])
def index_post():
ticket_subject = request.form.get('subject')
ticket_message = request.form.get('message')
ticket_email = request.form.get('email')
if not validators.email(ticket_email):
flash('Некорректный адрес электронной почты', category='error')
return redirect(url_for('support.index'))
# send mail message with recovery code
lead = u'Отправитель: %s' % ticket_email
callout = u''
email = ControllerMessagesEmail()
# email.send(title=subject, to=ticket_email, lead=lead, message=message, callout=callout)
email.send(
title=ticket_subject, to=g.settings.get('contacts.email'), lead=lead, message=ticket_message, callout=callout)
return redirect(url_for('support.thank'))
@viewSupport.route('/thank.html')
def thank():
return render_template('default/support/thank.html')
return render_template('gocloud2016/pages/support/thanks.html')

View file

@ -23,7 +23,7 @@ def view(document_name):
if not os.path.exists('docs/%s.md' % document_name):
return redirect(url_for('homepage.index'))
#
print document_name
print(document_name)
doc_markdown = u''
for ss in file('docs/%s.md' % document_name, 'r'):
doc_markdown += ss.decode('UTF-8')

View file

@ -2,8 +2,13 @@ import requests
class SWSStatisticsClient(object):
def get_vm(self, vm_id, limit=96):
r = requests.get('http://server-stats.gocloud.ru/stats/v1/compute/vms/%s' % vm_id, params={'limit': limit})
def get_vm(self, vm_id: str, limit: int = 96):
r = requests.get(
f"http://server-stats.gocloud.ru/stats/v1/compute/vms/{vm_id}",
params={
'limit': limit
}
)
if r.status_code == 200:
return r.json()
return None

5
cloud-admin-add.py Normal file → Executable file
View file

@ -1,6 +1,7 @@
#!/usr/bin/env python
# coding: utf-8
import sys
import argparse
import validators
from hashlib import md5
@ -25,13 +26,13 @@ if not validators.email(args.email):
admin_id = uuid4()
admin_email = args.email
admin_password = md5(args.password).hexdigest()
admin_password = md5(args.password.encode()).hexdigest()
models.database.connect()
if models.Admins.select().where(models.Admins.email == args.email).count() == 0:
models.Admins.create(id=admin_id, email=admin_email, password=admin_password, status=1)
else:
print "already exists"
print("already exists")
models.database.close()

12
cloud-admin-ls.py Normal file → Executable file
View file

@ -9,13 +9,13 @@ __author__ = 'vanzhiganov'
admins_total = models.Admins.select().count()
admins_items = models.Admins.select()
print "Total admins: %i" % admins_total
print("Total admins: %i" % admins_total)
if admins_total == 0:
print ''
print('')
else:
print 'List:'
print('List:')
for item in admins_items:
print '%s\t%s\t%s' % (item.id, item.email, item.status)
print '---'
print 'For create a new admin account use command "procdn-admin-add --email <email> --password <password>"'
print('%s\t%s\t%s' % (item.id, item.email, item.status))
print('---')
print('For create a new admin account use command "procdn-admin-add --email <email> --password <password>"')

10
cloud-admin-password.py Normal file → Executable file
View file

@ -18,13 +18,13 @@ args = parser.parse_args()
admin_id = uuid4()
# todo: validate admin email
admin_email = args.email
admin_password = md5(args.password).hexdigest()
admin_password = md5(args.password.encode()).hexdigest()
if models.Admins.select().where(models.Admins.email == args.email).count() == 0:
print "Admin account with email '%s' not exists." % admin_email
print '---'
print 'For create a new admin account use command "procdn-admin-add --email <email> --password <password>"'
print("Admin account with email '%s' not exists." % admin_email)
print('---')
print('For create a new admin account use command "procdn-admin-add --email <email> --password <password>"')
else:
query = models.Admins.update(password=admin_password).where(models.Admins.email == admin_email)
query.execute()
print 'Password updated.'
print('Password updated.')

10
cloud-cron-balance.py Normal file → Executable file
View file

@ -8,13 +8,13 @@ from SWSCloudCore.controllers.vms import ControllerVMS
nb = models.Settings.get_item('NEGATIVE_BALANCE')
if int(models.Settings.get_item('SERVICE_VMS_ENABLE')) == 1:
print 'total vms:', models.Vms.select().where(models.Vms.status == 1).count()
print('total vms:', models.Vms.select().where(models.Vms.status == 1).count())
for vm in models.Vms.select().where(models.Vms.status == 1):
# Высчитываем, сколько стоит виртуальная машина 15 минут
price_quarter = vm.plan.price / 30 / 24 / 4
print dict(id=vm.id, user=vm.user.id, plan=vm.plan.id, cost_mo=vm.plan.price, cost_quarter=price_quarter)
print(dict(id=vm.id, user=vm.user.id, plan=vm.plan.id, cost_mo=vm.plan.price, cost_quarter=price_quarter))
# Списание средств
x = models.UsersBalance.update(
@ -26,14 +26,14 @@ if int(models.Settings.get_item('SERVICE_VMS_ENABLE')) == 1:
user_balance = models.UsersBalance.select(
models.UsersBalance.balance).where(models.UsersBalance.user == vm.user.id).get().balance
if -500 > user_balance and models.Vms.get_state(vm.id) == 1:
print "user_balance", user_balance
print("user_balance", user_balance)
ControllerVMS(vm.user.id).status_set(vm.id, 3)
# Создание задания
ControllerTasks(vm.user.id).create(vm.datacenter.id, vm.server.id, 'vm_stop', 0, vm_id=vm.id)
if int(models.Settings.get_item('SERVICE_CONTAINERS_ENABLE')) == 1:
print 'total containers:', models.Containers.select().count()
print('total containers:', models.Containers.select().count())
for container in models.Containers.select():
container_state = models.ContainersStatisticsState.select().where(
models.ContainersStatisticsState.container == container.id
@ -43,7 +43,7 @@ if int(models.Settings.get_item('SERVICE_CONTAINERS_ENABLE')) == 1:
# # Высчитываем, сколько стоит виртуальная машина 15 минут
price_quarter = min_price / 30 / 24 / 4
#
# print dict(id=vm.id, user=vm.user.id, plan=vm.plan.id, cost_mo=vm.plan.price, cost_quarter=price_quarter)
# print(dict(id=vm.id, user=vm.user.id, plan=vm.plan.id, cost_mo=vm.plan.price, cost_quarter=price_quarter))
#
# Списание средств
x = models.UsersBalance.update(

0
cloud-db-init.py Normal file → Executable file
View file

2
cloud-dc-add.py Normal file → Executable file
View file

@ -28,4 +28,4 @@ if models.DataCenters.select().where(
status=1
)
else:
print "Data center with code '%s' already exists." % args.code
print("Data center with code '%s' already exists." % args.code)

12
cloud-dc-ls.py Normal file → Executable file
View file

@ -25,13 +25,13 @@ x = models.Ips.select().join(models.Servers).where(
).first()
print 'total: %s' % total
print 'items: '
print('total: %s' % total)
print('items: ')
for item in items:
print 'id: %s code: %s name: %s country: %s, city: %s, status: %s' % (
print('id: %s code: %s name: %s country: %s, city: %s, status: %s' % (
item.id, item.code, item.name, item.country, item.city, item.status
)
))
print '---'
print 'if you want to add a new data center, use cli-dc-add.py --'
print('---')
print('if you want to add a new data center, use cli-dc-add.py --')

2
cloud-invoicer.py Normal file → Executable file
View file

@ -169,7 +169,7 @@ html = u"""
</html>
"""
print type(html)
print(type(html))
pdf = MyFPDF()
# First page
pdf.add_page()

0
cloud-invoicer2.py Normal file → Executable file
View file

4
cloud-ip-add.py Normal file → Executable file
View file

@ -3,7 +3,7 @@
import argparse
from SWSCloudCore import models
from SWSCloudCore.controllers import ControllerManageIPs
from SWSCloudCore.controllers.ips.manage import ControllerManageIPs
parser = argparse.ArgumentParser(description='')
parser.add_argument('--dc', dest="datacenter")
@ -30,5 +30,5 @@ if success:
args.datacenter, args.server, args.ipv4, args.ipv4_gateway, args.ipv6, args.ipv6_gateway, args.status
)
else:
print 'fail'
print('fail')
# print "Admin account with email '%s' already exists." % args

0
cloud-runserver-admin.py Normal file → Executable file
View file

1
cloud-runserver.py Normal file → Executable file
View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# coding: utf-8
from SWSCloudWeb import app

4
cloud-server-add.py Normal file → Executable file
View file

@ -2,7 +2,7 @@
import argparse
from uuid import uuid4
from SWSCloudCore.controllers import ControllerManageServer
from SWSCloudCore.controllers.servers.manage import ControllerManageServer
parser = argparse.ArgumentParser(description='')
parser.add_argument('--dc', dest="datacenter")
@ -21,5 +21,5 @@ if not ControllerManageServer().check_exists(args.ip, None, args.hostname):
args.ip, None, args.status
)
else:
print 'fail'
print('fail')
# print "Admin account with email '%s' already exists." % args

8
cloud-server-ls.py Normal file → Executable file
View file

@ -16,10 +16,10 @@ items = models.Servers.select().where(
models.Servers.status == args.status
)
print 'total: %s' % total
print 'items: '
print('total: %s' % total)
print('items: ')
for item in items:
print 'id: %s dc: %s status: %s ip: %s hostname: %s' % (
print('id: %s dc: %s status: %s ip: %s hostname: %s' % (
item.id, item.datacenter.id, item.status, item.ip, item.hostname
)
))

2
cloud-settings-init.py Normal file → Executable file
View file

@ -7,7 +7,7 @@ def create_key(key, val=''):
if models.Settings.select().where(models.Settings.key == key).count() == 0:
models.Settings.create(key=key, val=val)
else:
print 'key %s already exists' % key
print('key %s already exists' % key)
create_key('bonus', '300')

0
cloud-settings.py Normal file → Executable file
View file

View file

@ -1 +0,0 @@
# Политика конфиденциальности

View file

@ -1,34 +0,0 @@
# Правила и условия использования хостинга
## Нарушение закона
Все предоставляемые услуги могут использоваться только для целей не противоречащих действующему общегосударственному и
международному законодательству. Пользователь несет полную ответственность за публикуемые материалы. Содержимое сайтов
и иных ресурсов клиентов может быть раскрыто третьим лицам не иначе, как в установленном Законом порядке.
## Нарушение прав третьих лиц
Примеры некорректных действий включают в себя рассылку информации частного характера о персоне без ее согласия,
нарушение прав интеллектуальной собственности, распространение клеветы на персону или юридическое лицо. Блокирование
сайта может быть вызвано ущемлением законных прав третьих лиц.
## Информационное содержание ресурса
При нарушении следующих правил Ваш ресурс может быть заблокирован или удален:
- Запрещается размещать материалы порнографического характера и ссылки на них.
- Запрещена рассылка спама и всех его проявлений.
- Не разрешается запуск резидентных программ.
- Не допускается запуск скриптов, вызывающих критическую загрузку сервера.
- Запрещается размещение материалов, нарушающее авторские права.
## Примите во внимание
Мы не несем ответственности за действие или бездействие третьих лиц в случае, если оно нарушает целостность сети
Интернет или отдельных ее сегментов, приводя к невозможности обеспечения связи, доступа или доставки данных (например,
электронной почты) между клиентом и сторонними участниками сети Интернет. Ответственность за безопасность использования
клиентом программного обеспечения третьих лиц лежит на клиенте.
В дополнение к этому, администрация компании оставляет за собой право в любое время вносить уточнения и дополнения в
настоящие правила, своевременно уведомляя пользователей. Нарушение пользователями настоящих правил будет
квалифицироваться как несоблюдение договорных отношений вплоть до отключения аккаунта.

View file

@ -1,9 +1,9 @@
[Database]
host = localhost
user = postgres
password = postgres
user = cherry
password = P@ss5476
port = 5432
name = gocloud
name = testdb
[Application]
DEBUG = true

View file

@ -1,19 +1,23 @@
[uwsgi]
virtualenv = /home/gocloud/env
env = HOME=/opt/nativecloud/.venv
env = CONFIG=/opt/nativecloud/extra/settings.origin.ini
chdir = /opt/nativecloud
;for http
;protocol = http
;socket = 127.0.0.1:8080
protocol = http
socket = 0.0.0.0:8080
; for unix-socket
socket = /var/run/sws/gocloud_web.sock
chmod-socket = 777
; socket = /var/run/nativecloud-web.sock
; chmod-socket = 777
module = SWSCloudWeb:app
master = true
processes = 2
vacuum = true
die-on-term = true
thunder-lock = true
enable-threads = true

View file

@ -1,13 +0,0 @@
# База знаний
## Обзие вопросы
- Как создать контейнер
- Как оплатить
-
## API
- Описание
- Запросы
- Коды ошибок

View file

@ -1,57 +0,0 @@
%PDF-1.4
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<< /F1 2 0 R /F2 3 0 R /F3 4 0 R >>
endobj
2 0 obj
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
endobj
3 0 obj
<< /BaseFont /ZapfDingbats /Encoding /ZapfDingbatsEncoding /Name /F2 /Subtype /Type1 /Type /Font >>
endobj
4 0 obj
<< /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font >>
endobj
5 0 obj
<< /Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
6 0 obj
<< /Outlines 10 0 R /PageMode /UseNone /Pages 8 0 R /Type /Catalog >>
endobj
7 0 obj
<< /Author (anonymous) /CreationDate (D:20161016043545-03'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20161016043545-03'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False >>
endobj
8 0 obj
<< /Count 1 /Kids [ 5 0 R ] /Type /Pages >>
endobj
9 0 obj
<< /Filter [ /ASCII85Decode /FlateDecode ] /Length 735 >>
stream
GasJPgN)"%&;KYAnN1Qb2mh$p3r4rMVN;4S9M8:0o\'IG#dN4>AdE<^Be<hY@c;s8q=i@@FtJURd5T$fOTF5_E-4g)1.YG2KeFQoJ8+#&rd#f(=\4%YGebF-,<qiQl'Vh@an4dMP`TG>kQ+u/`Zr=3r2g^b-k.lUmI^LCk74u@CK)JQ#\18LWr5OS(-LdAS.D-;?`\=9'WQ4E)2H=GYuQ&Q:IVk]/;C:l,6%eP0-JM^Zo*hl9jJh13EmLqHkqBD>Fd\H2g+u@9V&>(\Lr(ZQ1*g4Q1/*N?/uhi?OS@-82hCT,T;,0dWmd#HA`%oY>R#_4KDHdZUmAd&#4H%(AsJ1C4KcP[FDkE/;>k(8W,b"d_+GdLB1<BW$RY%:1"40!+_$"V>@5R;R"gGohPUPnc7,oXVAuZmRX:!mDlIV+%o0q+r6%6G_c\l:h4ZQ0a*n,/G=3b/IIli@D4@7"^rsL,8!"o'B7*N6I_.<76^h:?OIIk_oRsp`I=[aXl(P.[]4MPhpSe,6WhKr^h$#^6Q'EJ(Cf#9[g^o.O'pVP1<l/9g\KR2>FGms]h6\mnF++Nc#`c[5M^T0T1R[^UYMBR$o3nG#;>SA&Z)_+*ZRTi=A]Th,)r\&#?IWGdY82-R'\?<!NN$c<6bWHVXIL#)60S&<+<jAYeJb)DkoSHQqsV@:.N>%O@5Fq@s],dSsSJJS`X-9'K]D3V<LYJ[Au3rWiC:C+3rf(rW.VMNog~>endstream
endobj
10 0 obj
<< /Count 0 /Type /Outlines >>
endobj
xref
0 11
0000000000 65535 f
0000000075 00000 n
0000000129 00000 n
0000000239 00000 n
0000000357 00000 n
0000000472 00000 n
0000000669 00000 n
0000000757 00000 n
0000001057 00000 n
0000001119 00000 n
0000001949 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
[(F\377\262C\004ZI\203\233\321\244^\250\251\025\300) (F\377\262C\004ZI\203\233\321\244^\250\251\025\300)]
/Info 7 0 R /Root 6 0 R /Size 11 >>
startxref
1999
%%EOF

7
mngr.wsgi Normal file
View file

@ -0,0 +1,7 @@
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/opt/nativecloud")
from SWSCloudAdministrator import app as application

7
nativecloud.wsgi Normal file
View file

@ -0,0 +1,7 @@
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/opt/nativecloud")
from SWSCloudWeb import app as application

38
requirements.txt Normal file
View file

@ -0,0 +1,38 @@
async-timeout==5.0.1
babel==2.16.0
certifi==2024.8.30
charset-normalizer==3.4.0
click==8.1.7
configparser==7.1.0
dateutils==0.6.12
decorator==5.1.1
ecdsa==0.19.0
Flask==0.12.5
Flask-Babel==0.9
Flask-HTTPAuth==3.1.1
Flask-Markdown==0.3
flask-multistatic==1.0
flask-peewee==0.6.0
idna==3.10
importlib_metadata==8.5.0
itsdangerous==2.0.1
Jinja2==2.8
Markdown==3.7
MarkupSafe==2.0.1
peewee==2.8.0
psycopg2-binary==2.9.10
pycrypto==2.6.1
python-dateutil==2.9.0.post0
pytz==2024.2
pyuwsgi==2.0.28.post1
redis==5.2.1
requests==2.32.3
six==1.17.0
speaklater==1.3
sshpubkeys==1.0.6
urllib3==2.2.3
validators==0.10
Werkzeug==0.16.1
wtf-peewee==0.2.6
WTForms==3.2.1
zipp==3.21.0

View file

@ -1,10 +1,12 @@
# coding: utf-8
import os
from setuptools import setup
with open('requirements.txt') as f:
required = f.read().splitlines()
setup(
name='SWSCloudCore',
version='2.7.9',
version='2.7.10',
author='Vyacheslav Anzhiganov',
author_email='hello@anzhiganov.com',
packages=[
@ -79,7 +81,6 @@ setup(
'templates/default/documents/*.html',
'templates/default/homepage/*.html',
'templates/default/id/*.html',
'templates/default/kb/*.html',
'templates/default/payment/*.html',
'templates/default/payment/robokassa/*.html',
'templates/default/support/*.html',
@ -90,6 +91,7 @@ setup(
'templates/gocloud2016/layouts/*.html',
'templates/gocloud2016/macros/*.html',
'templates/gocloud2016/pages/*.html',
'templates/gocloud2016/pages/*/*.html',
# Errors
'templates/errors/*.html',
],
@ -118,7 +120,6 @@ setup(
'templates/administrator/settings/messages/*.html',
'templates/administrator/tasks/*.html',
'templates/administrator/users/*.html',
# 'templates/administrator/payments/*.html',
'templates/administrator/wiki/*.html',
'templates/administrator/wiki/article/*.html',
'templates/administrator/wiki/category/*.html',
@ -146,22 +147,5 @@ setup(
# billing
'cloud-cron-balance.py',
],
install_requires=[
'Flask==0.10',
'Flask-Markdown==0.3',
'Flask-Babel==0.9',
'flask-peewee==0.6.0',
'flask-multistatic',
'Jinja2==2.8',
'peewee==2.8',
'validators==0.10',
'psycopg2==2.6.1',
'configparser',
'flask_httpauth==3.1.1',
'requests==2.7',
'uWSGI==2.0.11.1',
'wsgiref==0.1.2',
'sshpubkeys==1.0.6',
'dateutils',
]
install_requires=required
)

Binary file not shown.