mirror of
https://github.com/ThomasGsp/HyperProxmox.git
synced 2025-03-09 15:40:18 +00:00
first commit
This commit is contained in:
commit
5352a2b94a
396 changed files with 10008 additions and 0 deletions
76
code/scripts/main/api/README.md
Normal file
76
code/scripts/main/api/README.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
### General
|
||||
|
||||
For all get request, there are a possibility to pass a payloads with differents param in json
|
||||
```code
|
||||
{'key1': 'value1', 'key2': 'value2'}
|
||||
```
|
||||
|
||||
All actions need a valid ticket. This ticket is generate when the client valid the connexion on the backend php.
|
||||
it's saved in the database with an expiration key.
|
||||
Each tickets are uniq.
|
||||
|
||||
Example to dump database:
|
||||
``` code
|
||||
GET /api/v1/instance/<instanceid>/database/<databaseid> -d '{'userid': '1', 'ticket': 'SFQSF22dFF','action': 'dump'}'
|
||||
```
|
||||
|
||||
##### Instance management
|
||||
Actions limited to proxmox api (wrapper)
|
||||
```code
|
||||
GET /api/v1/instance
|
||||
GET /api/v1/instance/<instanceid>
|
||||
POST /api/v1/instance/<instanceid>
|
||||
PUT /api/v1/instance/<instanceid>
|
||||
DELETE /api/v1/instance/<instanceid>
|
||||
```
|
||||
|
||||
##### Packages management
|
||||
Actions in the instances for packages managements
|
||||
```code
|
||||
GET /api/v1/instance/<instanceid>/package
|
||||
POST /api/v1/instance/<instanceid>/packages
|
||||
PUT /api/v1/instance/<instanceid>/packages
|
||||
DELETE /api/v1/instance/<instanceid>/package
|
||||
```
|
||||
|
||||
##### vhosts management
|
||||
Actions in the instances for packages managements
|
||||
```code
|
||||
GET /api/v1/instance/<instanceid>/vhost
|
||||
GET /api/v1/instance/<instanceid>/vhost/<vhostid>
|
||||
POST /api/v1/instance/<instanceid>/vhost/<vhostid>
|
||||
PUT /api/v1/instance/<instanceid>/vhost/<vhostid>
|
||||
DELETE /api/v1/instance/<instanceid>/vhost/<vhostid>
|
||||
```
|
||||
|
||||
##### Databases
|
||||
Actions in the instances for packages managements
|
||||
```code
|
||||
GET /api/v1/instance/<instanceid>/database
|
||||
GET /api/v1/instance/<instanceid>/database/<databaseid>
|
||||
POST /api/v1/instance/<instanceid>/database/<databaseid>
|
||||
PUT /api/v1/instance/<instanceid>/database/<databaseid>
|
||||
DELETE /api/v1/instance/<instanceid>/database/<databaseid>
|
||||
```
|
||||
|
||||
##### Nodes management
|
||||
Actions to proxmox nodes availables
|
||||
```code
|
||||
GET /api/v1/node
|
||||
GET /api/v1/node/<nodeid>
|
||||
```
|
||||
|
||||
##### services management
|
||||
```code
|
||||
GET /api/v1/service/ssl/instance/<instanceid>/vhost/<vhostid>
|
||||
GET /api/v1/service/ssl/instance/<instanceid>/vhost/<vhostid>
|
||||
POST api/v1/service/ssl/instance/<instanceid>/vhost/<vhostid>
|
||||
PUT /api/v1/service/ssl/instance/<instanceid>/vhost/<vhostid>
|
||||
DELETE /api/v1/service/ssl/instance/<instanceid>/vhost/<vhostid>
|
||||
|
||||
GET /api/v1/service/cache/instance/<instanceid>/vhost/<vhostid>
|
||||
GET /api/v1/service/cache/instance/<instanceid>/vhost/<vhostid>
|
||||
POST api/v1/service/cache/instance/<instanceid>/vhost/<vhostid>
|
||||
PUT /api/v1/service/cache/instance/<instanceid>/vhost/<vhostid>
|
||||
DELETE /api/v1/service/cache/instance/<instanceid>/vhost/<vhostid>
|
||||
```
|
2
code/scripts/main/api/v1/__init__.py
Normal file
2
code/scripts/main/api/v1/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
BIN
code/scripts/main/api/v1/__pycache__/__init__.cpython-35.pyc
Normal file
BIN
code/scripts/main/api/v1/__pycache__/__init__.cpython-35.pyc
Normal file
Binary file not shown.
BIN
code/scripts/main/api/v1/__pycache__/api.cpython-35.pyc
Normal file
BIN
code/scripts/main/api/v1/__pycache__/api.cpython-35.pyc
Normal file
Binary file not shown.
129
code/scripts/main/api/v1/api.py
Normal file
129
code/scripts/main/api/v1/api.py
Normal file
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import threading
|
||||
import web
|
||||
from core.core import *
|
||||
from core.modules.mod_analyst import *
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import ast
|
||||
|
||||
|
||||
class Auth:
|
||||
def POST(self):
|
||||
# '{"username":"fff", "password":"azerty"}'
|
||||
data = json.loads(web.data().decode('utf-8'))
|
||||
print(data["username"])
|
||||
# Test Login
|
||||
|
||||
# If true generate an ticket
|
||||
return
|
||||
|
||||
class Cluster:
|
||||
def GET(self, cluster=None):
|
||||
if cluster:
|
||||
return core.get_cluster(cluster)
|
||||
else:
|
||||
return core.get_cluster()
|
||||
|
||||
def POST(self):
|
||||
data = json.loads(web.data().decode('utf-8'))
|
||||
return core.insert_cluster(data)
|
||||
|
||||
def PUT(self, cluster):
|
||||
data = json.loads(web.data().decode('utf-8'))
|
||||
return core.change_cluster(cluster, data)
|
||||
|
||||
def DELETE(self, cluster):
|
||||
return core.delete_cluste(cluster)
|
||||
|
||||
|
||||
class Instance:
|
||||
def GET(self, vmid=None, status=None):
|
||||
if status:
|
||||
""" GET INSTANCE STATUS """
|
||||
return core.status_instance(vmid, status)
|
||||
elif vmid:
|
||||
""" GET INSTANCE INFORMATION """
|
||||
return core.info_instance(vmid)
|
||||
|
||||
def POST(self, vmid=None, status=None):
|
||||
if vmid:
|
||||
""" GET INSTANCE INFORMATION """
|
||||
return core.status_instance(vmid, status)
|
||||
else:
|
||||
""" CREATE NEWS INSTANCES"""
|
||||
count = json.loads(web.data().decode('utf-8'))["count"]
|
||||
|
||||
""" GENERATE UNIQ COMMAND ID """
|
||||
randtext = ''.join(random.choice('0123456789ABCDEF') for i in range(8))
|
||||
command_id = "{0}_{1}_{2}".format(time.time(), count, randtext)
|
||||
|
||||
""" LOAD CLUSTER CONFIGURATIONS """
|
||||
select = Analyse(core.clusters_conf, generalconf)
|
||||
sorted_nodes = dict(select.set_attribution(count))
|
||||
|
||||
""" START ALL Thread """
|
||||
for target, count in sorted_nodes.items():
|
||||
# Limit to 5 instance per block
|
||||
thci = threading.Thread(name="Insert Instance",
|
||||
target=core.insert_instance,
|
||||
args=(target, str(count), command_id,))
|
||||
|
||||
thci.start()
|
||||
|
||||
""" Wait all results of Thread from redis messages queue. Valid or not """
|
||||
timeout = 2 * int(generalconf["deploy"]["concurrencydeploy"]) * int(generalconf["deploy"]["delayrounddeploy"])
|
||||
for t in range(timeout):
|
||||
time.sleep(1)
|
||||
try:
|
||||
if len(ast.literal_eval(Lredis.get_message(command_id))) == int(count):
|
||||
break
|
||||
except BaseException as err:
|
||||
print("Value not found", err)
|
||||
|
||||
""" Return messages """
|
||||
return ast.literal_eval(Lredis.get_message(command_id))
|
||||
|
||||
def PUT(self, vmid):
|
||||
data = json.loads(web.data().decode('utf-8'))
|
||||
return core.change_instance(vmid, data)
|
||||
|
||||
def DELETE(self, vmid):
|
||||
return core.delete_instance(vmid)
|
||||
|
||||
|
||||
class ThreadAPI(threading.Thread):
|
||||
def __init__(self, threadid, name, urls, c, g, r):
|
||||
""" Pass Global var in this theard."""
|
||||
global core, generalconf, Lredis
|
||||
core = c
|
||||
generalconf = g
|
||||
Lredis = r
|
||||
|
||||
""" RUN API """
|
||||
threading.Thread.__init__(self)
|
||||
self.threadID = threadid
|
||||
self.threadName = name
|
||||
self.app = HttpApi(urls, globals())
|
||||
self.app.notfound = notfound
|
||||
|
||||
def run(self):
|
||||
print("Start API server...")
|
||||
self.app.run()
|
||||
|
||||
def stop(self):
|
||||
print("Stop API server...")
|
||||
self.app.stop()
|
||||
|
||||
|
||||
def notfound():
|
||||
return web.notfound({"value": "Bad request"})
|
||||
|
||||
|
||||
class HttpApi(web.application):
|
||||
def run(self, ip="127.0.0.1", port=8080, *middleware):
|
||||
func = self.wsgifunc(*middleware)
|
||||
return web.httpserver.runsimple(func, (ip, int(port)))
|
0
code/scripts/main/cli/README.md
Normal file
0
code/scripts/main/cli/README.md
Normal file
0
code/scripts/main/cli/command.py
Normal file
0
code/scripts/main/cli/command.py
Normal file
3
code/scripts/main/core/README.md
Normal file
3
code/scripts/main/core/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
##### Core funtions
|
||||
|
||||
The core is divised manage load differents modules with the goal to manage then and orchestrate all function.
|
BIN
code/scripts/main/core/__pycache__/core.cpython-35.pyc
Normal file
BIN
code/scripts/main/core/__pycache__/core.cpython-35.pyc
Normal file
Binary file not shown.
327
code/scripts/main/core/core.py
Normal file
327
code/scripts/main/core/core.py
Normal file
|
@ -0,0 +1,327 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Author: Tlams
|
||||
Langage: Python
|
||||
Minimum version require: 3.4
|
||||
"""
|
||||
|
||||
from core.modules.mod_proxmox import *
|
||||
from core.modules.mod_database import *
|
||||
from core.modules.mod_analyst import *
|
||||
from core.modules.mod_access import *
|
||||
from core.libs.hcrypt import *
|
||||
from netaddr import iter_iprange
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
def RunAnalyse(clusters_conf, generalconf, delay=300):
|
||||
play = Analyse(clusters_conf, generalconf)
|
||||
|
||||
while True:
|
||||
play.run()
|
||||
time.sleep(delay)
|
||||
|
||||
|
||||
class Core:
|
||||
|
||||
def __init__(self, generalconf, Lredis):
|
||||
|
||||
self.generalconf = generalconf
|
||||
self.Lredis = Lredis
|
||||
|
||||
""" LOAD MONGODB """
|
||||
self.mongo = MongoDB(generalconf["mongodb"]["ip"])
|
||||
self.mongo.client = self.mongo.connect()
|
||||
|
||||
""" LOAD REDIS """
|
||||
self.redis_msg = Lredis
|
||||
#self.redis_msg.co = self.redis_msg.connect()
|
||||
|
||||
if self.mongo.client and self.redis_msg.connect():
|
||||
self.mongo.db = self.mongo.client.db
|
||||
|
||||
""" Others """
|
||||
# value
|
||||
self.concurrencydeploy = generalconf["deploy"]["concurrencydeploy"]
|
||||
# in seconds
|
||||
self.delayrounddeploy = generalconf["deploy"]["delayrounddeploy"]
|
||||
|
||||
""" RUN THE ANALYZER IN DEDICATED THEARD"""
|
||||
self.clusters_conf = self.mongo.get_clusters_conf()
|
||||
|
||||
thc = threading.Thread(name="Update statistics",
|
||||
target=RunAnalyse,
|
||||
args=(self.clusters_conf, self.generalconf))
|
||||
thc.start()
|
||||
|
||||
"""
|
||||
#######################
|
||||
# INSTANCE MANAGEMENT #
|
||||
#######################
|
||||
"""
|
||||
def insert_instance(self, target, count=1, command_id=000000):
|
||||
|
||||
""" Find cluster informations from node """
|
||||
lastkeyvalid = self.mongo.get_last_datekey()
|
||||
node_informations = self.mongo.get_nodes_informations((int(lastkeyvalid["value"])), target)
|
||||
cluster_informations = self.mongo.get_clusters_conf(node_informations["cluster"])
|
||||
|
||||
proxmox_cluster_url = cluster_informations["url"]
|
||||
proxmox_cluster_port = cluster_informations["port"]
|
||||
proxmox_cluster_user = pdecrypt(cluster_informations["user"],self.generalconf["keys"]["key_pvt"])
|
||||
proxmox_cluster_pwd = pdecrypt(cluster_informations["password"], self.generalconf["keys"]["key_pvt"])
|
||||
|
||||
proxmox_template = cluster_informations["template"]
|
||||
proxmox_storage_disk = cluster_informations["storage_disk"]
|
||||
|
||||
""" LOAD PROXMOX """
|
||||
proxmox = Proxmox(target)
|
||||
|
||||
proxmox.get_ticket("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
proxmox_cluster_user,
|
||||
proxmox_cluster_pwd)
|
||||
|
||||
returnlistresult = []
|
||||
currentcount = 0
|
||||
for c in range(0, int(count)):
|
||||
|
||||
if currentcount == self.concurrencydeploy:
|
||||
time.sleep(self.delayrounddeploy)
|
||||
currentcount = 0
|
||||
|
||||
currentcount = currentcount + 1
|
||||
|
||||
get_info_system = self.mongo.get_system_info()
|
||||
""" FIND NEXT INSTANCE ID AVAILABLE AND INCREMENT IT"""
|
||||
next_instance_id = int(get_info_system["instances_number"]+1)
|
||||
|
||||
""" FIND LAST LAST IP USE AND INCREMENT IT"""
|
||||
if not get_info_system["IP_free"]:
|
||||
get_instance_ip = get_info_system["IP_current"]
|
||||
next_ip = iter_iprange(get_instance_ip, '172.16.255.250', step=1)
|
||||
# Revoir pour un truc plus clean ....
|
||||
next(next_ip)
|
||||
ip = str(next(next_ip))
|
||||
else:
|
||||
ip = str(get_info_system["IP_free"][0])
|
||||
self.mongo.update_system_delete_ip(ip)
|
||||
|
||||
|
||||
""" INSTANCE DEFINITION """
|
||||
data = {
|
||||
'ostemplate': proxmox_template,
|
||||
'vmid': next_instance_id,
|
||||
'storage': proxmox_storage_disk,
|
||||
'cores': 1,
|
||||
'cpulimit': 1,
|
||||
'cpuunits': 512,
|
||||
'arch': "amd64",
|
||||
'memory': 256,
|
||||
'description': command_id,
|
||||
'onboot': 0,
|
||||
'swap': 256,
|
||||
'ostype': 'debian',
|
||||
'net0': 'name=eth0,bridge=vmbr1,ip={0}/16,gw=172.16.1.254'.format(ip),
|
||||
'ssh-public-keys': get_info_system["sshpublickey"]
|
||||
}
|
||||
|
||||
""" INSTANCE INSERTION """
|
||||
result_new = {}
|
||||
#while not proxmox.retry_on_errorcode(result_new['result']):
|
||||
result_new = proxmox.create_instance("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)), target, "lxc",
|
||||
data)
|
||||
|
||||
""" VERIFY THE RESULT BY PROXMOX STATUS REQUEST CODE """
|
||||
if result_new['result'] == "OK":
|
||||
""" INCREMENT INSTANCE ID IN DATABASE """
|
||||
self.mongo.update_system_instance_id(next_instance_id)
|
||||
""" INCREMENT INSTANCE IP IN DATABASE """
|
||||
self.mongo.update_system_instance_ip(ip)
|
||||
|
||||
""" INSERT THIS NEW SERVER IN DATABASE """
|
||||
data["commandid"] = command_id
|
||||
data["cluster"] = node_informations["cluster"]
|
||||
data["node"] = target
|
||||
data["ip"] = ip
|
||||
|
||||
self.mongo.insert_instance(data)
|
||||
""" BREAK the loop due to valid creation """
|
||||
|
||||
|
||||
returnlistresult.append(result_new)
|
||||
|
||||
""" SEND MESSAGE IN REDIS """
|
||||
self.redis_msg.insert_message(command_id, returnlistresult)
|
||||
|
||||
return
|
||||
|
||||
def delete_instance(self, vmid):
|
||||
|
||||
try:
|
||||
""" Find node/cluster informations from vmid """
|
||||
instance_informations = self.mongo.get_instance(vmid)
|
||||
|
||||
""" Find cluster informations from node """
|
||||
cluster_informations = self.mongo.get_clusters_conf(instance_informations['cluster'])
|
||||
|
||||
proxmox_cluster_url = cluster_informations["url"]
|
||||
proxmox_cluster_port = cluster_informations["port"]
|
||||
proxmox_cluster_user = pdecrypt(cluster_informations["user"],self.generalconf["keys"]["key_pvt"])
|
||||
proxmox_cluster_pwd = pdecrypt(cluster_informations["password"], self.generalconf["keys"]["key_pvt"])
|
||||
|
||||
""" LOAD PROXMOX """
|
||||
proxmox = Proxmox(instance_informations['node'])
|
||||
proxmox.get_ticket("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
proxmox_cluster_user,
|
||||
proxmox_cluster_pwd)
|
||||
|
||||
result = proxmox.delete_instance("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)), instance_informations['node'], "lxc", vmid)
|
||||
|
||||
if result['result'] == "OK":
|
||||
self.mongo.delete_instance(vmid)
|
||||
self.mongo.update_system_free_ip(instance_informations['ip'])
|
||||
|
||||
except BaseException:
|
||||
result = {"value": "{0} {1}".format(vmid, "is not a valid VMID")}
|
||||
|
||||
return result
|
||||
|
||||
def status_instance(self, vmid, action):
|
||||
""" Find node/cluster informations from vmid """
|
||||
try:
|
||||
instance_informations = self.mongo.get_instance(vmid)
|
||||
|
||||
""" Find cluster informations from node """
|
||||
cluster_informations = self.mongo.get_clusters_conf(instance_informations['cluster'])
|
||||
|
||||
proxmox_cluster_url = cluster_informations["url"]
|
||||
proxmox_cluster_port = cluster_informations["port"]
|
||||
proxmox_cluster_user = pdecrypt(cluster_informations["user"],self.generalconf["keys"]["key_pvt"])
|
||||
proxmox_cluster_pwd = pdecrypt(cluster_informations["password"], self.generalconf["keys"]["key_pvt"])
|
||||
|
||||
""" LOAD PROXMOX """
|
||||
proxmox = Proxmox(instance_informations['node'])
|
||||
proxmox.get_ticket("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
proxmox_cluster_user,
|
||||
proxmox_cluster_pwd)
|
||||
|
||||
result = proxmox.status_instance("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
instance_informations['node'],
|
||||
"lxc",
|
||||
vmid, action)
|
||||
|
||||
except IndexError:
|
||||
result = {"value": "{0} {1}".format(vmid, "is not a valid VMID")}
|
||||
|
||||
return result
|
||||
|
||||
def info_instance(self, vmid):
|
||||
""" Find node/cluster informations from vmid """
|
||||
try:
|
||||
instance_informations = self.mongo.get_instance(vmid)
|
||||
|
||||
""" Find cluster informations from node """
|
||||
cluster_informations = self.mongo.get_clusters_conf(instance_informations['cluster'])
|
||||
|
||||
proxmox_cluster_url = cluster_informations["url"]
|
||||
proxmox_cluster_port = cluster_informations["port"]
|
||||
proxmox_cluster_user = pdecrypt(cluster_informations["user"],self.generalconf["keys"]["key_pvt"])
|
||||
proxmox_cluster_pwd = pdecrypt(cluster_informations["password"], self.generalconf["keys"]["key_pvt"])
|
||||
|
||||
""" LOAD PROXMOX """
|
||||
proxmox = Proxmox(instance_informations['node'])
|
||||
proxmox.get_ticket("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
proxmox_cluster_user,
|
||||
proxmox_cluster_pwd)
|
||||
|
||||
result = proxmox.get_config("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
instance_informations['node'],
|
||||
"lxc",
|
||||
vmid)
|
||||
|
||||
except IndexError:
|
||||
result = {"value": "{0} {1}".format(vmid, "is not a valid VMID")}
|
||||
|
||||
return result
|
||||
|
||||
def change_instance(self, vmid, data):
|
||||
""" Find node/cluster informations from vmid """
|
||||
try:
|
||||
instance_informations = self.mongo.get_instance(vmid)
|
||||
|
||||
""" Find cluster informations from node """
|
||||
cluster_informations = self.mongo.get_clusters_conf(instance_informations['cluster'])
|
||||
|
||||
proxmox_cluster_url = cluster_informations["url"]
|
||||
proxmox_cluster_port = cluster_informations["port"]
|
||||
proxmox_cluster_user = pdecrypt(cluster_informations["user"],self.generalconf["keys"]["key_pvt"])
|
||||
proxmox_cluster_pwd = pdecrypt(cluster_informations["password"], self.generalconf["keys"]["key_pvt"])
|
||||
|
||||
|
||||
""" LOAD PROXMOX """
|
||||
proxmox = Proxmox(instance_informations['node'])
|
||||
proxmox.get_ticket("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
proxmox_cluster_user,
|
||||
proxmox_cluster_pwd)
|
||||
|
||||
result = proxmox.resize_instance("{0}:{1}".format(proxmox_cluster_url,
|
||||
int(proxmox_cluster_port)),
|
||||
instance_informations['node'],
|
||||
"lxc",
|
||||
vmid, data)
|
||||
|
||||
if result['result'] == "OK":
|
||||
self.mongo.update_instance(vmid, data)
|
||||
|
||||
except IndexError:
|
||||
result = {"value": "{0} {1}".format(vmid, "is not a valid VMID")}
|
||||
|
||||
return result
|
||||
|
||||
"""
|
||||
#######################
|
||||
# CLUSTERS MANAGEMENT #
|
||||
#######################
|
||||
"""
|
||||
|
||||
def get_cluster(self, cluster=None):
|
||||
""" Find cluster informations from node """
|
||||
cluster_informations = self.mongo.get_clusters_conf(cluster)
|
||||
return cluster_informations
|
||||
|
||||
def insert_cluster(self, data):
|
||||
testdata = valid_cluster_data(data)
|
||||
if not testdata:
|
||||
data["user"] = pcrypt(data["user"], self.generalconf["keys"]["key_pvt"])["data"]
|
||||
data["password"] = pcrypt(data["password"], self.generalconf["keys"]["key_pvt"])["data"]
|
||||
new_cluster = self.mongo.insert_new_cluster(data)
|
||||
else:
|
||||
new_cluster = {"error": "{1} {0}".format(testdata, "Invalid or miss paramettrer")}
|
||||
return new_cluster
|
||||
|
||||
def change_cluster(self, cluster, data):
|
||||
return
|
||||
|
||||
def delete_cluster(self, cluster):
|
||||
return
|
||||
|
||||
|
||||
def valid_cluster_data(data):
|
||||
key_required = ["name", "url", "port", "user", "password", "template", "storage_disk", "weight", "exclude_nodes"]
|
||||
result = []
|
||||
for key in key_required:
|
||||
if key not in data:
|
||||
result.append(key)
|
||||
return result
|
2
code/scripts/main/core/libs/__init__.py
Normal file
2
code/scripts/main/core/libs/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
BIN
code/scripts/main/core/libs/__pycache__/__init__.cpython-35.pyc
Normal file
BIN
code/scripts/main/core/libs/__pycache__/__init__.cpython-35.pyc
Normal file
Binary file not shown.
BIN
code/scripts/main/core/libs/__pycache__/hcrypt.cpython-35.pyc
Normal file
BIN
code/scripts/main/core/libs/__pycache__/hcrypt.cpython-35.pyc
Normal file
Binary file not shown.
11
code/scripts/main/core/libs/hcrypt.py
Normal file
11
code/scripts/main/core/libs/hcrypt.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from core.modules.mod_access import *
|
||||
|
||||
def pcrypt(data, key):
|
||||
CritConf = CryticalData()
|
||||
data = CritConf.data_encryption(data, key)
|
||||
return data
|
||||
|
||||
def pdecrypt(data, key):
|
||||
CritConf = CryticalData()
|
||||
data = CritConf.data_decryption(data, key)
|
||||
return data
|
0
code/scripts/main/core/libs/logs.py
Normal file
0
code/scripts/main/core/libs/logs.py
Normal file
0
code/scripts/main/core/libs/write.py
Normal file
0
code/scripts/main/core/libs/write.py
Normal file
2
code/scripts/main/core/modules/__init__.py
Normal file
2
code/scripts/main/core/modules/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
133
code/scripts/main/core/modules/mod_access.py
Normal file
133
code/scripts/main/core/modules/mod_access.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
"""
|
||||
Author: Tlams
|
||||
Langage: Python
|
||||
Minimum version require: 3.4
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from Crypto.PublicKey import RSA
|
||||
import hashlib
|
||||
import codecs
|
||||
|
||||
def encodepassphrase(passphrase):
|
||||
return hashlib.sha512(passphrase.encode("UTF-8")).hexdigest()
|
||||
|
||||
|
||||
class CryticalData:
|
||||
def __init__(self):
|
||||
self.public_key = None
|
||||
self.private_key = None
|
||||
|
||||
def generate_key(self, key_pvt, key_pub, passphrase, lgt=4096):
|
||||
try:
|
||||
private_key = RSA.generate(lgt)
|
||||
file = open(key_pvt, "wb")
|
||||
file.write(private_key.exportKey('PEM', passphrase, pkcs=1))
|
||||
file.close()
|
||||
|
||||
public_key = private_key.publickey()
|
||||
file = open(key_pub, "wb")
|
||||
file.write(public_key.exportKey())
|
||||
file.close()
|
||||
|
||||
os.chmod(key_pvt, 0o600)
|
||||
os.chmod(key_pub, 0o600)
|
||||
key_generation = {"result": "OK"}
|
||||
|
||||
except BaseException as e:
|
||||
try:
|
||||
print("Clean...")
|
||||
os.remove(key_pvt)
|
||||
os.remove(key_pub)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
key_generation = {
|
||||
"result": "ERROR",
|
||||
"type": "PYTHON",
|
||||
"Error": "Key generation fail: {0}".format(e)
|
||||
}
|
||||
|
||||
return key_generation
|
||||
|
||||
def read_public_key(self, key_pub):
|
||||
try:
|
||||
file_key_pub = open(key_pub, "rb")
|
||||
self.public_key = RSA.importKey(file_key_pub.read())
|
||||
file_key_pub.close()
|
||||
result_public_key = {
|
||||
"result": "OK",
|
||||
"data": self.public_key
|
||||
}
|
||||
except BaseException as e:
|
||||
result_public_key = {
|
||||
"result": "ERROR",
|
||||
"type": "PYTHON",
|
||||
"error": "Your public key seem to invalid: {0}".format(e)
|
||||
}
|
||||
return result_public_key
|
||||
|
||||
def read_private_key(self, key_pvt, passphrase):
|
||||
try:
|
||||
file_key_pvt = open(key_pvt, "rb")
|
||||
self.private_key = RSA.importKey(file_key_pvt.read(), passphrase)
|
||||
file_key_pvt.close()
|
||||
result_private_key = {
|
||||
"result": "OK",
|
||||
"data": self.private_key
|
||||
|
||||
}
|
||||
except BaseException as e:
|
||||
result_private_key = {
|
||||
"result": "ERROR",
|
||||
"type": "PYTHON",
|
||||
"error": "Your private key seem to invalid: {0}".format(e)
|
||||
}
|
||||
return result_private_key
|
||||
|
||||
def data_encryption(self, data, key=None):
|
||||
|
||||
encfrypt = key.encrypt(data.encode("utf-8"), 32)
|
||||
convert_str = str(encfrypt[0])[2:-1]
|
||||
|
||||
|
||||
try:
|
||||
if key:
|
||||
result_encrypt = {
|
||||
"result": "OK",
|
||||
"data": convert_str
|
||||
}
|
||||
else:
|
||||
result_encrypt = {
|
||||
"result": "OK",
|
||||
"data": codecs.encode(self.public_key.encrypt(mutable_bytes, 32)[0], 'base64')
|
||||
}
|
||||
except BaseException as e:
|
||||
result_encrypt = {
|
||||
"result": "ERROR",
|
||||
"type": "PYTHON",
|
||||
"error": "Data encryption failed: {0}".format(e)
|
||||
}
|
||||
return result_encrypt
|
||||
|
||||
def data_decryption(self, data, key=None):
|
||||
try:
|
||||
if key:
|
||||
result_decryption = {
|
||||
"result": "OK",
|
||||
"data": key.decrypt(data)
|
||||
}
|
||||
else:
|
||||
result_decryption = {
|
||||
"result": "OK",
|
||||
"data": self.private_key.decrypt(data)
|
||||
}
|
||||
except BaseException as e:
|
||||
result_decryption = {
|
||||
"result": "ERROR",
|
||||
"type": "PYTHON",
|
||||
"error": "Data decryption failed: {0}".format(e)
|
||||
}
|
||||
return result_decryption
|
||||
|
157
code/scripts/main/core/modules/mod_analyst.py
Normal file
157
code/scripts/main/core/modules/mod_analyst.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
"""
|
||||
Author: Tlams
|
||||
Langage: Python
|
||||
Minimum version require: 3.4
|
||||
|
||||
Module function:
|
||||
The goal of this module is to analyse the differents clusters and node
|
||||
to allocate news instances.
|
||||
"""
|
||||
|
||||
from core.modules.mod_proxmox import *
|
||||
from core.modules.mod_database import *
|
||||
from core.libs.hcrypt import *
|
||||
import time
|
||||
import operator
|
||||
import random
|
||||
import codecs
|
||||
|
||||
def add_token(tokens_in_slots, slot_distributions):
|
||||
num_tokens = sum(tokens_in_slots)
|
||||
if not num_tokens:
|
||||
#first token can go anywhere
|
||||
tokens_in_slots[random.randint(0, 2)] += 1
|
||||
return
|
||||
expected_tokens = [num_tokens*distr for distr in slot_distributions]
|
||||
errors = [expected - actual
|
||||
for expected, actual in zip(expected_tokens, tokens_in_slots)]
|
||||
most_error = max(enumerate(errors), key=lambda i_e: i_e[1])
|
||||
tokens_in_slots[most_error[0]] += 1
|
||||
|
||||
|
||||
def distribution(n, tokens_in_slots, slot_distributions):
|
||||
for i in range(n):
|
||||
add_token(tokens_in_slots, slot_distributions)
|
||||
return tokens_in_slots
|
||||
|
||||
|
||||
class Analyse:
|
||||
def __init__(self, clusters_conf, generalconf):
|
||||
"""
|
||||
:param clusters_conf: Proxmox configurations
|
||||
:param generalconf : General configuration
|
||||
"""
|
||||
self.generalconf = generalconf
|
||||
self.clusters_conf = clusters_conf
|
||||
|
||||
""" LOAD MONGODB """
|
||||
self.mongo = MongoDB(generalconf["mongodb"]["ip"])
|
||||
self.mongo.client = self.mongo.connect()
|
||||
self.mongo.db = self.mongo.client.db
|
||||
|
||||
def run(self):
|
||||
insert_time = time.time()
|
||||
|
||||
self.mongo.insert_datekey(insert_time, 'running')
|
||||
|
||||
for cluster in self.clusters_conf:
|
||||
|
||||
|
||||
datamongo=cluster["user"].replace("\\\\x", "x")
|
||||
convert_to_byte=datamongo.encode("utf-8")
|
||||
print(convert_to_byte)
|
||||
print(pdecrypt(datamongo.encode("utf-8"), self.generalconf["keys"]["key_pvt"]))
|
||||
|
||||
|
||||
""" AUTH """
|
||||
proxmox = Proxmox("Analyse")
|
||||
proxmox.get_ticket("{0}:{1}".format(cluster["url"],
|
||||
int(cluster["port"])),
|
||||
pdecrypt(cluster["user"], self.generalconf["keys"]["key_pvt"]),
|
||||
pdecrypt(cluster["password"], self.generalconf["keys"]["key_pvt"]))
|
||||
|
||||
""" Get excluded nodes """
|
||||
exclude_nodes = cluster["exclude_nodes"]
|
||||
|
||||
""" UPDATE NODES LIST """
|
||||
nodes_list = proxmox.get_nodes("{0}:{1}".format(cluster["url"], int(cluster["port"])))["value"]
|
||||
|
||||
for value_nodes_list in nodes_list["data"]:
|
||||
if value_nodes_list["node"] not in exclude_nodes:
|
||||
""" TOTAL COUNT CPU and RAM allocate"""
|
||||
list_instances = proxmox.get_instance("{0}:{1}".format(cluster["url"], int(cluster["port"])),
|
||||
value_nodes_list["node"], "lxc")["value"]
|
||||
|
||||
totalcpu = 0
|
||||
totalram = 0
|
||||
for key_list_instances, value_list_instances in list_instances.items():
|
||||
for instances in value_list_instances:
|
||||
totalcpu = totalcpu + instances["cpus"]
|
||||
totalram = totalram + instances["maxmem"]
|
||||
|
||||
value_nodes_list["totalalloccpu"] = totalcpu
|
||||
value_nodes_list["totalallocram"] = totalram
|
||||
value_nodes_list["vmcount"] = len(list_instances.items())
|
||||
|
||||
percent_cpu_alloc = (totalcpu / value_nodes_list["maxcpu"]) * 100
|
||||
percent_ram_alloc = (totalram / value_nodes_list["mem"]) * 100
|
||||
|
||||
"""
|
||||
weight of node =
|
||||
(((Percent Alloc CPU x coef) + ( Percent Alloc RAM x coef)) / Total coef ) * Cluster weight
|
||||
"""
|
||||
weight = (((percent_cpu_alloc * 2) + (percent_ram_alloc * 4)) / 6) * int(cluster["weight"])
|
||||
|
||||
value_nodes_list["weight"] = int(weight)
|
||||
value_nodes_list["date"] = int(insert_time)
|
||||
value_nodes_list["cluster"] = cluster["name"]
|
||||
|
||||
self.mongo.insert_node(value_nodes_list)
|
||||
|
||||
self.mongo.update_datekey(int(insert_time), "OK")
|
||||
|
||||
return
|
||||
|
||||
def set_attribution(self, count):
|
||||
""" RETURN cluster and node"""
|
||||
# Search the last valid key
|
||||
lastkeyvalid = self.mongo.get_last_datekey()
|
||||
|
||||
# Get nodes weight
|
||||
nodes_availables = self.mongo.get_nodes_informations(int(lastkeyvalid["value"]))
|
||||
|
||||
if len(nodes_availables) > 1:
|
||||
# Select node name with weight
|
||||
nodes_values = {}
|
||||
for nodes in nodes_availables:
|
||||
nodes_values[nodes["node"]] = nodes["weight"]
|
||||
|
||||
# Sort node by weight
|
||||
sorted_nodes = sorted(nodes_values.items(), key=operator.itemgetter(1))
|
||||
|
||||
slot_distributions = []
|
||||
sorted_nodes_name = []
|
||||
|
||||
# Divise dict sorted_node to two list [name1, name2] [value1, value2]
|
||||
for nodes_sort in sorted_nodes:
|
||||
slot_distributions.append(nodes_sort[1])
|
||||
sorted_nodes_name.append((nodes_sort[0]))
|
||||
|
||||
# Calcul weight on a range of value 0-1 and convert in percent
|
||||
slot_distributions_p = []
|
||||
for s in slot_distributions:
|
||||
slot_distributions_p.append(100-(s/sum(slot_distributions)*100)/100)
|
||||
|
||||
# Generate default list
|
||||
tokens_in_slots = [0] * len(nodes_availables)
|
||||
|
||||
# use distribution algorithm to allocate
|
||||
distrib_final = distribution(int(count), tokens_in_slots, slot_distributions_p)
|
||||
|
||||
# Regenerate final dict !!
|
||||
final = {k: int(v) for k, v in zip(sorted_nodes_name, distrib_final)}
|
||||
|
||||
else:
|
||||
final = {nodes_availables[0]['node']: count}
|
||||
|
||||
return final
|
179
code/scripts/main/core/modules/mod_database.py
Normal file
179
code/scripts/main/core/modules/mod_database.py
Normal file
|
@ -0,0 +1,179 @@
|
|||
from pymongo import MongoClient
|
||||
from bson.json_util import dumps
|
||||
import json
|
||||
import redis
|
||||
import time
|
||||
|
||||
class Redis_instance_queue:
|
||||
def __init__(self, server="127.0.0.1", port=6379, db=3, password=None):
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.r = None
|
||||
self.db = db
|
||||
self.password = password
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
conn = self.r = redis.Redis(
|
||||
host=self.server, port=self.port, db=self.db, password=self.password,
|
||||
charset="utf-8", decode_responses=True)
|
||||
self.r.client_list()
|
||||
except BaseException as err:
|
||||
print("Redis connexion error on {0}:{1} ({2})".format(self.server, self.port, err))
|
||||
conn = False
|
||||
return conn
|
||||
|
||||
def insert_instance_queue(self, logtext, expir=3000):
|
||||
self.r.set(time.time(), logtext, expir)
|
||||
|
||||
|
||||
class Redis_logger:
|
||||
def __init__(self, server="127.0.0.1", port=6379, db=2, password=None):
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.r = None
|
||||
self.db = db
|
||||
self.password = password
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
conn = self.r = redis.Redis(
|
||||
host=self.server, port=self.port, db=self.db, password=self.password,
|
||||
charset="utf-8", decode_responses=True)
|
||||
self.r.client_list()
|
||||
except BaseException as err:
|
||||
print("Redis connexion error on {0}:{1} ({2})".format(self.server, self.port, err))
|
||||
conn = False
|
||||
return conn
|
||||
|
||||
def insert_logs(self, logtext, expir=86400*4):
|
||||
self.r.set(time.time(), logtext, expir)
|
||||
|
||||
|
||||
class Redis_messages:
|
||||
def __init__(self, server="127.0.0.1", port=6379, db=1, password=None):
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.r = None
|
||||
self.db = db
|
||||
self.password = password
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
conn = self.r = redis.Redis(
|
||||
host=self.server, port=self.port, db=self.db, password=self.password,
|
||||
charset="utf-8", decode_responses=True)
|
||||
self.r.client_list()
|
||||
except BaseException as err:
|
||||
print("Redis connexion error on {0}:{1} ({2})".format(self.server, self.port, err))
|
||||
conn = False
|
||||
return conn
|
||||
|
||||
def insert_message(self, key, value, expir=86400):
|
||||
self.r.set(key, value, expir)
|
||||
|
||||
def get_message(self, key):
|
||||
return self.r.get(key)
|
||||
|
||||
|
||||
class MongoDB:
|
||||
def __init__(self, server="127.0.0.1", port=27017):
|
||||
"""
|
||||
:param server:
|
||||
:param port:
|
||||
"""
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.collection_system = "system"
|
||||
self.collection_instance = "instances"
|
||||
self.collection_nodes = "nodes"
|
||||
self.collection_clusters = "clusters"
|
||||
self.collection_datekey = "dates"
|
||||
self.port = port
|
||||
self.db = None
|
||||
self.client = None
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
conn = MongoClient(self.server + ':' + str(self.port))
|
||||
conn.server_info()
|
||||
except BaseException as err:
|
||||
print("MongoDB connexion error on {0}:{1} ({2})".format(self.server, self.port, err))
|
||||
conn = False
|
||||
return conn
|
||||
|
||||
def authenticate(self, user=None, password=None, mechanism='SCRAM-SHA-1'):
|
||||
try:
|
||||
self.client.db.authenticate(user, password, mechanism)
|
||||
except (TypeError, ValueError) as e:
|
||||
raise("MongoDB authentification error on {0}:{1} ({2})".format(self.server, self.port, e))
|
||||
|
||||
""" CLUSTER """
|
||||
def get_clusters_conf(self, cluster=None):
|
||||
if cluster:
|
||||
return json.loads(dumps(self.db[self.collection_clusters].find_one({"name": cluster})))
|
||||
else:
|
||||
return json.loads(dumps(self.db[self.collection_clusters].find({})))
|
||||
|
||||
def insert_new_cluster(self, data):
|
||||
return self.db[self.collection_clusters].insert(data)
|
||||
|
||||
def update_cluster(self, cluster, data):
|
||||
return self.db[self.collection_clusters].update({"vmid": str(cluster)}, {'$set': data}, upsert=False)
|
||||
|
||||
def delete_cluster(self, cluster):
|
||||
return self.db[self.collection_clusters].remove({"cluster": str(cluster)})
|
||||
|
||||
|
||||
""" SYSTEM """
|
||||
def get_system_info(self):
|
||||
return self.db[self.collection_system].find_one({"_id": "0"})
|
||||
|
||||
def update_system_instance_id(self, value):
|
||||
self.db[self.collection_system].update({'_id': "0"}, {'$set': {'instances_number': value}})
|
||||
|
||||
def update_system_instance_ip(self, value):
|
||||
self.db[self.collection_system].update({'_id': "0"}, {'$set': {'IP_current': value}})
|
||||
|
||||
def update_system_free_ip(self, value):
|
||||
self.db[self.collection_system].update({'_id': "0"}, {'$push': {'IP_free': value}}, upsert=False)
|
||||
|
||||
def update_system_delete_ip(self, value):
|
||||
self.db[self.collection_system].update({'_id': "0"}, {'$pull': {'IP_free': value}}, upsert=False)
|
||||
|
||||
""" NODES MANAGEMENT"""
|
||||
def insert_node(self, data):
|
||||
return self.db[self.collection_nodes].insert(data)
|
||||
|
||||
def get_nodes_informations(self, time, node=None):
|
||||
if node:
|
||||
return json.loads(dumps(self.db[self.collection_nodes].find_one({'$and': [{'node': node, 'date': time}]})))
|
||||
else:
|
||||
return json.loads(dumps(self.db[self.collection_nodes].find({'date': time})))
|
||||
|
||||
""" KEY DATE MANAGEMENT"""
|
||||
def insert_datekey(self, date, status):
|
||||
return self.db[self.collection_datekey].insert({'date': int(date), 'status': status})
|
||||
|
||||
def update_datekey(self, date, status):
|
||||
self.db[self.collection_datekey].update({'date': date}, {'$set': {'status': status}}, upsert=False)
|
||||
|
||||
def get_last_datekey(self):
|
||||
last_id = self.db[self.collection_datekey].find({'status': 'OK'}).sort("date", -1).limit(1)
|
||||
return {"value": int(json.loads(dumps(last_id))[0]['date'])}
|
||||
|
||||
""" INSTANCE MANAGEMENT"""
|
||||
def insert_instance(self, data):
|
||||
return self.db[self.collection_instance].insert(data)
|
||||
|
||||
def update_instance(self, vmid, data):
|
||||
self.db[self.collection_instance].update({"vmid": int(vmid)}, {'$set': data}, upsert=False)
|
||||
|
||||
def delete_instance(self, vmid):
|
||||
self.db[self.collection_instance].remove({"vmid": int(vmid)})
|
||||
|
||||
def get_instance(self, vmid):
|
||||
try:
|
||||
return json.loads(dumps(self.db[self.collection_instance].find_one({"vmid": int(vmid)})))
|
||||
except BaseException as serr:
|
||||
raise ("MongoDB error on {0}:{1} ({2})".format(self.server, self.port, serr))
|
0
code/scripts/main/core/modules/mod_instance.py
Normal file
0
code/scripts/main/core/modules/mod_instance.py
Normal file
0
code/scripts/main/core/modules/mod_package.py
Normal file
0
code/scripts/main/core/modules/mod_package.py
Normal file
415
code/scripts/main/core/modules/mod_proxmox.py
Normal file
415
code/scripts/main/core/modules/mod_proxmox.py
Normal file
|
@ -0,0 +1,415 @@
|
|||
import requests
|
||||
import time
|
||||
"""
|
||||
Proxmox management API WRAPPER
|
||||
"""
|
||||
|
||||
|
||||
class NetworkError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class Proxmox:
|
||||
def __init__(self, name):
|
||||
"""
|
||||
:param name: Cluster Proxmox
|
||||
"""
|
||||
self.name = name
|
||||
self.socket = None
|
||||
self.ticket = None
|
||||
self.PVEAuthCookie = None
|
||||
self.csrf = None
|
||||
self.nodes = None
|
||||
self.status = None
|
||||
self.storage = None
|
||||
self.disks = None
|
||||
self.qemu = None
|
||||
self.config = None
|
||||
|
||||
def get_ticket(self, url, user, password):
|
||||
"""
|
||||
Get a new ticket from Proxmox api
|
||||
:param url: Generic ticket url
|
||||
:param user: Proxmox user API
|
||||
:param password: Proxmox password user API
|
||||
"""
|
||||
request = "https://{0}/api2/json/access/ticket".format(url)
|
||||
try:
|
||||
self.socket = requests.session()
|
||||
params = {'username': user, 'password': password}
|
||||
self.ticket = self.socket.post(request, params=params, verify=False, timeout=5)
|
||||
|
||||
if self.ticket.status_code == 200:
|
||||
result = {"result": "OK",
|
||||
"value": self.ticket.json()
|
||||
}
|
||||
self.PVEAuthCookie = {'PVEAuthCookie': self.ticket.json()['data']['ticket']}
|
||||
self.csrf = {'CSRFPreventionToken': self.ticket.json()['data']['CSRFPreventionToken']}
|
||||
else:
|
||||
result = {"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error nodes informations. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(self.ticket.status_code, self.ticket.text)
|
||||
}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot get ticket session {0} ({1})".format(url, e)}
|
||||
|
||||
return result
|
||||
|
||||
def get_nodes(self, url):
|
||||
"""
|
||||
Get Nodes from cluster
|
||||
:param url: Generic node url (node = physical hypervisor)
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes".format(url)
|
||||
try:
|
||||
nodes = self.nodes = self.socket.get(request,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False, timeout=5)
|
||||
|
||||
if nodes.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": nodes.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error nodes informations. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(nodes.status_code, nodes.text)
|
||||
}
|
||||
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot get node information for {0} ({1})".format(url, e)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def get_status(self, url, nodename):
|
||||
"""
|
||||
Get node informations
|
||||
:param url: Generic node url
|
||||
:param nodename: Node name (not int id)
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/status".format(url, nodename)
|
||||
try:
|
||||
self.status = self.socket.get(request, cookies=self.PVEAuthCookie, verify=False, timeout=5).json()
|
||||
result = {"result": "OK"}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR", "target": "[{3}]",
|
||||
"customerror": "Cannot get node information for {0} ({1})".format(url, e, nodename)}
|
||||
|
||||
return result
|
||||
|
||||
def get_storages(self, url, nodename):
|
||||
"""
|
||||
Get Storage from nodes
|
||||
:param url: Generic storage url
|
||||
:param nodename: Node name (no int id)
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/storage".format(url, nodename)
|
||||
try:
|
||||
self.storage = self.socket.get(request, cookies=self.PVEAuthCookie, verify=False, timeout=5).json()
|
||||
result = {"result": "OK"}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR", "target": "[{3}]",
|
||||
"customerror": "Cannot get storage information for {0} ({1})".format(url, e, nodename)}
|
||||
|
||||
return result
|
||||
|
||||
def get_disks(self, url, nodename, sto_id):
|
||||
"""
|
||||
Get VMs disk from storages
|
||||
:param url: Generic content url
|
||||
:param nodename: Node name (no int id)
|
||||
:param sto_id: Storage name (no int id)
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/storage/{2}/content".format(url, nodename, sto_id)
|
||||
try:
|
||||
self.disks = self.socket.get(request, cookies=self.PVEAuthCookie, verify=False, timeout=5).json()
|
||||
result = {"result": "OK"}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR", "target": "[{3}]",
|
||||
"customerror": "Cannot get disks information for {0} ({1})".format(url, e, nodename)}
|
||||
|
||||
return result
|
||||
|
||||
def get_instance(self, url, nodename, category):
|
||||
"""
|
||||
Get basic VMs informations from nodes
|
||||
:param url: Generic qemu url
|
||||
:param nodename: Node name (not int id)
|
||||
:param category: lxc or qemu
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}".format(url, nodename, category)
|
||||
try:
|
||||
instances = self.socket.get(request,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False, timeout=5)
|
||||
|
||||
if instances.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": instances.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error nodes informations. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(instances.status_code, instances.text)
|
||||
}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot get VM information for {0} {1} ({2})".format(url, nodename, e)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def get_config(self, url, nodename, category, instanceid):
|
||||
"""
|
||||
Get avanced VM information from nodes
|
||||
:param url: Generic qemu config url
|
||||
:param category: lxc or qemu
|
||||
:param nodename: Node name (not int id)
|
||||
:param instanceid: VM id (int id)
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}/{3}/config".format(url, nodename, category, instanceid)
|
||||
try:
|
||||
config = self.socket.get(request, cookies=self.PVEAuthCookie, verify=False, timeout=5)
|
||||
if config.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": config.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error nodes informations. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(config.status_code, config.text)
|
||||
}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(url),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot get VM information for {0} {1} ({2})".format(url, nodename, e)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def create_instance(self, url, nodename, category, data):
|
||||
"""
|
||||
:param url:
|
||||
:param nodename:
|
||||
:param category:
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}".format(url, nodename, category)
|
||||
try:
|
||||
createvm = self.socket.post(request,
|
||||
data=data,
|
||||
headers=self.csrf,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False,
|
||||
timeout=5)
|
||||
|
||||
if createvm.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": createvm.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error creating Container. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(createvm.status_code, createvm.text)
|
||||
}
|
||||
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot create this instance on {0} : ({1})".format(url, e)}
|
||||
|
||||
return result
|
||||
|
||||
def delete_instance(self, url, nodename, category, vmid):
|
||||
"""
|
||||
:param url:
|
||||
:param nodename:
|
||||
:param category:
|
||||
:param vmid:
|
||||
:return:
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}/{3}".format(url, nodename, category, vmid)
|
||||
try:
|
||||
deletevm = self.socket.delete(request,
|
||||
headers=self.csrf,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False,
|
||||
timeout=5
|
||||
)
|
||||
|
||||
if deletevm.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": deletevm.json()
|
||||
}
|
||||
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error delete Container. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(deletevm.status_code, deletevm.text)
|
||||
}
|
||||
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot delete Container ({2}) on {0} : ({1})".format(url, e, vmid)}
|
||||
|
||||
return result
|
||||
|
||||
def status_instance(self, url, nodename, category, vmid, action):
|
||||
"""
|
||||
:param url:
|
||||
:param nodename:
|
||||
:param category:
|
||||
:param vmid:
|
||||
:param action:
|
||||
:return:
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}/{3}/status/{4}".format(url, nodename, category, vmid, action)
|
||||
try:
|
||||
if action == "current":
|
||||
statusm = self.socket.get(request,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False,
|
||||
timeout=5)
|
||||
else:
|
||||
statusm = self.socket.post(request,
|
||||
headers=self.csrf,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False,
|
||||
timeout=5)
|
||||
|
||||
if statusm.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": statusm.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error action Container. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(statusm.status_code, statusm.text)
|
||||
}
|
||||
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot do this action this instance ({2}) on {0} : ({1})".format(url, e, vmid)}
|
||||
|
||||
return result
|
||||
|
||||
def resize_instance(self, url, nodename, category, instanceid, data):
|
||||
"""
|
||||
:param url:
|
||||
:param nodename:
|
||||
:param category:
|
||||
:param instanceid:
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}/{3}/config".format(url, nodename, category, instanceid)
|
||||
try:
|
||||
resizevm = self.socket.put(request,
|
||||
data=data,
|
||||
headers=self.csrf,
|
||||
cookies=self.PVEAuthCookie,
|
||||
verify=False,
|
||||
timeout=5)
|
||||
|
||||
if resizevm.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": resizevm.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error resizing container. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(resizevm.status_code, resizevm.text)
|
||||
}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot resize this instance {2} on {0} : ({1})".format(url, e, instanceid)
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def stats_instance(self, url, nodename, category, instanceid):
|
||||
"""
|
||||
:param url:
|
||||
:param nodename:
|
||||
:param category:
|
||||
:param instanceid:
|
||||
:return:
|
||||
"""
|
||||
request = "https://{0}/api2/json/nodes/{1}/{2}/{3}/rrddata".format(url, nodename, category, instanceid)
|
||||
try:
|
||||
statsvm = self.socket.get(request, cookies=self.PVEAuthCookie, verify=False, timeout=5)
|
||||
|
||||
if statsvm.status_code == 200:
|
||||
result = {
|
||||
"result": "OK",
|
||||
"value": statsvm.json()
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PROXMOX - STATUS CODE",
|
||||
"customerror": "Error to find statistic for instance {2}. Bad HTTP Status code : "
|
||||
"{0} -- {1}".format(statsvm.status_code, statsvm.text, instanceid)
|
||||
}
|
||||
except (TypeError, ValueError, requests.exceptions.RequestException) as e:
|
||||
result = {
|
||||
"result": "ERROR",
|
||||
"target": "{0}".format(nodename),
|
||||
"type": "PYTHON",
|
||||
"customerror": "Cannot find statistic for this instance {2} on {0} : ({1})".format(url, e, instanceid)
|
||||
}
|
||||
|
||||
return result
|
20
code/scripts/main/core/modules/mod_queue.py
Normal file
20
code/scripts/main/core/modules/mod_queue.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
"""
|
||||
Queue Management
|
||||
"""
|
||||
|
||||
class Queue():
|
||||
def __init__(self):
|
||||
self.name = "command"
|
||||
|
||||
def insert_command_queue(self):
|
||||
|
||||
return
|
||||
|
||||
def delete_command(self):
|
||||
return
|
||||
|
||||
def serve_command(self):
|
||||
return
|
||||
|
||||
def queue_stats(self):
|
||||
return
|
0
code/scripts/main/core/modules/mod_ssl.py
Normal file
0
code/scripts/main/core/modules/mod_ssl.py
Normal file
0
code/scripts/main/core/modules/mod_varnish.py
Normal file
0
code/scripts/main/core/modules/mod_varnish.py
Normal file
34
code/scripts/main/core/modules/mod_vhost.py
Normal file
34
code/scripts/main/core/modules/mod_vhost.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import requests
|
||||
|
||||
"""
|
||||
VHOST Management
|
||||
"""
|
||||
|
||||
class Nginx:
|
||||
def __init__(self, clientid):
|
||||
"""
|
||||
:param clientid:
|
||||
"""
|
||||
|
||||
class Apache:
|
||||
def __init__(self, siteid):
|
||||
"""
|
||||
:param name: Cluster Proxmox
|
||||
"""
|
||||
self.siteid = siteid
|
||||
|
||||
def get_vhost(self):
|
||||
"""
|
||||
List all vhost available
|
||||
:return:
|
||||
"""
|
||||
return
|
||||
|
||||
def create_vhost(self):
|
||||
return
|
||||
|
||||
def delete_vhost(self):
|
||||
return
|
||||
|
||||
def update_vhost(self):
|
||||
return
|
36
code/scripts/main/private/conf/config
Normal file
36
code/scripts/main/private/conf/config
Normal file
|
@ -0,0 +1,36 @@
|
|||
[system]
|
||||
; System configurations
|
||||
user: hosting
|
||||
|
||||
; If not exist on start, the key is auto-generate.
|
||||
key_pvt: private/keys/Ragnarok.pvt.key
|
||||
key_pub: private/keys/Ragnarok.pub.key
|
||||
|
||||
[web]
|
||||
user: www-data
|
||||
|
||||
[api]:
|
||||
user: hosting_api
|
||||
|
||||
[databases]
|
||||
; Databases configurations
|
||||
; NOSQL databases, should use a password
|
||||
mongodb_user:
|
||||
mongodb_password:
|
||||
mongodb_ip: 192.168.66.1
|
||||
mongodb_port: 27017
|
||||
|
||||
redis_user:
|
||||
redis_password:
|
||||
redis_ip: 192.168.66.1
|
||||
redis_port: 6379
|
||||
|
||||
[options]
|
||||
; Maximum deploy instance in same time
|
||||
; A hight value my do overcharge on your physicals servers
|
||||
concurrencydeploy: 2
|
||||
|
||||
; Delay between two deploy round
|
||||
; If your infrastructure isn't very large, you should'nt reduce this delay.
|
||||
; A low delay my do overcharge on your physicals servers
|
||||
delayrounddeploy: 15
|
14
code/scripts/main/private/keys/Ragnarok.pub.key
Normal file
14
code/scripts/main/private/keys/Ragnarok.pub.key
Normal file
|
@ -0,0 +1,14 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0BzZj0KTIqPsAnxO0P89
|
||||
3Q8u13jSchAPcT0B7EgJL6RCK5qFRvo4JhGvaG0R8L1YK6T5jS2bzoZR6TDIdze/
|
||||
/a2XJ/0B2u9CvsP/goUMdIqnhkC98K+UxiFY2Rqs68TAJFbWVxAjDLjyYEnZ+faU
|
||||
FWo5x9Nq9Py+VN66N+zRAfWLoUDouEwVQm6pQf5ksJ2qBxyQUxD2j+/0h3yRz+tY
|
||||
UKy7F8cMXup9VYpiebC4O0XwAtE+QXwCzC15C1VaVQs/8rw4qYy6gzdwbaN0Dqim
|
||||
wG/3+nO9R08stCBimEMynKbcOjsdktebTdbgWo+uMI+DauBgpsxqgTciI1yKWmzk
|
||||
uKe0D+fZzfIAGTcSQpxwefqfOKBk2Uy6jhFz6kBa4pDWPNqvfmD3v2TzCkFNqbEA
|
||||
ZGfQuBEZR4iEQoef2D6pA5KjNpdDFdWXC1HvmO9LsS71TlJig1u1/boWWyOTlIm4
|
||||
1mGZumco35EhsyTdFFgf779isgley84Z1jLbmILf8z41l8icZt3Sz3ej4QeH2vdm
|
||||
xpIGcw5RWCh2+ociRvqTw2JBrGU9GLXQibYGeI8xIDds8hJ8R2U38/R4Sru7a5NX
|
||||
JDxPZXyfLZbTtCUihOtqWWke33BAGzHMn7+bPRJe27f/fl6gYiBzxaNhB4Ta3m4G
|
||||
aNVCH4vCl37SGpASd2NYpWkCAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
54
code/scripts/main/private/keys/Ragnarok.pvt.key
Normal file
54
code/scripts/main/private/keys/Ragnarok.pvt.key
Normal file
|
@ -0,0 +1,54 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,B9C57D57F4BBC73D
|
||||
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
115
code/scripts/main/startup.py
Normal file
115
code/scripts/main/startup.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Author: Tlams
|
||||
Langage: Python
|
||||
Minimum version require: 3.4
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from api.v1.api import *
|
||||
from core.modules.mod_access import *
|
||||
import configparser
|
||||
import getpass
|
||||
import os
|
||||
import stat
|
||||
import urllib3
|
||||
global passhash
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
if __name__ == "__main__":
|
||||
""" Read conf """
|
||||
localconf = configparser.ConfigParser()
|
||||
localconf.read('private/conf/config')
|
||||
|
||||
CritConf = CryticalData()
|
||||
""" Step One: test private key or create it """
|
||||
key_pvt = Path(localconf['system']['key_pvt'])
|
||||
|
||||
if not key_pvt.is_file():
|
||||
print("No key found, auto-generation started ...")
|
||||
passhash = encodepassphrase(getpass.getpass("Need a passphrase to start the generation:"))
|
||||
|
||||
print("This action can take some minutes, please wait.")
|
||||
gen = CritConf.generate_key(localconf['system']['key_pvt'], localconf['system']['key_pub'], passhash)
|
||||
if gen['result'] == "OK":
|
||||
print("Your new key has been generate ! "
|
||||
"\n - Private Key: {0} "
|
||||
"\n - Public Key: {1}"
|
||||
.format(localconf['system']['key_pvt'], localconf['system']['key_pvt']))
|
||||
print("Passphrase HASH: {0}".format(passhash))
|
||||
print("You must save your passphrase hash in a security place !")
|
||||
else:
|
||||
print(gen['Error'])
|
||||
exit(1)
|
||||
|
||||
""" Test valid right for your private Key """
|
||||
if oct(stat.S_IMODE(os.stat(localconf['system']['key_pvt']).st_mode)) != oct(0o600):
|
||||
print("Your private key has not the good right({0})..."
|
||||
"This problem can be very critical for your security.".
|
||||
format(oct(stat.S_IMODE(os.stat(localconf['system']['key_pvt']).st_mode))))
|
||||
os.chmod(localconf['system']['key_pvt'], 0o600)
|
||||
print("Auto correction... done !")
|
||||
|
||||
""" Step two"""
|
||||
if 'passhash' not in vars():
|
||||
passhash = encodepassphrase(getpass.getpass("This system need a passphrase to start:"))
|
||||
key_pvt = CritConf.read_private_key(localconf['system']['key_pvt'], passhash)
|
||||
if key_pvt['result'] != "OK":
|
||||
print("{0}: {1}"
|
||||
"\n Please verify your passphrase".format(key_pvt['type'], key_pvt['error']))
|
||||
exit(1)
|
||||
|
||||
key_pub = CritConf.read_public_key(localconf['system']['key_pub'])
|
||||
"""
|
||||
crypttest=CritConf.data_encryption("ploopp")
|
||||
print(type(crypttest['data']))
|
||||
print(CritConf.data_decryption(crypttest['data']))
|
||||
exit(0)
|
||||
"""
|
||||
# URL MAPPING
|
||||
urls = \
|
||||
(
|
||||
# MAPPING INSTANCES
|
||||
'/api/v1/instance', 'Instance',
|
||||
'/api/v1/instance/new', 'Instance',
|
||||
'/api/v1/instance/([0-9]+)', 'Instance',
|
||||
'/api/v1/instance/([0-9]+)/status/([a-z]+)', 'Instance',
|
||||
|
||||
'/api/v1/instance/([0-9]+)/package', 'package',
|
||||
'/api/v1/instance/([0-9]+)/vhost(?:/([0-9]+))', 'vhost',
|
||||
'/api/v1/instance/([0-9]+)/database(?:/([0-9]+))', 'database',
|
||||
|
||||
# MAPPIN NODES
|
||||
'/api/v1/node(?:/([0-9]+))', 'node',
|
||||
|
||||
# MAPPING SERVICES
|
||||
'/api/v1/service/([a-z]+)/instance/([0-9]+)/vhost(?:/([0-9]+))', 'service',
|
||||
|
||||
# AUTH
|
||||
'/api/v1/auth', 'Auth',
|
||||
|
||||
# MANAGEMENT
|
||||
'/api/v1/administration/cluster', 'Cluster',
|
||||
'/api/v1/administration/cluster/new', 'Cluster',
|
||||
)
|
||||
|
||||
generalconf = {
|
||||
"keys": {"key_pvt": key_pvt["data"], "key_pub": key_pub["data"]},
|
||||
"mongodb": {"ip": localconf['databases']['mongodb_ip'], 'port': localconf['databases']['mongodb_port']},
|
||||
"redis": {"ip": localconf['databases']['redis_ip'], 'port': localconf['databases']['redis_port']},
|
||||
"deploy": {'concurrencydeploy': localconf['options']['concurrencydeploy'], 'delayrounddeploy': localconf['options']['delayrounddeploy']}
|
||||
}
|
||||
|
||||
""" First redis connection """
|
||||
Lredis = Redis_messages(generalconf["redis"]["ip"])
|
||||
Lredis.connect()
|
||||
|
||||
""" Init Core thread """
|
||||
core = Core(generalconf, Lredis)
|
||||
|
||||
""" Init API thread """
|
||||
api_th = ThreadAPI(1, "ThreadAPI", urls, core, generalconf, Lredis)
|
||||
api_th.start()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue