diff --git a/app/modules/roxywi/class_models.py b/app/modules/roxywi/class_models.py index e669696b..771a5ed7 100644 --- a/app/modules/roxywi/class_models.py +++ b/app/modules/roxywi/class_models.py @@ -179,6 +179,7 @@ class HAClusterRequest(BaseModel): use_src: Optional[bool] = 1 vip: Optional[IPvAnyAddress] = None virt_server: Optional[bool] = 1 + reconfigure: Optional[bool] = 0 class ConfigFileNameQuery(BaseModel): diff --git a/app/modules/service/ha_cluster.py b/app/modules/service/ha_cluster.py index 8de9dbe9..5c103bc1 100644 --- a/app/modules/service/ha_cluster.py +++ b/app/modules/service/ha_cluster.py @@ -18,7 +18,7 @@ def _get_servers_dict(cluster: Union[HAClusterRequest, HAClusterVIP, HAClusterSe return servers -def _get_services_dict(cluster: HAClusterRequest) -> dict: +def get_services_dict(cluster: HAClusterRequest) -> dict: for i, k in cluster.model_dump(mode='json').items(): if i == 'services': services = k @@ -27,7 +27,7 @@ def _get_services_dict(cluster: HAClusterRequest) -> dict: def create_cluster(cluster: HAClusterRequest, group_id: int) -> int: servers = _get_servers_dict(cluster) - services = _get_services_dict(cluster) + services = get_services_dict(cluster) try: cluster_id = ha_sql.create_cluster(cluster.name, cluster.syn_flood, group_id, cluster.description) @@ -70,7 +70,7 @@ def create_cluster(cluster: HAClusterRequest, group_id: int) -> int: def update_cluster(cluster: HAClusterRequest, cluster_id: int, group_id: int) -> None: servers = _get_servers_dict(cluster) - services = _get_services_dict(cluster) + services = get_services_dict(cluster) try: ha_sql.update_cluster(cluster_id, cluster.name, cluster.description, cluster.syn_flood) diff --git a/app/modules/service/installation.py b/app/modules/service/installation.py index 73061e13..255d13c6 100644 --- a/app/modules/service/installation.py +++ b/app/modules/service/installation.py @@ -16,7 +16,7 @@ import app.modules.common.common as common 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 -from app.modules.roxywi.class_models import ServiceInstall +from app.modules.roxywi.class_models import ServiceInstall, HAClusterRequest def generate_udp_inv(listener_id: int, action: str) -> object: @@ -328,7 +328,7 @@ def service_actions_after_install(server_ips: str, service: str, json_data) -> N service_sql.insert_or_update_service_setting(server_id, service, 'restart', '1') -def install_service(service: str, json_data: Union[str, ServiceInstall]) -> dict: +def install_service(service: str, json_data: Union[str, ServiceInstall, HAClusterRequest], cluster_id: int = None) -> dict: generate_functions = { 'haproxy': generate_haproxy_inv, 'nginx': generate_service_inv, @@ -337,6 +337,8 @@ def install_service(service: str, json_data: Union[str, ServiceInstall]) -> dict } json_data = json_data.model_dump(mode='json') + if cluster_id: + json_data['cluster_id'] = cluster_id try: inv, server_ips = generate_functions[service](json_data, service) except Exception as e: diff --git a/app/views/ha/views.py b/app/views/ha/views.py index 7fff9644..80103fad 100644 --- a/app/views/ha/views.py +++ b/app/views/ha/views.py @@ -8,8 +8,10 @@ import app.modules.db.ha_cluster as ha_sql import app.modules.roxywi.common as roxywi_common import app.modules.common.common as common import app.modules.service.ha_cluster as ha_cluster +import app.modules.service.installation as service_mod from app.middleware import get_user_params, page_for_admin, check_group, check_services from app.modules.roxywi.class_models import BaseResponse, IdResponse, HAClusterRequest, HAClusterVIP +from app.routes.service.routes import services class HAView(MethodView): @@ -179,10 +181,17 @@ class HAView(MethodView): """ try: cluster_id = ha_cluster.create_cluster(body, self.group_id) - return IdResponse(id=cluster_id).model_dump(mode='json'), 201 except Exception as e: return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot create cluster') + if body.reconfigure: + try: + self._install_service(body, cluster_id) + except Exception as e: + return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot reconfigure cluster') + + return IdResponse(id=cluster_id).model_dump(mode='json'), 201 + @validate(body=HAClusterRequest) def put(self, service: str, cluster_id: int, body: HAClusterRequest): """ @@ -258,10 +267,17 @@ class HAView(MethodView): """ try: ha_cluster.update_cluster(body, cluster_id, self.group_id) - return BaseResponse().model_dump(mode='json'), 201 except Exception as e: return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot update cluster') + if body.reconfigure: + try: + self._install_service(body, cluster_id) + except Exception as e: + return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot reconfigure cluster') + + return BaseResponse().model_dump(mode='json'), 201 + @staticmethod def delete(service: str, cluster_id: int): """ @@ -294,6 +310,29 @@ class HAView(MethodView): except Exception as e: return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete cluster') + @staticmethod + def _install_service(body: HAClusterRequest, cluster_id: int): + try: + output = service_mod.install_service('keepalived', body, cluster_id) + except Exception as e: + raise e + + if len(output['failures']) > 0 or len(output['dark']) > 0: + raise Exception('Cannot install Keepalived. Check Apache error log') + + cluster_services = ha_cluster.get_services_dict(body) + for service, value in cluster_services.items(): + if not value['enabled']: + continue + else: + try: + output = service_mod.install_service(service, body) + except Exception as e: + raise e + + if len(output['failures']) > 0 or len(output['dark']) > 0: + raise Exception(f'Cannot install {service.title()}. Check Apache error log') + class HAVIPView(MethodView): methods = ["GET", "POST", "PUT", "DELETE"]