2024-08-02 09:50:02 +00:00
|
|
|
from typing import Union
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
import app.modules.db.server as server_sql
|
|
|
|
import app.modules.db.ha_cluster as ha_sql
|
|
|
|
import app.modules.db.service as service_sql
|
2024-02-17 12:28:34 +00:00
|
|
|
from app.modules.db.db_model import HaCluster, HaClusterRouter, HaClusterVip, HaClusterVirt
|
|
|
|
import app.modules.server.server as server_mod
|
|
|
|
import app.modules.roxywi.common as roxywi_common
|
|
|
|
from app.modules.server.ssh import return_ssh_keys_path
|
2024-08-02 09:50:02 +00:00
|
|
|
from app.modules.roxywi.class_models import HAClusterRequest, HAClusterVIP
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-02-17 12:28:34 +00:00
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def _get_servers_dict(cluster: Union[HAClusterRequest, HAClusterVIP]) -> dict:
|
|
|
|
for i, k in cluster.model_dump(mode='json').items():
|
|
|
|
if i == 'servers':
|
|
|
|
servers = k
|
|
|
|
return servers
|
|
|
|
|
|
|
|
|
|
|
|
def _get_services_dict(cluster: HAClusterRequest) -> dict:
|
|
|
|
for i, k in cluster.model_dump(mode='json').items():
|
|
|
|
if i == 'services':
|
|
|
|
services = k
|
|
|
|
return services
|
|
|
|
|
|
|
|
|
|
|
|
def create_cluster(cluster: HAClusterRequest, group_id: int) -> int:
|
2023-12-16 07:15:59 +00:00
|
|
|
master_ip = None
|
2024-08-02 09:50:02 +00:00
|
|
|
servers = _get_servers_dict(cluster)
|
|
|
|
services = _get_services_dict(cluster)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
cluster_id = ha_sql.create_cluster(cluster.name, cluster.syn_flood, group_id, cluster.description)
|
2023-12-16 08:34:45 +00:00
|
|
|
roxywi_common.logging(cluster_id, 'New cluster has been created', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
2024-08-02 09:50:02 +00:00
|
|
|
raise Exception(f'error: Cannot create new HA cluster: {e}')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
router_id = HaClusterRouter.insert(cluster_id=cluster_id, default=1).on_conflict_ignore().execute()
|
|
|
|
except Exception as e:
|
2024-08-02 09:50:02 +00:00
|
|
|
raise Exception(f'error: Cannon create router: {e}')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
vip_id = HaClusterVip.insert(cluster_id=cluster_id, router_id=router_id, vip=cluster.vip, return_master=cluster.return_master).execute()
|
|
|
|
roxywi_common.logging(cluster_id, f'New vip {cluster.vip} has been created and added to the cluster', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
2024-08-02 09:50:02 +00:00
|
|
|
raise Exception(f'error: Cannon add VIP: {e}')
|
|
|
|
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-08-02 18:12:14 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
|
|
|
master_ip = value['ip']
|
|
|
|
|
2024-08-02 18:12:14 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
|
|
|
continue
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.update_server_master(master_ip, value['ip'])
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update master on slave {value["ip"]: {e}}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2024-08-02 18:12:14 +00:00
|
|
|
slave_id = value['id']
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
2024-03-03 07:11:48 +00:00
|
|
|
slave_id = server_sql.select_server_id_by_ip(master_ip)
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'New server {value["ip"]} has been added to the cluster', keep_history=1, roxywi=1, service='HA cluster')
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update slave server {value["ip"]}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for service, value in services.items():
|
2023-12-16 07:15:59 +00:00
|
|
|
if not value['enabled']:
|
|
|
|
continue
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
service_id = service_sql.select_service_id_by_slug(service)
|
|
|
|
ha_sql.insert_cluster_services(cluster_id, service_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Service {service} has been enabled on the cluster', keep_history=1, roxywi=1, service='HA cluster')
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot add service {service}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
if cluster.virt_server:
|
|
|
|
add_or_update_virt(cluster, servers, cluster_id, vip_id, group_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
return int(cluster_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def update_cluster(cluster: HAClusterRequest, cluster_id: int, group_id: int) -> None:
|
|
|
|
servers = _get_servers_dict(cluster)
|
|
|
|
services = _get_services_dict(cluster)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
router_id = ha_sql.get_router_id(cluster_id, default_router=1)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot get router: {e}')
|
|
|
|
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
ha_sql.update_cluster(cluster_id, cluster.name, cluster.description, cluster.syn_flood)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update HA cluster: {e}')
|
|
|
|
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
update_slaves(servers, cluster_id, router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
|
|
|
|
try:
|
|
|
|
update_vip(cluster_id, router_id, cluster, group_id)
|
|
|
|
except Exception as e:
|
|
|
|
raise Exception(e)
|
|
|
|
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.delete_cluster_services(cluster_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot delete old services: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for service, value in services.items():
|
2023-12-16 07:15:59 +00:00
|
|
|
if not value['enabled']:
|
|
|
|
continue
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
service_id = service_sql.select_service_id_by_slug(service)
|
|
|
|
ha_sql.insert_cluster_services(cluster_id, service_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot add service {service}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Cluster {cluster.name} has been updated', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
def delete_cluster(cluster_id: int) -> str:
|
2024-03-03 07:11:48 +00:00
|
|
|
router_id = ha_sql.get_router_id(cluster_id, default_router=1)
|
|
|
|
slaves = ha_sql.select_cluster_slaves(cluster_id, router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
for slave in slaves:
|
2024-03-03 07:11:48 +00:00
|
|
|
slave_ip = server_sql.select_server_ip_by_id(slave[0])
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.update_master_server_by_slave_ip(0, slave_ip)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update master on slave {slave_ip}: {e}')
|
|
|
|
|
2023-12-30 19:59:56 +00:00
|
|
|
HaCluster.delete().where(HaCluster.id == cluster_id).execute()
|
|
|
|
roxywi_common.logging(cluster_id, 'Cluster has been deleted', roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
return 'ok'
|
|
|
|
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def update_vip(cluster_id: int, router_id: int, cluster: Union[HAClusterRequest, HAClusterVIP], group_id: int) -> None:
|
2024-03-03 07:11:48 +00:00
|
|
|
vip_id = ha_sql.select_clusters_vip_id(cluster_id, router_id)
|
2024-08-02 09:50:02 +00:00
|
|
|
servers = _get_servers_dict(cluster)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-08-04 14:44:11 +00:00
|
|
|
ha_sql.update_ha_cluster_vip(cluster_id, router_id, str(cluster.vip), cluster.return_master, cluster.use_src)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update VIP: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
ha_sql.update_slave(cluster_id, value['id'], value['eth'], value['master'], router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot add server {value["ip"]}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
if cluster.virt_server:
|
|
|
|
add_or_update_virt(cluster, servers, cluster_id, vip_id, group_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
else:
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
if ha_sql.check_ha_virt(vip_id):
|
|
|
|
ha_sql.delete_ha_virt(vip_id)
|
2024-08-02 09:50:02 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Cluster virtual server for VIP: {cluster.vip} has been deleted', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
2024-08-02 09:50:02 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Cannot delete cluster virtual server for VIP {cluster.vip}: {e}', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Cluster VIP {cluster.vip} has been updated', keep_history=1, roxywi=1, service='HA cluster')
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def insert_vip(cluster_id: int, cluster: HAClusterVIP, group_id: int) -> None:
|
|
|
|
vip = cluster.vip
|
|
|
|
servers = _get_servers_dict(cluster)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
router_id = ha_sql.create_ha_router(cluster_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot create new router: {e}')
|
|
|
|
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
vip_id = HaClusterVip.insert(cluster_id=cluster_id, router_id=router_id, vip=vip, return_master=cluster.return_master).execute()
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot save VIP {vip}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
ha_sql.insert_or_update_slave(cluster_id, value['id'], value['eth'], value['master'], router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot add server {value["ip"]}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
if cluster.virt_server:
|
|
|
|
add_or_update_virt(cluster, servers, cluster_id, vip_id, group_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
roxywi_common.logging(cluster_id, f'New cluster VIP: {vip} has been created', keep_history=1, roxywi=1, service='HA cluster')
|
|
|
|
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def update_slaves(servers: dict, cluster_id: int, router_id: int) -> None:
|
2023-12-16 07:15:59 +00:00
|
|
|
master_ip = None
|
|
|
|
all_routers_in_cluster = HaClusterRouter.select(HaClusterRouter.id).where(HaClusterRouter.cluster_id == cluster_id).execute()
|
2024-03-03 07:11:48 +00:00
|
|
|
server_ids_from_db = ha_sql.select_cluster_slaves(cluster_id, router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
server_ids = []
|
|
|
|
server_ids_from_json = []
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
2024-08-02 09:50:02 +00:00
|
|
|
master_ip = value['ip']
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
for server in server_ids_from_db:
|
|
|
|
server_ids.append(server[0])
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
|
|
|
slave_id = value['id']
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
2024-03-03 07:11:48 +00:00
|
|
|
slave_id = server_sql.select_server_id_by_ip(master_ip)
|
2023-12-16 07:15:59 +00:00
|
|
|
server_ids_from_json.append(int(slave_id))
|
|
|
|
|
|
|
|
server_ids_for_deletion = set(server_ids) - set(server_ids_from_json)
|
|
|
|
server_ids_for_adding = set(server_ids_from_json) - set(server_ids)
|
|
|
|
|
|
|
|
for router in all_routers_in_cluster:
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
|
|
|
slave_id = value['id']
|
2023-12-16 07:15:59 +00:00
|
|
|
for server_id_add in server_ids_for_adding:
|
|
|
|
if int(slave_id) == int(server_id_add):
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot add new slave {value["name"]}: {e}')
|
|
|
|
|
|
|
|
for o_s in server_ids_for_deletion:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.delete_master_from_slave(o_s)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.delete_ha_cluster_delete_slave(o_s)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot recreate slaves server: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
|
|
|
continue
|
|
|
|
try:
|
2024-08-02 09:50:02 +00:00
|
|
|
ha_sql.update_server_master(master_ip, value['ip'])
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update master on slave {value["ip"]}: {e}')
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
|
|
|
slave_id = value['id']
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
2024-03-03 07:11:48 +00:00
|
|
|
slave_id = server_sql.select_server_id_by_ip(master_ip)
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise Exception(f'error: Cannot update server {value["ip"]}: {e}')
|
|
|
|
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
def add_or_update_virt(cluster: Union[HAClusterRequest, HAClusterVIP], servers: dict, cluster_id: int, vip_id: int, group_id: int) -> None:
|
2023-12-16 07:15:59 +00:00
|
|
|
haproxy = 0
|
|
|
|
nginx = 0
|
|
|
|
apache = 0
|
|
|
|
master_ip = None
|
2024-08-04 14:44:11 +00:00
|
|
|
vip = str(cluster.vip)
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
for value in servers:
|
2023-12-16 07:15:59 +00:00
|
|
|
if value['master']:
|
2024-08-02 09:50:02 +00:00
|
|
|
master_ip = value['ip']
|
2023-12-16 07:15:59 +00:00
|
|
|
|
2024-03-03 07:11:48 +00:00
|
|
|
if ha_sql.check_ha_virt(vip_id):
|
2023-12-16 07:15:59 +00:00
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
ha_sql.update_ha_virt_ip(vip_id, vip)
|
2023-12-16 07:15:59 +00:00
|
|
|
roxywi_common.logging(cluster_id, f'Cluster virtual server for VIP {vip} has been updated', keep_history=1, roxywi=1, service='HA cluster')
|
|
|
|
except Exception as e:
|
|
|
|
roxywi_common.logging(cluster_id, f'Cannot update cluster virtual server for VIP {vip}: {e}', roxywi=1, service='HA cluster')
|
|
|
|
else:
|
2024-03-03 07:11:48 +00:00
|
|
|
services = ha_sql.select_cluster_services(cluster_id)
|
2023-12-16 07:15:59 +00:00
|
|
|
for service in services:
|
|
|
|
haproxy = 1 if service.service_id == '1' else 0
|
|
|
|
nginx = 1 if service.service_id == '2' else 0
|
|
|
|
apache = 1 if service.service_id == '4' else 0
|
|
|
|
try:
|
2024-03-03 07:11:48 +00:00
|
|
|
cred_id = ha_sql.get_cred_id_by_server_ip(master_ip)
|
2023-12-16 07:15:59 +00:00
|
|
|
firewall = 1 if server_mod.is_service_active(master_ip, 'firewalld') else 0
|
|
|
|
ssh_settings = return_ssh_keys_path(master_ip)
|
2024-03-03 07:11:48 +00:00
|
|
|
virt_id = server_sql.add_server(
|
2023-12-16 07:15:59 +00:00
|
|
|
f'{vip}-VIP', vip, group_id, '1', '1', '0', cred_id, ssh_settings['port'],
|
2024-08-02 09:50:02 +00:00
|
|
|
f'VRRP IP for {cluster.name} cluster', haproxy, nginx, apache, firewall
|
2023-12-16 07:15:59 +00:00
|
|
|
)
|
|
|
|
HaClusterVirt.insert(cluster_id=cluster_id, virt_id=virt_id, vip_id=vip_id).execute()
|
|
|
|
roxywi_common.logging(cluster_id, f'New cluster virtual server for VIP: {vip} has been created', keep_history=1, roxywi=1,
|
|
|
|
service='HA cluster')
|
|
|
|
except Exception as e:
|
|
|
|
roxywi_common.logging(cluster_id, f'error: Cannot create new cluster virtual server for VIP: {vip}: {e}', roxywi=1, service='HA cluster')
|