1
0
Fork 0
mirror of https://github.com/ThomasGsp/HyperProxmox.git synced 2025-03-09 15:40:18 +00:00

first commit

This commit is contained in:
thomas.guiseppin 2017-10-21 22:04:42 +02:00
commit 5352a2b94a
396 changed files with 10008 additions and 0 deletions

View 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>
```

View file

@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

View 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)))

View file

View file

View 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.

Binary file not shown.

View 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

View file

@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

View 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

View file

View file

View file

@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

View 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

View 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

View 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))

View 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

View 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

View 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

View 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

View 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-----

View 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-----

View 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()