mirror of https://github.com/Aidaho12/haproxy-wi
parent
cc0edee75a
commit
820b0cd3db
|
@ -147,6 +147,7 @@ def default_values():
|
|||
{'service_id': 2, 'service': 'NGINX', 'slug': 'nginx'},
|
||||
{'service_id': 3, 'service': 'Keepalived', 'slug': 'keepalived'},
|
||||
{'service_id': 4, 'service': 'Apache', 'slug': 'apache'},
|
||||
{'service_id': 5, 'service': 'HA cluster', 'slug': 'cluster'},
|
||||
]
|
||||
|
||||
try:
|
||||
|
@ -668,7 +669,7 @@ def update_db_v_6_3_18():
|
|||
|
||||
def update_ver():
|
||||
try:
|
||||
Version.update(version='7.0.4.0').execute()
|
||||
Version.update(version='7.1.0.0').execute()
|
||||
except Exception:
|
||||
print('Cannot update version')
|
||||
|
||||
|
|
16
app/jobs.py
16
app/jobs.py
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import shutil
|
||||
import datetime
|
||||
|
||||
import distro
|
||||
|
@ -78,3 +79,18 @@ def update_owner_on_log():
|
|||
os.system(f'sudo chown apache:apache -R {log_path}')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@scheduler.task('interval', id='delete_ansible_artifacts', hours=24, misfire_grace_time=None)
|
||||
def delete_ansible_artifacts():
|
||||
full_path = get_config.get_config_var('main', 'fullpath')
|
||||
ansible_path = f'{full_path}/app/scripts/ansible'
|
||||
folders = ['artifacts', 'env']
|
||||
|
||||
for folder in folders:
|
||||
if os.path.isdir(f'{ansible_path}/{folder}'):
|
||||
try:
|
||||
shutil.rmtree(f'{ansible_path}/{folder}')
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cron cannot delete ansible folders: {e}')
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ def check_services(fn):
|
|||
@wraps(fn)
|
||||
def decorated_view(*args, **kwargs):
|
||||
service = kwargs['service']
|
||||
if service not in ('haproxy', 'nginx', 'apache', 'keepalived'):
|
||||
if service not in ('haproxy', 'nginx', 'apache', 'keepalived', 'cluster'):
|
||||
abort(405, 'Wrong service')
|
||||
if not roxywi_auth.is_access_permit_to_service(service):
|
||||
abort(403, f'You do not have needed permissions to access to {service.title()} service')
|
||||
|
|
|
@ -36,7 +36,7 @@ class User(BaseModel, UserMixin):
|
|||
groups = CharField()
|
||||
ldap_user = IntegerField(constraints=[SQL('DEFAULT "0"')])
|
||||
activeuser = IntegerField(constraints=[SQL('DEFAULT "1"')])
|
||||
user_services = CharField(constraints=[SQL('DEFAULT "1 2 3 4"')])
|
||||
user_services = CharField(constraints=[SQL('DEFAULT "1 2 3 4 5"')])
|
||||
last_login_date = DateTimeField(constraints=[SQL('DEFAULT "0000-00-00 00:00:00"')])
|
||||
last_login_ip = CharField(null=True)
|
||||
|
||||
|
@ -649,12 +649,81 @@ class RoxyTool(BaseModel):
|
|||
constraints = [SQL('UNIQUE (name)')]
|
||||
|
||||
|
||||
class HaCluster(BaseModel):
|
||||
id = AutoField()
|
||||
name = CharField()
|
||||
syn_flood = IntegerField(constraints=[SQL('DEFAULT "0"')])
|
||||
group_id = IntegerField()
|
||||
desc = CharField()
|
||||
pos = IntegerField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_clusters'
|
||||
|
||||
|
||||
class HaClusterRouter(BaseModel):
|
||||
id = AutoField()
|
||||
cluster_id = ForeignKeyField(HaCluster, on_delete='Cascade')
|
||||
default = IntegerField(constraints=[SQL('DEFAULT "0"')])
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_cluster_routers'
|
||||
|
||||
|
||||
class HaClusterSlave(BaseModel):
|
||||
id = AutoField()
|
||||
cluster_id = ForeignKeyField(HaCluster, on_delete='Cascade')
|
||||
server_id = ForeignKeyField(Server, on_delete='Cascade')
|
||||
master = IntegerField(constraints=[SQL('DEFAULT "0"')])
|
||||
eth = CharField(constraints=[SQL('DEFAULT "eth0"')])
|
||||
router_id = ForeignKeyField(HaClusterRouter, on_delete='Cascade')
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_cluster_slaves'
|
||||
constraints = [SQL('UNIQUE (cluster_id, server_id, router_id)')]
|
||||
|
||||
|
||||
class HaClusterVip(BaseModel):
|
||||
id = AutoField()
|
||||
cluster_id = ForeignKeyField(HaCluster, on_delete='Cascade')
|
||||
router_id = ForeignKeyField(HaClusterRouter, on_delete='Cascade')
|
||||
return_master = IntegerField(constraints=[SQL('DEFAULT "0"')])
|
||||
vip = CharField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_cluster_vips'
|
||||
constraints = [SQL('UNIQUE (cluster_id, vip)')]
|
||||
|
||||
|
||||
class HaClusterVirt(BaseModel):
|
||||
cluster_id = ForeignKeyField(HaCluster, on_delete='Cascade')
|
||||
virt_id = ForeignKeyField(Server, on_delete='Cascade')
|
||||
vip_id = ForeignKeyField(HaClusterVip, on_delete='Cascade')
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_cluster_virts'
|
||||
primary_key = False
|
||||
constraints = [SQL('UNIQUE (cluster_id, virt_id)')]
|
||||
|
||||
|
||||
class HaClusterService(BaseModel):
|
||||
cluster_id = ForeignKeyField(HaCluster, on_delete='Cascade')
|
||||
service_id = CharField()
|
||||
|
||||
class Meta:
|
||||
table_name = 'ha_cluster_services'
|
||||
primary_key = False
|
||||
constraints = [SQL('UNIQUE (cluster_id, service_id)')]
|
||||
|
||||
|
||||
def create_tables():
|
||||
with conn:
|
||||
conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion,
|
||||
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory,
|
||||
PortScannerSettings, PortScannerPorts, PortScannerHistory, ServiceSetting, MetricsHttpStatus,
|
||||
SMON, WafRules, Alerts, GeoipCodes, NginxMetrics, SystemInfo, Services, UserName, GitSetting,
|
||||
CheckerSetting, ApacheMetrics, WafNginx, ServiceStatus, KeepaliveRestart, PD, SmonHistory,
|
||||
SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup, RoxyTool, SmonStatusPage,
|
||||
SmonStatusPageCheck])
|
||||
conn.create_tables(
|
||||
[User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion, Setting,
|
||||
Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory, PortScannerSettings,
|
||||
PortScannerPorts, PortScannerHistory, ServiceSetting, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes,
|
||||
NginxMetrics, SystemInfo, Services, UserName, GitSetting, CheckerSetting, ApacheMetrics, WafNginx, ServiceStatus,
|
||||
KeepaliveRestart, PD, SmonHistory, SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup, RoxyTool,
|
||||
SmonStatusPage, SmonStatusPageCheck, HaCluster, HaClusterSlave, HaClusterVip, HaClusterVirt, HaClusterService,
|
||||
HaClusterRouter]
|
||||
)
|
||||
|
|
|
@ -291,11 +291,11 @@ def update_group(name, descript, group_id):
|
|||
|
||||
def add_server(hostname, ip, group, typeip, enable, master, cred, port, desc, haproxy, nginx, apache, firewall):
|
||||
try:
|
||||
Server.insert(
|
||||
server_id = Server.insert(
|
||||
hostname=hostname, ip=ip, groups=group, type_ip=typeip, enable=enable, master=master, cred=cred,
|
||||
port=port, desc=desc, haproxy=haproxy, nginx=nginx, apache=apache, firewall_enable=firewall
|
||||
).execute()
|
||||
return True
|
||||
return server_id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
return False
|
||||
|
@ -4265,3 +4265,257 @@ def delete_status_page(page_id):
|
|||
SmonStatusPage.delete().where(SmonStatusPage.id == page_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters(group_id: int):
|
||||
try:
|
||||
return HaCluster.select().where(HaCluster.group_id == group_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def create_cluster(name: str, syn_flood: int, group_id: int, desc: str) -> int:
|
||||
try:
|
||||
last_id = HaCluster.insert(
|
||||
name=name, syn_flood=syn_flood, group_id=group_id, desc=desc
|
||||
).execute()
|
||||
return last_id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_cluster(cluster_id: int):
|
||||
try:
|
||||
return HaCluster.select().where(HaCluster.id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_cluster_name(cluster_id: int) -> str:
|
||||
try:
|
||||
return HaCluster.get(HaCluster.id == cluster_id).name
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_slaves():
|
||||
try:
|
||||
return HaClusterSlave.select().execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_virts():
|
||||
try:
|
||||
return HaClusterVirt.select().execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_vips():
|
||||
try:
|
||||
return HaClusterVip.select().execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_cluster_vips(cluster_id: int) -> object:
|
||||
try:
|
||||
return HaClusterVip.select().where(HaClusterVip.cluster_id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_vip(cluster_id: int, router_id: int):
|
||||
try:
|
||||
return HaClusterVip.get((HaClusterVip.cluster_id == cluster_id) & (HaClusterVip.router_id == router_id)).vip
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_vip_return_master(cluster_id: int, router_id: int):
|
||||
try:
|
||||
return HaClusterVip.get((HaClusterVip.cluster_id == cluster_id) & (HaClusterVip.router_id == router_id)).return_master
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_clusters_vip_id(cluster_id: int, router_id):
|
||||
try:
|
||||
return HaClusterVip.get((HaClusterVip.cluster_id == cluster_id) & (HaClusterVip.router_id == router_id)).id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_cluster_services(cluster_id: int):
|
||||
try:
|
||||
return HaClusterService.select().where(HaClusterService.cluster_id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_cluster_services(cluster_id: int):
|
||||
try:
|
||||
return HaClusterService.delete().where(HaClusterService.cluster_id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def insert_cluster_services(cluster_id: int, service_id: int):
|
||||
try:
|
||||
return HaClusterService.insert(cluster_id=cluster_id, service_id=service_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_cluster_master_slaves(cluster_id: int, group_id: int):
|
||||
cursor = conn.cursor()
|
||||
sql = f"select * from servers left join ha_clusters on (servers.id = ha_clusters.master_id) " \
|
||||
f"left join ha_cluster_slaves on (servers.id = ha_cluster_slaves.server_id) " \
|
||||
f"left join ha_cluster_virts on (servers.id = ha_cluster_virts.virt_id)" \
|
||||
f"where (servers.groups = {group_id} and " \
|
||||
f"(ha_cluster_slaves.cluster_id = {cluster_id} or ha_clusters.id = {cluster_id} or ha_cluster_virts.cluster_id = {cluster_id}));"
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
else:
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def select_cluster_slaves(cluster_id: int, router_id: int):
|
||||
cursor = conn.cursor()
|
||||
sql = f"select * from servers " \
|
||||
f"left join ha_cluster_slaves on (servers.id = ha_cluster_slaves.server_id) " \
|
||||
f"where ha_cluster_slaves.cluster_id = {cluster_id} and ha_cluster_slaves.router_id = {router_id};"
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
else:
|
||||
return cursor.fetchall()
|
||||
|
||||
|
||||
def select_cluster_slaves_for_inv(router_id: int):
|
||||
try:
|
||||
return HaClusterSlave.select().where(HaClusterSlave.router_id == router_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_ha_cluster_delete_slave(server_id: int) -> None:
|
||||
try:
|
||||
HaClusterSlave.delete().where(HaClusterSlave.server_id == server_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_ha_cluster_delete_slaves(cluster_id: int) -> None:
|
||||
try:
|
||||
HaClusterSlave.delete().where(HaClusterSlave.cluster_id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_master_from_slave(server_id: int) -> None:
|
||||
try:
|
||||
Server.update(master=0).where(Server.server_id == server_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def ha_cluster_add_slave(server_id: int, master_id: int) -> None:
|
||||
try:
|
||||
HaClusterSlave.insert(
|
||||
server_id=server_id,
|
||||
cluster_id=HaCluster.get(HaCluster.master_id == master_id).id
|
||||
).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_ha_cluster_not_masters_not_slaves(group_id: int):
|
||||
try:
|
||||
query = Server.select().where(
|
||||
(Server.type_ip == 0) &
|
||||
(Server.server_id.not_in(HaClusterSlave.select(HaClusterSlave.server_id))) &
|
||||
(Server.groups == group_id)
|
||||
)
|
||||
return query.execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def get_router_id(cluster_id: int, default_router=0) -> int:
|
||||
try:
|
||||
return HaClusterRouter.get((HaClusterRouter.cluster_id == cluster_id) & (HaClusterRouter.default == default_router)).id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def create_ha_router(cluster_id: int) -> int:
|
||||
try:
|
||||
last_id = HaClusterRouter.insert(cluster_id=cluster_id).execute()
|
||||
return last_id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_ha_router(router_id: int) -> int:
|
||||
try:
|
||||
last_id = HaClusterRouter.delete().where(HaClusterRouter.id == router_id).execute()
|
||||
return last_id
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def insert_or_update_slave(cluster_id: int, server_id: int, eth: str, master: int, router_id) -> None:
|
||||
try:
|
||||
HaClusterSlave.insert(cluster_id=cluster_id, server_id=server_id, eth=eth, master=master, router_id=router_id).on_conflict('replace').execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def update_slave(cluster_id: int, server_id: int, eth: str, master: int, router_id) -> None:
|
||||
try:
|
||||
HaClusterSlave.update(
|
||||
cluster_id=cluster_id, server_id=server_id, eth=eth, master=master, router_id=router_id
|
||||
).where((HaClusterSlave.server_id == server_id) & (HaClusterSlave.router_id == router_id)).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def update_cluster(cluster_id: int, name: str, desc: str, syn_flood: int) -> None:
|
||||
try:
|
||||
HaCluster.update(name=name, desc=desc, syn_flood=syn_flood).where(HaCluster.id == cluster_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def update_ha_cluster_vip(cluster_id: int, router_id: int, vip: str, return_master: int) -> None:
|
||||
try:
|
||||
HaClusterVip.update(vip=vip, return_master=return_master).where((HaClusterVip.cluster_id == cluster_id) & (HaClusterVip.router_id == router_id)).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def update_ha_virt_ip(vip_id: int, vip: str) -> None:
|
||||
try:
|
||||
Server.update(ip=vip).where(Server.server_id == HaClusterVirt.get(HaClusterVirt.vip_id == vip_id).virt_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_ha_virt(vip_id: int) -> None:
|
||||
try:
|
||||
Server.delete().where(Server.server_id == HaClusterVirt.get(HaClusterVirt.vip_id == vip_id).virt_id).execute()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
def check_ha_virt(vip_id: int) -> bool:
|
||||
try:
|
||||
HaClusterVirt.get(HaClusterVirt.vip_id == vip_id).virt_id
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
|
|
@ -131,11 +131,6 @@ def logging(server_ip: str, action: str, **kwargs) -> None:
|
|||
if kwargs.get('roxywi') == 1:
|
||||
if kwargs.get('login'):
|
||||
mess = f"{cur_date_in_log} from {ip} user: {login}, group: {user_group}, {action} on: {server_ip}\n"
|
||||
if kwargs.get('keep_history'):
|
||||
try:
|
||||
keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
else:
|
||||
mess = f"{cur_date_in_log} {action} from {ip}\n"
|
||||
log_file = f"{log_path}/roxy-wi-{cur_date}.log"
|
||||
|
@ -146,11 +141,11 @@ def logging(server_ip: str, action: str, **kwargs) -> None:
|
|||
mess = f"{cur_date_in_log} from {ip} user: {login}, group: {user_group}, {action} on: {server_ip}\n"
|
||||
log_file = f"{log_path}/config_edit-{cur_date}.log"
|
||||
|
||||
if kwargs.get('keep_history'):
|
||||
try:
|
||||
keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
|
||||
except Exception:
|
||||
pass
|
||||
if kwargs.get('keep_history'):
|
||||
try:
|
||||
keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
|
||||
except Exception as e:
|
||||
print(f'error: Cannot save history: {e}')
|
||||
|
||||
try:
|
||||
with open(log_file, 'a') as log:
|
||||
|
@ -160,19 +155,24 @@ def logging(server_ip: str, action: str, **kwargs) -> None:
|
|||
|
||||
|
||||
def keep_action_history(service: str, action: str, server_ip: str, login: str, user_ip: str):
|
||||
try:
|
||||
server_id = sql.select_server_id_by_ip(server_ip=server_ip)
|
||||
hostname = sql.get_hostname_by_server_ip(server_ip)
|
||||
if login != '':
|
||||
user_id = sql.get_user_id_by_username(login)
|
||||
else:
|
||||
user_id = 0
|
||||
if user_ip == '':
|
||||
user_ip = 'localhost'
|
||||
if login != '':
|
||||
user_id = sql.get_user_id_by_username(login)
|
||||
else:
|
||||
user_id = 0
|
||||
if user_ip == '':
|
||||
user_ip = 'localhost'
|
||||
|
||||
sql.insert_action_history(service, action, server_id, user_id, user_ip, server_ip, hostname)
|
||||
except Exception as e:
|
||||
logging('Roxy-WI server', f'Cannot save a history: {e}', roxywi=1)
|
||||
if service == 'HA cluster':
|
||||
cluster_name = sql.select_cluster_name(server_ip)
|
||||
sql.insert_action_history(service, action, server_ip, user_id, user_ip, server_ip, cluster_name)
|
||||
else:
|
||||
try:
|
||||
server_id = sql.select_server_id_by_ip(server_ip=server_ip)
|
||||
hostname = sql.get_hostname_by_server_ip(server_ip)
|
||||
|
||||
sql.insert_action_history(service, action, server_id, user_id, user_ip, server_ip, hostname)
|
||||
except Exception as e:
|
||||
logging('Roxy-WI server', f'Cannot save a history: {e}', roxywi=1)
|
||||
|
||||
|
||||
def get_dick_permit(**kwargs):
|
||||
|
@ -253,7 +253,8 @@ def get_users_params(**kwargs):
|
|||
'servers': servers,
|
||||
'user_services': user_services,
|
||||
'lang': user_lang,
|
||||
'user_id': user_id
|
||||
'user_id': user_id,
|
||||
'group_id': group_id
|
||||
}
|
||||
|
||||
return user_params
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
import modules.db.sql as sql
|
||||
from modules.db.db_model import HaCluster, HaClusterRouter, HaClusterVip, HaClusterVirt
|
||||
import modules.common.common as common
|
||||
import modules.server.server as server_mod
|
||||
import modules.roxywi.common as roxywi_common
|
||||
from modules.server.ssh import return_ssh_keys_path
|
||||
|
||||
|
||||
def create_cluster(cluster: object, group_id: int) -> str:
|
||||
master_ip = None
|
||||
vip = common.is_ip_or_dns(cluster['vip'])
|
||||
syn_flood = int(cluster['syn_flood'])
|
||||
return_master = int(cluster['return_to_master'])
|
||||
|
||||
try:
|
||||
cluster_id = sql.create_cluster(cluster['name'], syn_flood, group_id, cluster['desc'])
|
||||
roxywi_common.logging(cluster_id, f'New cluster has been created', keep_history=1, roxywi=1, service='HA cluster')
|
||||
except Exception as e:
|
||||
return f'error: Cannot create new HA cluster: {e}'
|
||||
|
||||
try:
|
||||
router_id = HaClusterRouter.insert(cluster_id=cluster_id, default=1).on_conflict_ignore().execute()
|
||||
except Exception as e:
|
||||
return f'error: Cannon create router: {e}'
|
||||
|
||||
try:
|
||||
vip_id = HaClusterVip.insert(cluster_id=cluster_id, router_id=router_id, vip=vip, return_master=return_master).execute()
|
||||
roxywi_common.logging(cluster_id, f'New vip {vip} has been created and added to the cluster', keep_history=1, roxywi=1, service='HA cluster')
|
||||
except Exception as e:
|
||||
return f'error: Cannon add VIP: {e}'
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
master_ip = value['ip']
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
continue
|
||||
try:
|
||||
sql.update_server_master(master_ip, value['ip'])
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update master on slave {value["ip"]: {e}}')
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
slave_id = sql.select_server_id_by_ip(master_ip)
|
||||
try:
|
||||
sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
||||
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}')
|
||||
|
||||
for service, value in cluster['services'].items():
|
||||
if not value['enabled']:
|
||||
continue
|
||||
try:
|
||||
service_id = sql.select_service_id_by_slug(service)
|
||||
sql.insert_cluster_services(cluster_id, service_id)
|
||||
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}')
|
||||
|
||||
if cluster['virt_server']:
|
||||
add_or_update_virt(cluster, cluster_id, vip_id, group_id)
|
||||
|
||||
return str(cluster_id)
|
||||
|
||||
|
||||
def update_cluster(cluster: object, group_id: int) -> str:
|
||||
cluster_id = int(cluster['cluster_id'])
|
||||
syn_flood = int(cluster['syn_flood'])
|
||||
cluster_name = cluster['name']
|
||||
|
||||
try:
|
||||
router_id = sql.get_router_id(cluster_id, default_router=1)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot get router: {e}')
|
||||
|
||||
try:
|
||||
sql.update_cluster(cluster_id, cluster['name'], cluster['desc'], syn_flood)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update HA cluster: {e}')
|
||||
|
||||
try:
|
||||
update_slaves(cluster, router_id)
|
||||
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:
|
||||
sql.delete_cluster_services(cluster_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot delete old services: {e}')
|
||||
|
||||
for service, value in cluster['services'].items():
|
||||
if not value['enabled']:
|
||||
continue
|
||||
try:
|
||||
service_id = sql.select_service_id_by_slug(service)
|
||||
sql.insert_cluster_services(cluster_id, service_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot add service {service}: {e}')
|
||||
|
||||
roxywi_common.logging(cluster_id, f'Cluster {cluster_name} has been updated', keep_history=1, roxywi=1, service='HA cluster')
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def delete_cluster(cluster_id: int) -> str:
|
||||
HaCluster.delete().where(HaCluster.id == cluster_id).execute()
|
||||
slaves = sql.select_cluster_slaves(cluster_id)
|
||||
|
||||
for slave in slaves:
|
||||
slave_ip = select_server_ip_by_id(slave.server_id)
|
||||
try:
|
||||
sql.update_server_master(0, slave_ip)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update master on slave {slave_ip}: {e}')
|
||||
|
||||
roxywi_common.logging(cluster_id, f'Cluster {cluster_name} has been deleted', keep_history=1, roxywi=1, service='HA cluster')
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def update_vip(cluster_id: int, router_id: int, json_data: object, group_id: int) -> None:
|
||||
return_master = int(json_data['return_to_master'])
|
||||
vip = common.is_ip_or_dns(json_data['vip'])
|
||||
vip_id = sql.select_clusters_vip_id(cluster_id, router_id)
|
||||
|
||||
try:
|
||||
sql.update_ha_cluster_vip(cluster_id, router_id, vip, return_master)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update VIP: {e}')
|
||||
|
||||
for slave_id, value in json_data['servers'].items():
|
||||
try:
|
||||
sql.update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot add server {value["ip"]}: {e}')
|
||||
|
||||
if json_data['virt_server']:
|
||||
add_or_update_virt(json_data, cluster_id, vip_id, group_id)
|
||||
else:
|
||||
try:
|
||||
if sql.check_ha_virt(vip_id):
|
||||
sql.delete_ha_virt(vip_id)
|
||||
roxywi_common.logging(cluster_id, f'Cluster virtual server for VIP: {vip} has been deleted', keep_history=1, roxywi=1, service='HA cluster')
|
||||
except Exception as e:
|
||||
roxywi_common.logging(cluster_id, f'Cannot delete cluster virtual server for VIP {vip}: {e}', keep_history=1, roxywi=1, service='HA cluster')
|
||||
|
||||
roxywi_common.logging(cluster_id, f'Cluster VIP {vip} has been updated', keep_history=1, roxywi=1, service='HA cluster')
|
||||
|
||||
|
||||
def insert_vip(cluster_id: int, json_data: object, group_id: int) -> None:
|
||||
vip = common.is_ip_or_dns(json_data['vip'])
|
||||
return_master = int(json_data['return_to_master'])
|
||||
|
||||
try:
|
||||
router_id = sql.create_ha_router(cluster_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot create new router: {e}')
|
||||
|
||||
try:
|
||||
vip_id = HaClusterVip.insert(cluster_id=cluster_id, router_id=router_id, vip=vip, return_master=return_master).execute()
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot save VIP {vip}: {e}')
|
||||
|
||||
for slave_id, value in json_data['servers'].items():
|
||||
try:
|
||||
sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot add server {value["ip"]}: {e}')
|
||||
|
||||
if json_data['virt_server']:
|
||||
add_or_update_virt(json_data, cluster_id, vip_id, group_id)
|
||||
|
||||
roxywi_common.logging(cluster_id, f'New cluster VIP: {vip} has been created', keep_history=1, roxywi=1, service='HA cluster')
|
||||
|
||||
|
||||
def update_slaves(json_data: object, router_id: int) -> None:
|
||||
master_ip = None
|
||||
cluster = json_data
|
||||
cluster_id = int(json_data['cluster_id'])
|
||||
all_routers_in_cluster = HaClusterRouter.select(HaClusterRouter.id).where(HaClusterRouter.cluster_id == cluster_id).execute()
|
||||
server_ids_from_db = sql.select_cluster_slaves(cluster_id, router_id)
|
||||
server_ids = []
|
||||
server_ids_from_json = []
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
master_ip = value['ip']
|
||||
|
||||
for server in server_ids_from_db:
|
||||
server_ids.append(server[0])
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
slave_id = sql.select_server_id_by_ip(master_ip)
|
||||
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:
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
for server_id_add in server_ids_for_adding:
|
||||
if int(slave_id) == int(server_id_add):
|
||||
try:
|
||||
sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot add new slave {value["name"]}: {e}')
|
||||
|
||||
for o_s in server_ids_for_deletion:
|
||||
sql.delete_master_from_slave(o_s)
|
||||
|
||||
try:
|
||||
sql.delete_ha_cluster_delete_slave(o_s)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot recreate slaves server: {e}')
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
continue
|
||||
try:
|
||||
sql.update_server_master(master_ip, value['ip'])
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update master on slave {value["ip"]}: {e}')
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
slave_id = sql.select_server_id_by_ip(master_ip)
|
||||
try:
|
||||
sql.insert_or_update_slave(cluster_id, slave_id, value['eth'], value['master'], router_id)
|
||||
except Exception as e:
|
||||
raise Exception(f'error: Cannot update server {value["ip"]}: {e}')
|
||||
|
||||
|
||||
def add_or_update_virt(cluster: object, cluster_id: int, vip_id: int, group_id: int) -> None:
|
||||
haproxy = 0
|
||||
nginx = 0
|
||||
apache = 0
|
||||
master_ip = None
|
||||
vip = common.is_ip_or_dns(cluster['vip'])
|
||||
cluster_name = common.checkAjaxInput(cluster['name'])
|
||||
|
||||
for slave_id, value in cluster['servers'].items():
|
||||
if value['master']:
|
||||
master_ip = common.is_ip_or_dns(value['ip'])
|
||||
|
||||
if sql.check_ha_virt(vip_id):
|
||||
try:
|
||||
sql.update_ha_virt_ip(vip_id, vip)
|
||||
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:
|
||||
services = sql.select_cluster_services(cluster_id)
|
||||
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:
|
||||
cred_id = sql.get_cred_id_by_server_ip(master_ip)
|
||||
firewall = 1 if server_mod.is_service_active(master_ip, 'firewalld') else 0
|
||||
ssh_settings = return_ssh_keys_path(master_ip)
|
||||
virt_id = sql.add_server(
|
||||
f'{vip}-VIP', vip, group_id, '1', '1', '0', cred_id, ssh_settings['port'],
|
||||
f'VRRP IP for {cluster_name} cluster', haproxy, nginx, apache, firewall
|
||||
)
|
||||
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')
|
|
@ -2,6 +2,7 @@ import os
|
|||
import json
|
||||
|
||||
from flask import render_template
|
||||
import ansible_runner
|
||||
|
||||
import modules.db.sql as sql
|
||||
import modules.service.common as service_common
|
||||
|
@ -12,12 +13,12 @@ from modules.server.ssh import return_ssh_keys_path
|
|||
|
||||
|
||||
def show_installation_output(error: str, output: str, service: str, rc=0):
|
||||
if error and "WARNING" not in error:
|
||||
if error.read() and "WARNING" not in error.read():
|
||||
roxywi_common.logging('Roxy-WI server', error, roxywi=1)
|
||||
raise Exception('error: ' + error)
|
||||
else:
|
||||
if rc != 0:
|
||||
for line in output:
|
||||
for line in output.read():
|
||||
if any(s in line for s in ("Traceback", "FAILED", "error", "ERROR", "UNREACHABLE")):
|
||||
try:
|
||||
correct_out = line.split('=>')
|
||||
|
@ -34,75 +35,6 @@ def show_success_installation(service):
|
|||
return render_template('include/show_success_installation.html', service=service, lang=lang)
|
||||
|
||||
|
||||
def install_haproxy(server_ip: str, api=0, **kwargs):
|
||||
script = "install_haproxy.sh"
|
||||
hap_sock_p = str(sql.get_setting('haproxy_sock_port'))
|
||||
stats_port = str(sql.get_setting('stats_port'))
|
||||
server_state_file = sql.get_setting('server_state_file')
|
||||
stats_user = sql.get_setting('stats_user')
|
||||
stats_password = sql.get_setting('stats_password')
|
||||
proxy = sql.get_setting('proxy')
|
||||
haproxy_dir = sql.get_setting('haproxy_dir')
|
||||
container_name = sql.get_setting('haproxy_container_name')
|
||||
haproxy_ver = kwargs.get('hapver')
|
||||
server_for_installing = kwargs.get('server')
|
||||
docker = kwargs.get('docker')
|
||||
m_or_s = kwargs.get('m_or_s')
|
||||
master = kwargs.get('master')
|
||||
slave = kwargs.get('slave')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(server_ip)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
|
||||
if haproxy_ver is None:
|
||||
haproxy_ver = '2.8.1-1'
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
|
||||
syn_flood_protect = '1' if kwargs.get('syn_flood') == "1" else ''
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} SOCK_PORT={hap_sock_p} STAT_PORT={stats_port} "
|
||||
f"STAT_FILE={server_state_file} DOCKER={docker} SSH_PORT={ssh_settings['port']} STATS_USER={stats_user} "
|
||||
f"CONT_NAME={container_name} HAP_DIR={haproxy_dir} STATS_PASS='{stats_password}' HAPVER={haproxy_ver} "
|
||||
f"SYN_FLOOD={syn_flood_protect} HOST={server_ip} USER={ssh_settings['user']} PASS='{ssh_settings['password']}' "
|
||||
f"M_OR_S={m_or_s} MASTER={master} SLAVE={slave} KEY={ssh_settings['key']}"
|
||||
]
|
||||
|
||||
if server_for_installing:
|
||||
service = server_for_installing + ' HAProxy'
|
||||
else:
|
||||
service = ' HAProxy'
|
||||
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], service, rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
try:
|
||||
sql.update_haproxy(server_ip)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
if docker == '1':
|
||||
server_id = sql.select_server_id_by_ip(server_ip)
|
||||
sql.insert_or_update_service_setting(server_id, 'haproxy', 'dockerized', '1')
|
||||
sql.insert_or_update_service_setting(server_id, 'haproxy', 'restart', '1')
|
||||
|
||||
try:
|
||||
os.remove(f'{full_path}/{script}')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not api:
|
||||
return show_success_installation(service)
|
||||
|
||||
|
||||
def waf_install(server_ip: str):
|
||||
script = "waf.sh"
|
||||
proxy = sql.get_setting('proxy')
|
||||
|
@ -179,77 +111,6 @@ def waf_nginx_install(server_ip: str):
|
|||
return show_success_installation(service)
|
||||
|
||||
|
||||
def install_service(server_ip: str, service: str, docker: str, syn_flood_protect: int, api=0, **kwargs) -> str:
|
||||
script = f"install_{service}.sh"
|
||||
stats_user = sql.get_setting(f'{service}_stats_user')
|
||||
stats_password = sql.get_setting(f'{service}_stats_password')
|
||||
stats_port = str(sql.get_setting(f'{service}_stats_port'))
|
||||
stats_page = sql.get_setting(f'{service}_stats_page')
|
||||
config_path = sql.get_setting(f'{service}_config_path')
|
||||
service_dir = sql.get_setting(f'{service}_dir')
|
||||
server_for_installing = kwargs.get('server')
|
||||
proxy = sql.get_setting('proxy')
|
||||
container_name = sql.get_setting(f'{service}_container_name')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(server_ip)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
|
||||
try:
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
except Exception as e:
|
||||
raise Exception(f'error: {e}')
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
|
||||
if service == 'apache':
|
||||
correct_service_name = service_common.get_correct_apache_service_name(server_ip=server_ip, server_id=None)
|
||||
if service_dir == '/etc/httpd' and correct_service_name == 'apache2':
|
||||
service_dir = '/etc/apache2'
|
||||
elif service_dir == '/etc/apache2' and correct_service_name == 'httpd':
|
||||
service_dir = '/etc/httpd'
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} STATS_USER={stats_user} STATS_PASS='{stats_password}' "
|
||||
f"SSH_PORT={ssh_settings['port']} CONFIG_PATH={config_path} CONT_NAME={container_name} STAT_PORT={stats_port} "
|
||||
f"STAT_PAGE={stats_page} SYN_FLOOD={syn_flood_protect} DOCKER={docker} service_dir={service_dir} HOST={server_ip} "
|
||||
f"USER={ssh_settings['user']} PASS='{ssh_settings['password']}' KEY={ssh_settings['key']}"
|
||||
]
|
||||
|
||||
if server_for_installing:
|
||||
service_name = f'{server_for_installing} {service.title()}'
|
||||
else:
|
||||
service_name = service.title()
|
||||
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], service_name, rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
if service == 'nginx':
|
||||
try:
|
||||
sql.update_nginx(server_ip)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
elif service == 'apache':
|
||||
try:
|
||||
sql.update_apache(server_ip)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
if docker == '1':
|
||||
server_id = sql.select_server_id_by_ip(server_ip)
|
||||
sql.insert_or_update_service_setting(server_id, service, 'dockerized', '1')
|
||||
sql.insert_or_update_service_setting(server_id, service, 'restart', '1')
|
||||
|
||||
os.remove(f'{full_path}/{script}')
|
||||
|
||||
if not api:
|
||||
return show_success_installation(service)
|
||||
|
||||
|
||||
def geoip_installation(serv, geoip_update, service):
|
||||
proxy = sql.get_setting('proxy')
|
||||
maxmind_key = sql.get_setting('maxmind_key')
|
||||
|
@ -322,165 +183,199 @@ def grafana_install():
|
|||
return f'success: Grafana and Prometheus servers were installed. You can find Grafana on http://{host}:3000<br>'
|
||||
|
||||
|
||||
def keepalived_master_install(
|
||||
master: str, eth: str, eth_slave: str, vrrp_ip: str, virt_server: int, syn_flood: int, return_to_master: int,
|
||||
haproxy: int, nginx: int, router_id: int, api=0
|
||||
) -> str:
|
||||
script = "install_keepalived.sh"
|
||||
proxy = sql.get_setting('proxy')
|
||||
def generate_kp_inv(json_data: json, install_service) -> object:
|
||||
json_data = json.loads(json_data)
|
||||
inv = {"server": {"hosts":{}}}
|
||||
server_ips = []
|
||||
cluster_id = int(json_data['cluster_id'])
|
||||
haproxy = json_data['services']['haproxy']['enabled']
|
||||
nginx = json_data['services']['nginx']['enabled']
|
||||
# apache = json_data['apache']
|
||||
apache = 0
|
||||
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(master)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
service = 'master Keepalived'
|
||||
syn_flood_protect = str(json_data['syn_flood'])
|
||||
routers = {}
|
||||
vips = sql.select_cluster_vips(cluster_id)
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
for vip in vips:
|
||||
router_id = str(vip.router_id)
|
||||
routers[router_id] = {vip.vip: {}}
|
||||
routers[router_id][vip.vip].setdefault('return_master', vip.return_master)
|
||||
routers[router_id][vip.vip].setdefault('vip', vip.vip)
|
||||
slaves = sql.select_cluster_slaves_for_inv(router_id)
|
||||
for slave in slaves:
|
||||
routers[router_id][vip.vip].setdefault('master', slave.master)
|
||||
routers[router_id][vip.vip].setdefault('eth', slave.eth)
|
||||
|
||||
try:
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
except Exception as e:
|
||||
raise Exception(f'error: {e}')
|
||||
for k, v in json_data['servers'].items():
|
||||
server_ip = v['ip']
|
||||
inv['server']['hosts'][server_ip] = {
|
||||
"HAPROXY": haproxy,
|
||||
"NGINX": nginx,
|
||||
"APACHE": apache,
|
||||
"RESTART": 1,
|
||||
"SYN_FLOOD": syn_flood_protect,
|
||||
"keepalived_path_logs": keepalived_path_logs,
|
||||
"routers": routers
|
||||
}
|
||||
server_ips.append(server_ip)
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} SSH_PORT={ssh_settings['port']} router_id={router_id} "
|
||||
f"ETH={eth} IP={vrrp_ip} MASTER=MASTER ETH_SLAVE={eth_slave} keepalived_path_logs={keepalived_path_logs} "
|
||||
f"RETURN_TO_MASTER={return_to_master} SYN_FLOOD={syn_flood} HOST={master} HAPROXY={haproxy} NGINX={nginx} "
|
||||
f"USER={ssh_settings['user']} PASS='{ssh_settings['password']}' KEY={ssh_settings['key']}"
|
||||
]
|
||||
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], service, rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(f'error: read output: {e}')
|
||||
|
||||
try:
|
||||
sql.update_keepalived(master)
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
if virt_server:
|
||||
group_id = sql.get_group_id_by_server_ip(master)
|
||||
cred_id = sql.get_cred_id_by_server_ip(master)
|
||||
hostname = sql.get_hostname_by_server_ip(master)
|
||||
firewall = 1 if server_mod.is_service_active(master, 'firewalld') else 0
|
||||
sql.add_server(
|
||||
hostname + '-VIP', vrrp_ip, group_id, '1', '1', '0', cred_id, ssh_settings['port'], f'VRRP IP for {master}',
|
||||
haproxy, nginx, '0', firewall
|
||||
)
|
||||
|
||||
if not api:
|
||||
return show_success_installation(service)
|
||||
return inv, server_ips
|
||||
|
||||
|
||||
def keepalived_slave_install(
|
||||
master: str, slave: str, eth: str, eth_slave: str, vrrp_ip: str, syn_flood: int, haproxy: int, nginx: int, router_id: int, api=0
|
||||
) -> str:
|
||||
script = "install_keepalived.sh"
|
||||
def generate_haproxy_inv(json_data: json, install_service: str) -> object:
|
||||
json_data = json.loads(json_data)
|
||||
inv = {"server": {"hosts": {}}}
|
||||
slaves = []
|
||||
server_ips = []
|
||||
master_ip = 0
|
||||
hap_sock_p = str(sql.get_setting('haproxy_sock_port'))
|
||||
stats_port = str(sql.get_setting('stats_port'))
|
||||
server_state_file = sql.get_setting('server_state_file')
|
||||
stats_user = sql.get_setting('stats_user')
|
||||
stats_password = sql.get_setting('stats_password')
|
||||
haproxy_dir = sql.get_setting('haproxy_dir')
|
||||
container_name = sql.get_setting('haproxy_container_name')
|
||||
haproxy_ver = ''
|
||||
is_docker = json_data['services']['haproxy']['docker']
|
||||
|
||||
if haproxy_ver == '':
|
||||
haproxy_ver = '2.8.1-1'
|
||||
|
||||
for k, v in json_data['servers'].items():
|
||||
if not v['master']:
|
||||
slaves.append(v['ip'])
|
||||
else:
|
||||
master_ip = v['ip']
|
||||
|
||||
for k, v in json_data['servers'].items():
|
||||
server_ip = v['ip']
|
||||
is_master = v['master']
|
||||
|
||||
if 'version' in v:
|
||||
haproxy_ver = v['version']
|
||||
|
||||
inv['server']['hosts'][server_ip] = {
|
||||
"SOCK_PORT": hap_sock_p,
|
||||
"STAT_PORT": stats_port,
|
||||
"STAT_FILE": server_state_file,
|
||||
"STATS_USER": stats_user,
|
||||
"CONT_NAME": container_name,
|
||||
"HAP_DIR": haproxy_dir,
|
||||
"STATS_PASS": stats_password,
|
||||
"HAPVER": haproxy_ver,
|
||||
"SYN_FLOOD": '0',
|
||||
"M_OR_S": is_master,
|
||||
"MASTER": master_ip,
|
||||
"slaves": slaves,
|
||||
"DOCKER": is_docker
|
||||
}
|
||||
server_ips.append(server_ip)
|
||||
|
||||
return inv, server_ips
|
||||
|
||||
|
||||
def generate_service_inv(json_data: json, install_service: str) -> object:
|
||||
json_data = json.loads(json_data)
|
||||
inv = {"server": {"hosts": {}}}
|
||||
server_ips = []
|
||||
stats_user = sql.get_setting(f'{install_service}_stats_user')
|
||||
stats_password = sql.get_setting(f'{install_service}_stats_password')
|
||||
stats_port = str(sql.get_setting(f'{install_service}_stats_port'))
|
||||
stats_page = sql.get_setting(f'{install_service}_stats_page')
|
||||
config_path = sql.get_setting(f'{install_service}_config_path')
|
||||
service_dir = sql.get_setting(f'{install_service}_dir')
|
||||
container_name = sql.get_setting(f'{install_service}_container_name')
|
||||
is_docker = json_data['services'][install_service]['docker']
|
||||
|
||||
if install_service == 'nginx':
|
||||
os.system('ansible-galaxy collection install community.general')
|
||||
os.system('ansible-galaxy install nginxinc.nginx,0.23.2 --roles-path /var/www/haproxy-wi/app/scripts/ansible/roles/')
|
||||
|
||||
for k, v in json_data['servers'].items():
|
||||
server_ip = v['ip']
|
||||
if install_service == 'apache':
|
||||
correct_service_name = service_common.get_correct_apache_service_name(server_ip=server_ip, server_id=None)
|
||||
if service_dir == '/etc/httpd' and correct_service_name == 'apache2':
|
||||
service_dir = '/etc/apache2'
|
||||
elif service_dir == '/etc/apache2' and correct_service_name == 'httpd':
|
||||
service_dir = '/etc/httpd'
|
||||
|
||||
inv['server']['hosts'][server_ip] = {
|
||||
"STAT_PORT": stats_port,
|
||||
"DOCKER": is_docker,
|
||||
"STATS_USER": stats_user,
|
||||
"CONT_NAME": container_name,
|
||||
"STATS_PASS": stats_password,
|
||||
"service_dir": service_dir,
|
||||
"SYN_FLOOD": "0",
|
||||
"CONFIG_PATH": config_path,
|
||||
"STAT_PAGE": stats_page,
|
||||
"service": install_service,
|
||||
}
|
||||
server_ips.append(server_ip)
|
||||
|
||||
return inv, server_ips
|
||||
|
||||
|
||||
def run_ansible(inv: object, server_ips: str, ansible_role: str, service: str) -> object:
|
||||
inventory = f'/var/www/haproxy-wi/app/scripts/ansible/inventory/{ansible_role}.json'
|
||||
proxy = sql.get_setting('proxy')
|
||||
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(slave)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
service = 'slave Keepalived'
|
||||
tags = ''
|
||||
for server_ip in server_ips:
|
||||
ssh_settings = return_ssh_keys_path(server_ip)
|
||||
inv['server']['hosts'][server_ip]['ansible_ssh_private_key_file'] = ssh_settings['key']
|
||||
inv['server']['hosts'][server_ip]['ansible_password'] = ssh_settings['password']
|
||||
inv['server']['hosts'][server_ip]['ansible_user'] = ssh_settings['user']
|
||||
inv['server']['hosts'][server_ip]['ansible_port'] = ssh_settings['port']
|
||||
inv['server']['hosts'][server_ip]['ansible_become'] = True
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
|
||||
inv['server']['hosts'][server_ip]['PROXY'] = proxy_serv
|
||||
|
||||
if 'DOCKER' in inv['server']['hosts'][server_ip]:
|
||||
if inv['server']['hosts'][server_ip]['DOCKER']:
|
||||
tags = 'docker'
|
||||
else:
|
||||
tags = 'system'
|
||||
|
||||
envvars = {
|
||||
'ANSIBLE_DISPLAY_OK_HOSTS': 'no',
|
||||
'ANSIBLE_SHOW_CUSTOM_STATS': 'no',
|
||||
'ANSIBLE_DISPLAY_SKIPPED_HOSTS': "no",
|
||||
'ANSIBLE_CALLBACK_PLUGINS': "/var/www/haproxy-wi/app/scripts/ansible/callback_plugins",
|
||||
'ANSIBLE_CALLBACKS_ENABLED': "roxywi",
|
||||
'ANSIBLE_STDOUT_CALLBACK': "roxywi",
|
||||
'ORIGINAL_STDOUT_CALLBACK': "roxywi",
|
||||
'ANSIBLE_HOST_KEY_CHECKING': "no",
|
||||
'ACTION_WARNINGS': "no",
|
||||
'LOCALHOST_WARNING': "no",
|
||||
'COMMAND_WARNINGS': "no",
|
||||
'AWX_DISPLAY': False,
|
||||
}
|
||||
|
||||
kwargs = {
|
||||
'private_data_dir': '/var/www/haproxy-wi/app/scripts/ansible/',
|
||||
'inventory': inventory,
|
||||
'envvars': envvars,
|
||||
'playbook': f'/var/www/haproxy-wi/app/scripts/ansible/roles/{ansible_role}.yml',
|
||||
'tags': tags
|
||||
}
|
||||
|
||||
if os.path.isfile(inventory):
|
||||
os.remove(inventory)
|
||||
|
||||
try:
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
with open(inventory, 'a') as invent:
|
||||
invent.write(str(inv))
|
||||
except Exception as e:
|
||||
raise Exception(f'error: {e}')
|
||||
raise Exception(f'error: Cannot save inventory file: {e}')
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} SSH_PORT={ssh_settings['port']} router_id={router_id} ETH={eth} "
|
||||
f"IP={vrrp_ip} MASTER=BACKUP ETH_SLAVE={eth_slave} SYN_FLOOD={syn_flood} keepalived_path_logs={keepalived_path_logs} HAPROXY={haproxy} "
|
||||
f"NGINX={nginx} HOST={slave} USER={ssh_settings['user']} PASS='{ssh_settings['password']}' KEY={ssh_settings['key']}"
|
||||
]
|
||||
result = ansible_runner.run(**kwargs)
|
||||
stats = result.stats
|
||||
|
||||
try:
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
except Exception as e:
|
||||
raise Exception(f'error: {e}')
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], service, rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(f'error: read output: {e}')
|
||||
|
||||
try:
|
||||
sql.update_server_master(master, slave)
|
||||
sql.update_keepalived(slave)
|
||||
except Exception as e:
|
||||
raise Exception(f'{e}')
|
||||
|
||||
try:
|
||||
os.remove(f'{full_path}/{script}')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not api:
|
||||
return show_success_installation(service)
|
||||
|
||||
|
||||
def keepalived_masteradd(master, eth, slave_eth, vrrp_ip, router_id, return_to_master, kp):
|
||||
script = "install_keepalived.sh"
|
||||
proxy = sql.get_setting('proxy')
|
||||
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(master)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} SSH_PORT={ssh_settings['port']} ETH={eth} ETH_SLAVE={slave_eth} "
|
||||
f"keepalived_path_logs={keepalived_path_logs} RETURN_TO_MASTER={return_to_master} IP={vrrp_ip} MASTER=MASTER "
|
||||
f"RESTART={kp} ADD_VRRP=1 HOST={master} router_id={router_id} USER={ssh_settings['user']} "
|
||||
f"PASS='{ssh_settings['password']}' KEY={ssh_settings['key']}"
|
||||
]
|
||||
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], 'master VRRP address', rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
return show_success_installation('master VRRP address')
|
||||
|
||||
|
||||
def keepalived_slaveadd(slave, eth, slave_eth, vrrp_ip, router_id, kp):
|
||||
script = "install_keepalived.sh"
|
||||
proxy = sql.get_setting('proxy')
|
||||
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
|
||||
proxy_serv = ''
|
||||
ssh_settings = return_ssh_keys_path(slave)
|
||||
full_path = '/var/www/haproxy-wi/app'
|
||||
|
||||
if proxy is not None and proxy != '' and proxy != 'None':
|
||||
proxy_serv = proxy
|
||||
|
||||
os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
|
||||
|
||||
commands = [
|
||||
f"chmod +x {full_path}/{script} && {full_path}/{script} PROXY={proxy_serv} SSH_PORT={ssh_settings['port']} ETH={eth} ETH_SLAVE={slave_eth} "
|
||||
f"keepalived_path_logs={keepalived_path_logs} IP={vrrp_ip} MASTER=BACKUP RESTART={kp} ADD_VRRP=1 HOST={slave} "
|
||||
f"router_id={router_id} USER={ssh_settings['user']} PASS='{ssh_settings['password']}' KEY={ssh_settings['key']}"
|
||||
]
|
||||
|
||||
return_out = server_mod.subprocess_execute_with_rc(commands[0])
|
||||
|
||||
try:
|
||||
show_installation_output(return_out['error'], return_out['output'], 'slave VRRP address', rc=return_out['rc'])
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
os.remove(f'{full_path}/{script}')
|
||||
|
||||
return show_success_installation('slave VRRP address')
|
||||
os.remove(inventory)
|
||||
return stats
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import app.modules.server.server as server_mod
|
||||
|
||||
|
||||
def get_status(server_ip: str) -> tuple:
|
||||
out1 = []
|
||||
h = (['', ''],)
|
||||
try:
|
||||
cmd = [
|
||||
"/usr/sbin/keepalived -v 2>&1|head -1|awk '{print $2}' && systemctl status keepalived |"
|
||||
"grep -e 'Active' |awk '{print $2, $9$10$11$12$13}' && ps ax |grep keepalived|grep -v grep |wc -l"
|
||||
]
|
||||
out = server_mod.ssh_command(server_ip, cmd)
|
||||
for k in out.split():
|
||||
out1.append(k)
|
||||
h = (out1,)
|
||||
servers_with_status1= h
|
||||
servers_with_status2= h
|
||||
except Exception:
|
||||
servers_with_status1 = h
|
||||
servers_with_status2 = h
|
||||
|
||||
return servers_with_status1, servers_with_status2
|
|
@ -0,0 +1,5 @@
|
|||
from flask import Blueprint
|
||||
|
||||
bp = Blueprint('ha', __name__)
|
||||
|
||||
from app.routes.ha import routes
|
|
@ -0,0 +1,296 @@
|
|||
import json
|
||||
|
||||
from flask import render_template, g, request, jsonify
|
||||
from flask_login import login_required
|
||||
|
||||
from app import app
|
||||
from app.routes.ha import bp
|
||||
from middleware import get_user_params, check_services
|
||||
import modules.db.sql as sql
|
||||
import app.modules.common.common as common
|
||||
import modules.server.server as server_mod
|
||||
import modules.roxywi.common as roxywi_common
|
||||
import modules.service.keepalived as keepalived
|
||||
import modules.service.ha_cluster as ha_cluster
|
||||
import modules.service.installation as installation
|
||||
|
||||
|
||||
@bp.before_request
|
||||
@login_required
|
||||
def before_request():
|
||||
""" Protect all of the admin endpoints. """
|
||||
pass
|
||||
|
||||
|
||||
@bp.route('/<service>', methods=['GET', 'POST', 'PUT', 'DELETE'])
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def cluster_function(service):
|
||||
user_params = g.user_params
|
||||
group_id = user_params['group_id']
|
||||
if request.method == 'GET':
|
||||
clusters = sql.select_clusters(group_id)
|
||||
is_needed_tool = common.is_tool('ansible')
|
||||
user_subscription = roxywi_common.return_user_subscription()
|
||||
|
||||
return render_template(
|
||||
'ha_cluster.html', role=user_params['role'], user=user_params['user'], clusters=clusters, is_needed_tool=is_needed_tool,
|
||||
user_services=user_params['user_services'], token=user_params['token'], lang=user_params['lang'], user_subscription=user_subscription
|
||||
)
|
||||
elif request.method == 'PUT':
|
||||
cluster = json.loads(request.form.get('jsonData'))
|
||||
|
||||
try:
|
||||
return ha_cluster.update_cluster(cluster, group_id)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
elif request.method == 'POST':
|
||||
cluster = json.loads(request.form.get('jsonData'))
|
||||
|
||||
try:
|
||||
return ha_cluster.create_cluster(cluster, group_id)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
elif request.method == 'DELETE':
|
||||
cluster_id = int(request.form.get('cluster_id'))
|
||||
try:
|
||||
return ha_cluster.delete_cluster(cluster_id)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
|
||||
|
||||
@bp.route('/<service>/get/<int:cluster_id>')
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def get_ha_cluster(service, cluster_id):
|
||||
user_params = g.user_params
|
||||
group_id = user_params['group_id']
|
||||
clusters = sql.select_cluster(cluster_id)
|
||||
router_id = sql.get_router_id(cluster_id, default_router=1)
|
||||
slaves = sql.select_cluster_slaves(cluster_id, router_id)
|
||||
virts = sql.select_clusters_virts()
|
||||
vips = sql.select_cluster_vips(cluster_id)
|
||||
servers = roxywi_common.get_dick_permit(virt=1)
|
||||
cluster_services = sql.select_cluster_services(cluster_id)
|
||||
services = sql.select_services()
|
||||
|
||||
return render_template(
|
||||
'ajax/ha/clusters.html', role=user_params['role'], user=user_params['user'], servers=servers,
|
||||
user_services=user_params['user_services'], token=user_params['token'], lang=user_params['lang'],
|
||||
clusters=clusters, slaves=slaves, virts=virts, vips=vips, cluster_services=cluster_services, services=services,
|
||||
group_id=group_id, router_id=router_id
|
||||
)
|
||||
|
||||
|
||||
@bp.route('/<service>/settings/<int:cluster_id>')
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def get_cluster_settings(service, cluster_id):
|
||||
settings = {}
|
||||
clusters = sql.select_cluster(cluster_id)
|
||||
router_id = sql.get_router_id(cluster_id, default_router=1)
|
||||
slaves = sql.select_cluster_slaves(cluster_id, router_id)
|
||||
cluster_services = sql.select_cluster_services(cluster_id)
|
||||
vip = sql.select_clusters_vip(cluster_id, router_id)
|
||||
return_master = sql.select_clusters_vip_return_master(cluster_id, router_id)
|
||||
vip_id = sql.select_clusters_vip_id(cluster_id, router_id)
|
||||
is_virt = sql.check_ha_virt(vip_id)
|
||||
for cluster in clusters:
|
||||
settings.setdefault('name', cluster.name)
|
||||
settings.setdefault('desc', cluster.desc)
|
||||
settings.setdefault('return_to_master', return_master)
|
||||
settings.setdefault('syn_flood', cluster.syn_flood)
|
||||
settings.setdefault('vip', vip)
|
||||
settings.setdefault('virt_server', is_virt)
|
||||
|
||||
for slave in slaves:
|
||||
if slave[31]:
|
||||
settings.setdefault('eth', slave[32])
|
||||
|
||||
for c_s in cluster_services:
|
||||
if int(c_s.service_id) == 1:
|
||||
settings.setdefault('haproxy', 1)
|
||||
elif int(c_s.service_id) == 2:
|
||||
settings.setdefault('nginx', 1)
|
||||
elif int(c_s.service_id) == 4:
|
||||
settings.setdefault('apache', 1)
|
||||
|
||||
return jsonify(settings)
|
||||
|
||||
|
||||
@bp.route('/<service>/<int:cluster_id>')
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def show_ha_cluster(service, cluster_id):
|
||||
user_params = g.user_params
|
||||
services = []
|
||||
service = 'keepalived'
|
||||
service_desc = sql.select_service(service)
|
||||
servers = sql.select_cluster_master_slaves(cluster_id, user_params['group_id'])
|
||||
waf_server = ''
|
||||
cmd = "ps ax |grep -e 'keep_alive.py' |grep -v grep |wc -l"
|
||||
keep_alive, stderr = server_mod.subprocess_execute(cmd)
|
||||
servers_with_status1 = []
|
||||
restart_settings = sql.select_restart_services_settings(service_desc.slug)
|
||||
for s in servers:
|
||||
servers_with_status = list()
|
||||
servers_with_status.append(s[0])
|
||||
servers_with_status.append(s[1])
|
||||
servers_with_status.append(s[2])
|
||||
servers_with_status.append(s[11])
|
||||
status1, status2 = keepalived.get_status(s[2])
|
||||
servers_with_status.append(status1)
|
||||
servers_with_status.append(status2)
|
||||
servers_with_status.append(s[22])
|
||||
servers_with_status.append(sql.is_master(s[2]))
|
||||
servers_with_status.append(sql.select_servers(server=s[2]))
|
||||
|
||||
is_keepalived = sql.select_keepalived(s[2])
|
||||
|
||||
if is_keepalived:
|
||||
try:
|
||||
cmd = ['sudo kill -USR1 `cat /var/run/keepalived.pid` && sudo grep State /tmp/keepalived.data -m 1 |'
|
||||
'awk -F"=" \'{print $2}\'|tr -d \'[:space:]\' && sudo rm -f /tmp/keepalived.data']
|
||||
out = server_mod.ssh_command(s[2], cmd)
|
||||
out1 = ('1', out)
|
||||
servers_with_status.append(out1)
|
||||
except Exception as e:
|
||||
servers_with_status.append(str(e))
|
||||
else:
|
||||
servers_with_status.append('')
|
||||
|
||||
servers_with_status1.append(servers_with_status)
|
||||
|
||||
user_subscription = roxywi_common.return_user_subscription()
|
||||
|
||||
return render_template(
|
||||
'service.html', role=user_params['role'], user=user_params['user'],
|
||||
servers=servers_with_status1, keep_alive=''.join(keep_alive), service=service, services=services,
|
||||
user_services=user_params['user_services'], user_status=user_subscription['user_status'],
|
||||
user_plan=user_subscription['user_plan'], waf_server=waf_server, restart_settings=restart_settings,
|
||||
service_desc=service_desc, token=user_params['token'], lang=user_params['lang']
|
||||
)
|
||||
|
||||
|
||||
@bp.route('/<service>/slaves/<int:cluster_id>', methods=['GET', 'POST'])
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def get_slaves(service, cluster_id):
|
||||
lang = g.user_params['lang']
|
||||
if request.method == 'GET':
|
||||
router_id = sql.get_router_id(cluster_id, default_router=1)
|
||||
else:
|
||||
router_id = int(request.form.get('router_id'))
|
||||
slaves = sql.select_cluster_slaves(cluster_id, router_id)
|
||||
|
||||
return render_template('ajax/ha/add_vip_slaves.html', lang=lang, slaves=slaves)
|
||||
|
||||
|
||||
@bp.route('/<service>/slaves/servers/<int:cluster_id>')
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def get_server_slaves(service, cluster_id):
|
||||
group_id = g.user_params['group_id']
|
||||
lang = g.user_params['lang']
|
||||
try:
|
||||
router_id = sql.get_router_id(cluster_id, default_router=1)
|
||||
slaves = sql.select_cluster_slaves(cluster_id, router_id)
|
||||
except Exception:
|
||||
slaves = ''
|
||||
free_servers = sql.select_ha_cluster_not_masters_not_slaves(group_id)
|
||||
|
||||
return render_template('ajax/ha/slave_servers.html', free_servers=free_servers, slaves=slaves, lang=lang)
|
||||
|
||||
|
||||
@bp.route('/<service>/masters')
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def get_masters(service):
|
||||
group_id = g.user_params['group_id']
|
||||
free_servers = sql.select_ha_cluster_not_masters_not_slaves(group_id)
|
||||
|
||||
return render_template('ajax/ha/masters.html', free_servers=free_servers)
|
||||
|
||||
|
||||
@bp.route('/<service>/settings/<int:cluster_id>/vip/<int:router_id>')
|
||||
@check_services
|
||||
def get_vip_settings(service, cluster_id, router_id):
|
||||
settings = {}
|
||||
return_master = sql.select_clusters_vip_return_master(cluster_id, router_id)
|
||||
vip_id = sql.select_clusters_vip_id(cluster_id, router_id)
|
||||
is_virt = sql.check_ha_virt(vip_id)
|
||||
settings.setdefault('return_to_master', return_master)
|
||||
settings.setdefault('virt_server', is_virt)
|
||||
return jsonify(settings)
|
||||
|
||||
|
||||
@bp.route('/<service>/<int:cluster_id>/vip', methods=['POST', 'PUT', 'DELETE'])
|
||||
@check_services
|
||||
@get_user_params()
|
||||
def ha_vip(service, cluster_id):
|
||||
user_params = g.user_params
|
||||
group_id = user_params['group_id']
|
||||
json_data = json.loads(request.form.get('jsonData'))
|
||||
if request.method == 'PUT':
|
||||
router_id = int(json_data['router_id'])
|
||||
try:
|
||||
ha_cluster.update_vip(cluster_id, router_id, json_data, group_id)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
return 'ok'
|
||||
elif request.method == 'POST':
|
||||
try:
|
||||
ha_cluster.insert_vip(cluster_id, json_data, group_id)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
|
||||
return 'ok'
|
||||
elif request.method == 'DELETE':
|
||||
router_id = int(json_data['router_id'])
|
||||
try:
|
||||
sql.delete_ha_router(router_id)
|
||||
return 'ok'
|
||||
except Exception as e:
|
||||
return f'error: Cannot delete VIP: {e}'
|
||||
|
||||
|
||||
@bp.route('/<service>/reconfigure/<install_service>', methods=['PUT'])
|
||||
@check_services
|
||||
def reconfigure_haproxy(service, install_service):
|
||||
json_data = request.form.get('jsonData')
|
||||
update_functions = {
|
||||
'haproxy': sql.update_haproxy,
|
||||
'nginx': sql.update_nginx,
|
||||
'apache': sql.update_apache,
|
||||
}
|
||||
generate_functions = {
|
||||
'haproxy': installation.generate_haproxy_inv,
|
||||
'nginx': installation.generate_service_inv,
|
||||
'apache': installation.generate_service_inv,
|
||||
'keepalived': installation.generate_kp_inv,
|
||||
}
|
||||
inv, server_ips = generate_functions[install_service](json_data, install_service)
|
||||
json_data = json.loads(json_data)
|
||||
is_docker = None
|
||||
|
||||
if install_service == 'keepalived':
|
||||
nice_service_name = 'HA cluster'
|
||||
else:
|
||||
service_desc = sql.select_service(install_service)
|
||||
nice_service_name = service_desc.service
|
||||
is_docker = json_data['services'][install_service]['docker']
|
||||
|
||||
for server_ip in server_ips:
|
||||
if install_service == 'keepalived':
|
||||
continue
|
||||
try:
|
||||
update_functions[install_service](server_ip)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
if is_docker == '1':
|
||||
server_id = sql.select_server_id_by_ip(server_ip)
|
||||
sql.insert_or_update_service_setting(server_id, install_service, 'dockerized', '1')
|
||||
sql.insert_or_update_service_setting(server_id, install_service, 'restart', '1')
|
||||
|
||||
return installation.run_ansible(inv, server_ips, install_service, nice_service_name), 201
|
|
@ -2,7 +2,7 @@ from flask import render_template, request, g, abort
|
|||
from flask_login import login_required
|
||||
|
||||
from app.routes.install import bp
|
||||
from middleware import get_user_params
|
||||
from middleware import get_user_params, check_services
|
||||
import app.modules.db.sql as sql
|
||||
import app.modules.common.common as common
|
||||
import app.modules.roxywi.auth as roxywi_auth
|
||||
|
@ -36,135 +36,20 @@ def install_monitoring():
|
|||
)
|
||||
|
||||
|
||||
@bp.route('/ha')
|
||||
@get_user_params()
|
||||
def ha():
|
||||
if not roxywi_auth.is_access_permit_to_service('keepalived'):
|
||||
abort(403, 'You do not have needed permissions to access to Keepalived service')
|
||||
roxywi_auth.page_for_admin(level=2)
|
||||
|
||||
user_params = g.user_params
|
||||
is_needed_tool = common.is_tool('ansible')
|
||||
user_subscription = roxywi_common.return_user_subscription()
|
||||
|
||||
return render_template(
|
||||
'ha.html', h2=1, role=user_params['role'], user=user_params['user'], selects=user_params['servers'],
|
||||
user_services=user_params['user_services'], user_status=user_subscription['user_status'], lang=user_params['lang'],
|
||||
user_plan=user_subscription['user_plan'], is_needed_tool=is_needed_tool, token=user_params['token']
|
||||
)
|
||||
|
||||
|
||||
@bp.post('/keepalived', defaults={'slave_kp': None})
|
||||
@bp.post('/keepalived/<slave_kp>')
|
||||
def install_keepalived(slave_kp):
|
||||
master = request.form.get('master')
|
||||
slave = request.form.get('slave')
|
||||
eth = request.form.get('interface')
|
||||
eth_slave = request.form.get('slave_interface')
|
||||
vrrp_ip = request.form.get('vrrpip')
|
||||
syn_flood = request.form.get('syn_flood')
|
||||
return_to_master = request.form.get('return_to_master')
|
||||
haproxy = request.form.get('hap')
|
||||
nginx = request.form.get('nginx')
|
||||
router_id = request.form.get('router_id')
|
||||
virt_server = request.form.get('virt_server')
|
||||
|
||||
@bp.post('/<service>')
|
||||
@check_services
|
||||
def install_service(service):
|
||||
try:
|
||||
virt_server = int(virt_server)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not slave_kp:
|
||||
try:
|
||||
return service_mod.keepalived_master_install(
|
||||
master, eth, eth_slave, vrrp_ip, virt_server, syn_flood, return_to_master, haproxy, nginx, router_id
|
||||
)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
else:
|
||||
try:
|
||||
return service_mod.keepalived_slave_install(
|
||||
master, slave, eth, eth_slave, vrrp_ip, syn_flood, haproxy, nginx, router_id
|
||||
)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
|
||||
|
||||
@bp.post('/keepalived/add', defaults={'slave_kp': None})
|
||||
@bp.post('/keepalived/add/<slave_kp>')
|
||||
def add_extra_vrrp(slave_kp):
|
||||
master = request.form.get('master')
|
||||
slave = request.form.get('slave')
|
||||
eth = request.form.get('interface')
|
||||
slave_eth = request.form.get('slave_interface')
|
||||
vrrp_ip = request.form.get('vrrpip')
|
||||
router_id = request.form.get('router_id')
|
||||
return_to_master = request.form.get('return_to_master')
|
||||
kp = request.form.get('kp')
|
||||
|
||||
if not slave_kp:
|
||||
try:
|
||||
return service_mod.keepalived_masteradd(master, eth, slave_eth, vrrp_ip, router_id, return_to_master, kp)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
else:
|
||||
try:
|
||||
return service_mod.keepalived_slaveadd(slave, eth, slave_eth, vrrp_ip, router_id, kp)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
|
||||
|
||||
@bp.post('/<service>/<server_ip>')
|
||||
def install_service(service, server_ip):
|
||||
server_ip = common.is_ip_or_dns(server_ip)
|
||||
docker = common.checkAjaxInput(request.form.get('docker'))
|
||||
syn_flood = request.form.get('syn_flood')
|
||||
hapver = request.form.get('hapver')
|
||||
|
||||
if service in ('nginx', 'apache'):
|
||||
try:
|
||||
return service_mod.install_service(server_ip, service, docker, syn_flood)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
elif service == 'haproxy':
|
||||
try:
|
||||
return service_mod.install_haproxy(server_ip, syn_flood=syn_flood, hapver=hapver, docker=docker)
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
else:
|
||||
return 'warning: Wrong service'
|
||||
|
||||
|
||||
@bp.post('/<service>/master-slave')
|
||||
def master_slave(service):
|
||||
master = request.form.get('master')
|
||||
slave = request.form.get('slave')
|
||||
server = request.form.get('server')
|
||||
docker = request.form.get('docker')
|
||||
|
||||
if service == 'haproxy':
|
||||
if server == 'master':
|
||||
try:
|
||||
return service_mod.install_haproxy(master, server=server, docker=docker, m_or_s='master', master=master, slave=slave)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
elif server == 'slave':
|
||||
try:
|
||||
return service_mod.install_haproxy(slave, server=server, docker=docker, m_or_s='slave', master=master, slave=slave)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
elif service == 'nginx':
|
||||
syn_flood_protect = '1' if request.form.get('syn_flood') == "1" else ''
|
||||
if server == 'master':
|
||||
try:
|
||||
return service_mod.install_service(master, 'nginx', docker, syn_flood_protect, server=server)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
elif server == 'slave':
|
||||
try:
|
||||
return service_mod.install_service(slave, 'nginx', docker, syn_flood_protect, server=server)
|
||||
except Exception as e:
|
||||
return f'{e}'
|
||||
json_data = request.form.get('jsonData')
|
||||
generate_functions = {
|
||||
'haproxy': service_mod.generate_haproxy_inv,
|
||||
'nginx': service_mod.generate_service_inv,
|
||||
'apache': service_mod.generate_service_inv,
|
||||
}
|
||||
inv, server_ips = generate_functions[service](json_data, service)
|
||||
return service_mod.run_ansible(inv, server_ips, service, service), 201
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
@bp.route('/<service>/version/<server_ip>')
|
||||
|
|
|
@ -151,11 +151,14 @@ def service_history(service, server_ip):
|
|||
user_subscription = roxywi_common.return_user_subscription()
|
||||
user_params = g.user_params
|
||||
|
||||
if service in ('haproxy', 'nginx', 'keepalived', 'apache'):
|
||||
if service in ('haproxy', 'nginx', 'keepalived', 'apache', 'cluster'):
|
||||
service_desc = sql.select_service(service)
|
||||
if not roxywi_auth.is_access_permit_to_service(service_desc.slug):
|
||||
abort(403, f'You do not have needed permissions to access to {service_desc.slug.title()} service')
|
||||
server_id = sql.select_server_id_by_ip(server_ip)
|
||||
if service == 'cluster':
|
||||
server_id = server_ip
|
||||
else:
|
||||
server_id = sql.select_server_id_by_ip(server_ip)
|
||||
history = sql.select_action_history_by_server_id_and_service(server_id, service_desc.service)
|
||||
elif service == 'server':
|
||||
if roxywi_common.check_is_server_in_group(server_ip):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
- name: Install common role
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
|
@ -15,7 +15,7 @@
|
|||
- docker
|
||||
|
||||
- name: Install docker
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
roles:
|
||||
|
@ -34,7 +34,7 @@
|
|||
- docker
|
||||
|
||||
- name: Install system role
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
tasks:
|
||||
|
@ -50,7 +50,7 @@
|
|||
- system
|
||||
|
||||
- name: "Set {{ ansible_user }} owner to {{ service_dir }}"
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: no
|
||||
tasks:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
- name: Install HAProxy as a service
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
|
@ -14,7 +14,7 @@
|
|||
- system
|
||||
|
||||
- name: Install HAProxy as a Docker
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Set SSH port
|
||||
set_fact:
|
||||
ansible_port: "{{SSH_PORT}}"
|
||||
#- name: Set SSH port
|
||||
# set_fact:
|
||||
# ansible_port: "{{SSH_PORT}}"
|
||||
|
||||
- name: check if HAProxy is installed
|
||||
package_facts:
|
||||
|
|
|
@ -43,10 +43,14 @@ listen stats
|
|||
peers default_peers
|
||||
{% if M_OR_S == 'master' %}
|
||||
peer {{ ansible_hostname }} {{MASTER}}:10000
|
||||
peer slave_lb {{SLAVE}}:10000
|
||||
{% for slave in slaves %}
|
||||
peer slave_lb {{slave}}:10000
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
peer master_lb {{MASTER}}:10000
|
||||
peer {{ ansible_hostname }} {{SLAVE}}:10000
|
||||
{% for slave in slaves %}
|
||||
peer {{ ansible_hostname }} {{slave}}:10000
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/var/log/haproxy.log {
|
||||
/var/log/haproxy/access.log {
|
||||
daily
|
||||
rotate 10
|
||||
missingok
|
||||
|
@ -9,4 +9,30 @@
|
|||
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
/bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
endscript
|
||||
}
|
||||
}
|
||||
|
||||
/var/log/haproxy/error.log {
|
||||
daily
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
sharedscripts
|
||||
postrotate
|
||||
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
/bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
endscript
|
||||
}
|
||||
|
||||
/var/log/haproxy/status.log {
|
||||
daily
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
sharedscripts
|
||||
postrotate
|
||||
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
/bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
|
||||
endscript
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- hosts: "{{ variable_host }}"
|
||||
- hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
- name: Creation config from template
|
||||
template:
|
||||
src: add_vrrp.conf.j2
|
||||
dest: /etc/keepalived/keepalived.conf_temp
|
||||
mode: 0644
|
||||
force: no
|
||||
|
||||
|
||||
- name: "Append keepalived.conf with content from temporary file"
|
||||
shell: cat keepalived.conf_temp >> keepalived.conf
|
||||
args:
|
||||
chdir: "/etc/keepalived/"
|
||||
|
||||
|
||||
- name: "Delete temporary file"
|
||||
file:
|
||||
path: /etc/keepalived/keepalived.conf_temp
|
||||
state: absent
|
||||
|
||||
|
||||
- name: Restart service keepalived
|
||||
service:
|
||||
name: keepalived
|
||||
state: restarted
|
||||
force: no
|
||||
ignore_errors: yes
|
||||
when: (RESTART is defined) and (RESTART|length > 0)
|
|
@ -1,111 +0,0 @@
|
|||
---
|
||||
- name: check if Keepalived is installed
|
||||
package_facts:
|
||||
manager: "auto"
|
||||
|
||||
- name: install EPEL Repository
|
||||
yum:
|
||||
name: epel-release
|
||||
state: latest
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
- ansible_facts['distribution_major_version'] == '7'
|
||||
ignore_errors: yes
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
- name: Creates log directory
|
||||
file:
|
||||
path: "{{keepalived_path_logs}}"
|
||||
state: directory
|
||||
|
||||
- name: Copy keepalived configuration for rsyslog.
|
||||
template:
|
||||
src: rsyslog.conf.j2
|
||||
dest: /etc/rsyslog.d/50-keepalived.conf
|
||||
mode: 0644
|
||||
notify: restart rsyslog
|
||||
|
||||
- name: Install the latest version of Keepalived
|
||||
package:
|
||||
name:
|
||||
- keepalived
|
||||
- psmisc
|
||||
state: present
|
||||
when: "'keepalived' not in ansible_facts.packages"
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
|
||||
- name: Ensure group "keepalived_script" exists
|
||||
group:
|
||||
name: keepalived_script
|
||||
state: present
|
||||
system: yes
|
||||
|
||||
|
||||
- name: Add the user 'keepalived_script'
|
||||
user:
|
||||
name: keepalived_script
|
||||
comment: User for keepalived_script
|
||||
group: keepalived_script
|
||||
shell: /sbin/nologin
|
||||
create_home: no
|
||||
system: yes
|
||||
|
||||
|
||||
- name: Copy keepalived configuration in place.
|
||||
template:
|
||||
src: keepalived.conf.j2
|
||||
dest: /etc/keepalived/keepalived.conf
|
||||
mode: 0644
|
||||
|
||||
- name: test to see if selinux is running
|
||||
command: getenforce
|
||||
register: sestatus
|
||||
changed_when: false
|
||||
when: (ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS')
|
||||
|
||||
|
||||
- name: Disble SELINUX in config
|
||||
template:
|
||||
src: ../../haproxy/templates/selinux.j2
|
||||
dest: /etc/selinux/config
|
||||
ignore_errors: yes
|
||||
when:
|
||||
- sestatus.stdout is defined
|
||||
- '"Enforcing" in sestatus.stdout'
|
||||
|
||||
|
||||
- name: Disble SELINUX in env
|
||||
shell: setenforce 0 2> /dev/null
|
||||
ignore_errors: yes
|
||||
debugger: never
|
||||
when:
|
||||
- sestatus.stdout is defined
|
||||
- '"Enforcing" in sestatus.stdout'
|
||||
|
||||
|
||||
- name: Enable and start service keepalived
|
||||
service:
|
||||
name: keepalived
|
||||
daemon_reload: yes
|
||||
state: started
|
||||
enabled: yes
|
||||
ignore_errors: yes
|
||||
|
||||
|
||||
- name: Enable net.ipv4.ip_forward
|
||||
sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
sysctl_set: yes
|
||||
state: present
|
||||
reload: yes
|
||||
|
||||
|
||||
- name: Add syn_flood tasks
|
||||
include: ../../haproxy/tasks/syn_flood.yml
|
||||
when: (SYN_FLOOD is defined) and (SYN_FLOOD|length > 0)
|
|
@ -1,13 +1,111 @@
|
|||
---
|
||||
- name: Set SSH port
|
||||
set_fact:
|
||||
ansible_port: "{{SSH_PORT}}"
|
||||
|
||||
- name: Add installation tasks
|
||||
include_tasks: install.yml
|
||||
when: (ADD_VRRP is not defined) or (ADD_VRRP != "1")
|
||||
|
||||
|
||||
- name: Add add vrrp tasks
|
||||
include_tasks: add_vrrp.yml
|
||||
when: (ADD_VRRP is defined) and (ADD_VRRP|length > 0)
|
||||
- name: check if Keepalived is installed
|
||||
package_facts:
|
||||
manager: "auto"
|
||||
|
||||
- name: install EPEL Repository
|
||||
yum:
|
||||
name: epel-release
|
||||
state: latest
|
||||
when:
|
||||
- ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS'
|
||||
- ansible_facts['distribution_major_version'] == '7'
|
||||
ignore_errors: yes
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
- name: Creates log directory
|
||||
file:
|
||||
path: "{{keepalived_path_logs}}"
|
||||
state: directory
|
||||
|
||||
- name: Copy keepalived configuration for rsyslog.
|
||||
template:
|
||||
src: rsyslog.conf.j2
|
||||
dest: /etc/rsyslog.d/50-keepalived.conf
|
||||
mode: 0644
|
||||
notify: restart rsyslog
|
||||
|
||||
- name: Install the latest version of Keepalived
|
||||
package:
|
||||
name:
|
||||
- keepalived
|
||||
- psmisc
|
||||
state: present
|
||||
when: "'keepalived' not in ansible_facts.packages"
|
||||
environment:
|
||||
http_proxy: "{{PROXY}}"
|
||||
https_proxy: "{{PROXY}}"
|
||||
|
||||
|
||||
- name: Ensure group "keepalived_script" exists
|
||||
group:
|
||||
name: keepalived_script
|
||||
state: present
|
||||
system: yes
|
||||
|
||||
|
||||
- name: Add the user 'keepalived_script'
|
||||
user:
|
||||
name: keepalived_script
|
||||
comment: User for keepalived_script
|
||||
group: keepalived_script
|
||||
shell: /sbin/nologin
|
||||
create_home: no
|
||||
system: yes
|
||||
|
||||
|
||||
- name: Copy keepalived configuration in place.
|
||||
template:
|
||||
src: keepalived.conf.j2
|
||||
dest: /etc/keepalived/keepalived.conf
|
||||
mode: 0644
|
||||
|
||||
- name: test to see if selinux is running
|
||||
command: getenforce
|
||||
register: sestatus
|
||||
changed_when: false
|
||||
when: (ansible_facts['os_family'] == "RedHat" or ansible_facts['os_family'] == 'CentOS')
|
||||
|
||||
|
||||
- name: Disble SELINUX in config
|
||||
template:
|
||||
src: ../../haproxy/templates/selinux.j2
|
||||
dest: /etc/selinux/config
|
||||
ignore_errors: yes
|
||||
when:
|
||||
- sestatus.stdout is defined
|
||||
- '"Enforcing" in sestatus.stdout'
|
||||
|
||||
|
||||
- name: Disble SELINUX in env
|
||||
shell: setenforce 0 2> /dev/null
|
||||
ignore_errors: yes
|
||||
debugger: never
|
||||
when:
|
||||
- sestatus.stdout is defined
|
||||
- '"Enforcing" in sestatus.stdout'
|
||||
|
||||
|
||||
- name: Enable and start service keepalived
|
||||
service:
|
||||
name: keepalived
|
||||
daemon_reload: yes
|
||||
state: started
|
||||
enabled: yes
|
||||
ignore_errors: yes
|
||||
|
||||
|
||||
- name: Enable net.ipv4.ip_forward
|
||||
sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
sysctl_set: yes
|
||||
state: present
|
||||
reload: yes
|
||||
|
||||
|
||||
- name: Add syn_flood tasks
|
||||
include: ../../haproxy/tasks/syn_flood.yml
|
||||
when: (SYN_FLOOD is defined) and (SYN_FLOOD|length > 0)
|
|
@ -1,21 +0,0 @@
|
|||
vrrp_instance VI_{{IP}} {
|
||||
state {{MASTER}}
|
||||
interface {% if MASTER == 'MASTER' %}{{ETH}} {% else %} {{ETH_SLAVE}} {% endif %}
|
||||
|
||||
virtual_router_id {{ router_id }}
|
||||
|
||||
priority {% if RETURN_TO_MASTER == 1 and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == 0 %}102{% else %}101{%endif%}
|
||||
|
||||
track_script {
|
||||
chk_haproxy
|
||||
}
|
||||
|
||||
advert_int 1
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass VerySecretPass2!
|
||||
}
|
||||
virtual_ipaddress {
|
||||
{{IP}}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,47 @@
|
|||
global_defs {
|
||||
# Managed by Roxy-WI do not edit this file. Use HA cluster configuration instead
|
||||
router_id LVS_DEVEL
|
||||
}
|
||||
{%- if NGINX == '1' %}
|
||||
{% set check_service = 'nginx' %}
|
||||
{% else %}
|
||||
{% set check_service = 'haproxy' %}
|
||||
{% endif %}
|
||||
#health-check for keepalive
|
||||
vrrp_script chk_service {
|
||||
script "systemctl is-active --quiet {{ check_service }}"
|
||||
interval 2
|
||||
weight 3
|
||||
}
|
||||
vrrp_instance VI_1 {
|
||||
state {{MASTER}}
|
||||
interface {% if MASTER == 'MASTER' %}{{ETH}} {% else %} {{ETH_SLAVE}} {% endif %}
|
||||
|
||||
virtual_router_id {{router_id}}
|
||||
priority {% if RETURN_TO_MASTER == '1' and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == '0' %}102{% else %}101{%endif%}
|
||||
|
||||
{%- if NGINX %}
|
||||
#NGINX health-check for keepalive
|
||||
vrrp_script chk_nginx {
|
||||
script "systemctl is-active --quiet nginx"
|
||||
interval 2
|
||||
weight 3
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{%- if HAPROXY %}
|
||||
#HAProxy health-check for keepalive
|
||||
vrrp_script chk_haproxy {
|
||||
script "systemctl is-active --quiet haproxy"
|
||||
interval 2
|
||||
weight 3
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% for router, vip in routers.items() %}
|
||||
{% for vrrp, s in vip.items() %}
|
||||
vrrp_instance VI_{{router}} {
|
||||
state {{s.master}}
|
||||
interface {{s.eth}}
|
||||
|
||||
virtual_router_id {{router}}
|
||||
priority {% if s.return_master and s.master %}152{% elif s.master and not s.return_master %}102{% else %}101{%endif%}
|
||||
|
||||
#check if we are still running
|
||||
track_script {
|
||||
chk_service
|
||||
|
||||
|
||||
{%- if HAPROXY %}
|
||||
chk_haproxy
|
||||
{% endif %}
|
||||
{%- if NGINX %}
|
||||
chk_nginx
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
advert_int 1
|
||||
|
@ -30,6 +50,9 @@ vrrp_instance VI_1 {
|
|||
auth_pass VerySecretPass
|
||||
}
|
||||
virtual_ipaddress {
|
||||
{{IP}}
|
||||
{{vrrp}}
|
||||
}
|
||||
}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
# Managed by Roxy-WI do not edit this file. Use HA cluster configuration instead
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
- name: Install common role
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: yes
|
||||
|
@ -15,7 +15,7 @@
|
|||
- docker
|
||||
|
||||
- name: Install docker
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: yes
|
||||
roles:
|
||||
|
@ -34,7 +34,7 @@
|
|||
- docker
|
||||
|
||||
- name: Install system role
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
become_method: sudo
|
||||
tasks:
|
||||
|
@ -58,13 +58,10 @@
|
|||
- system
|
||||
|
||||
- name: "Set {{ ansible_user }} owner to {{ service_dir }}"
|
||||
hosts: "{{ variable_host }}"
|
||||
hosts: all
|
||||
become: yes
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Set SSH port
|
||||
set_fact:
|
||||
ansible_port: "{{SSH_PORT}}"
|
||||
- name: "Set {{ ansible_user }} owner to {{ service_dir }}"
|
||||
file:
|
||||
path: "{{ service_dir }}"
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
#!/bin/bash
|
||||
for ARGUMENT in "$@"
|
||||
do
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
|
||||
|
||||
case "$KEY" in
|
||||
PROXY) PROXY=${VALUE} ;;
|
||||
HOST) HOST=${VALUE} ;;
|
||||
USER) USER=${VALUE} ;;
|
||||
PASS) PASS=${VALUE} ;;
|
||||
KEY) KEY=${VALUE} ;;
|
||||
SYN_FLOOD) SYN_FLOOD=${VALUE} ;;
|
||||
STAT_PORT) STAT_PORT=${VALUE} ;;
|
||||
STAT_PAGE) STAT_PAGE=${VALUE} ;;
|
||||
STATS_USER) STATS_USER=${VALUE} ;;
|
||||
STATS_PASS) STATS_PASS=${VALUE} ;;
|
||||
SSH_PORT) SSH_PORT=${VALUE} ;;
|
||||
CONFIG_PATH) CONFIG_PATH=${VALUE} ;;
|
||||
DOCKER) DOCKER=${VALUE} ;;
|
||||
CONT_NAME) CONT_NAME=${VALUE} ;;
|
||||
service_dir) service_dir=${VALUE} ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $DOCKER == '1' ]]; then
|
||||
tags='docker'
|
||||
else
|
||||
tags='system'
|
||||
fi
|
||||
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
|
||||
export ACTION_WARNINGS=False
|
||||
export LOCALHOST_WARNING=False
|
||||
export COMMAND_WARNINGS=False
|
||||
|
||||
PWD=/var/www/haproxy-wi/app/scripts/ansible/
|
||||
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
|
||||
|
||||
if [[ $KEY == "" ]]; then
|
||||
ansible-playbook $PWD/roles/apache.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST PROXY=$PROXY CONT_NAME=$CONT_NAME service_dir=$service_dir SYN_FLOOD=$SYN_FLOOD STAT_PAGE=$STAT_PAGE STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS=$STATS_PASS CONFIG_PATH=$CONFIG_PATH SSH_PORT=$SSH_PORT service=apache" -i $PWD/$HOST -t $tags
|
||||
else
|
||||
ansible-playbook $PWD/roles/apache.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST PROXY=$PROXY CONT_NAME=$CONT_NAME service_dir=$service_dir SYN_FLOOD=$SYN_FLOOD STAT_PAGE=$STAT_PAGE STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS=$STATS_PASS CONFIG_PATH=$CONFIG_PATH SSH_PORT=$SSH_PORT service=apache" -i $PWD/$HOST -t $tags
|
||||
fi
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
echo "error: Can't install Apache service <br /><br />"
|
||||
rm -f $PWD/$HOST
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
rm -f $PWD/$HOST
|
|
@ -1,59 +0,0 @@
|
|||
#!/bin/bash
|
||||
for ARGUMENT in "$@"
|
||||
do
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
|
||||
|
||||
case "$KEY" in
|
||||
PROXY) PROXY=${VALUE} ;;
|
||||
SOCK_PORT) SOCK_PORT=${VALUE} ;;
|
||||
STAT_PORT) STAT_PORT=${VALUE} ;;
|
||||
STAT_FILE) STAT_FILE=${VALUE} ;;
|
||||
STATS_USER) STATS_USER=${VALUE} ;;
|
||||
STATS_PASS) STATS_PASS=${VALUE} ;;
|
||||
HAPVER) HAPVER=${VALUE} ;;
|
||||
HOST) HOST=${VALUE} ;;
|
||||
USER) USER=${VALUE} ;;
|
||||
PASS) PASS=${VALUE} ;;
|
||||
KEY) KEY=${VALUE} ;;
|
||||
SYN_FLOOD) SYN_FLOOD=${VALUE} ;;
|
||||
SSH_PORT) SSH_PORT=${VALUE} ;;
|
||||
DOCKER) DOCKER=${VALUE} ;;
|
||||
HAP_DIR) HAP_DIR=${VALUE} ;;
|
||||
CONT_NAME) CONT_NAME=${VALUE} ;;
|
||||
M_OR_S) M_OR_S=${VALUE} ;;
|
||||
MASTER) MASTER=${VALUE} ;;
|
||||
SLAVE) SLAVE=${VALUE} ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
|
||||
export ACTION_WARNINGS=False
|
||||
export LOCALHOST_WARNING=False
|
||||
export COMMAND_WARNINGS=False
|
||||
|
||||
PWD=/var/www/haproxy-wi/app/scripts/ansible/
|
||||
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
|
||||
|
||||
if [[ $DOCKER == '1' ]]; then
|
||||
tags='docker'
|
||||
else
|
||||
tags='system'
|
||||
fi
|
||||
|
||||
if [[ $KEY == "" ]]; then
|
||||
ansible-playbook $PWD/roles/haproxy.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST PROXY=$PROXY HAPVER=$HAPVER HAP_DIR=$HAP_DIR CONT_NAME=$CONT_NAME SOCK_PORT=$SOCK_PORT STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS='$STATS_PASS' STAT_FILE=$STAT_FILE SSH_PORT=$SSH_PORT SYN_FLOOD=$SYN_FLOOD M_OR_S=$M_OR_S MASTER=$MASTER SLAVE=$SLAVE" -i $PWD/$HOST -t $tags
|
||||
else
|
||||
ansible-playbook $PWD/roles/haproxy.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST PROXY=$PROXY HAPVER=$HAPVER HAP_DIR=$HAP_DIR CONT_NAME=$CONT_NAME SOCK_PORT=$SOCK_PORT STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS='$STATS_PASS' STAT_FILE=$STAT_FILE SSH_PORT=$SSH_PORT SYN_FLOOD=$SYN_FLOOD M_OR_S=$M_OR_S MASTER=$MASTER SLAVE=$SLAVE" -i $PWD/$HOST -t $tags
|
||||
fi
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
echo "error: Cannot install Haproxy service"
|
||||
rm -f $PWD/$HOST
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f $PWD/$HOST
|
|
@ -1,55 +0,0 @@
|
|||
#!/bin/bash
|
||||
for ARGUMENT in "$@"
|
||||
do
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
|
||||
|
||||
case "$KEY" in
|
||||
PROXY) PROXY=${VALUE} ;;
|
||||
MASTER) MASTER=${VALUE} ;;
|
||||
ETH) ETH=${VALUE} ;;
|
||||
ETH_SLAVE) ETH_SLAVE=${VALUE} ;;
|
||||
keepalived_path_logs) keepalived_path_logs=${VALUE} ;;
|
||||
IP) IP=${VALUE} ;;
|
||||
HOST) HOST=${VALUE} ;;
|
||||
USER) USER=${VALUE} ;;
|
||||
router_id) router_id=${VALUE} ;;
|
||||
PASS) PASS=${VALUE} ;;
|
||||
KEY) KEY=${VALUE} ;;
|
||||
SYN_FLOOD) SYN_FLOOD=${VALUE} ;;
|
||||
RESTART) RESTART=${VALUE} ;;
|
||||
RETURN_TO_MASTER) RETURN_TO_MASTER=${VALUE} ;;
|
||||
ADD_VRRP) ADD_VRRP=${VALUE} ;;
|
||||
SSH_PORT) SSH_PORT=${VALUE} ;;
|
||||
HAPROXY) HAPROXY=${VALUE} ;;
|
||||
NGINX) NGINX=${VALUE} ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
|
||||
export ACTION_WARNINGS=False
|
||||
export LOCALHOST_WARNING=False
|
||||
export COMMAND_WARNINGS=False
|
||||
|
||||
PWD=/var/www/haproxy-wi/app/scripts/ansible/
|
||||
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
|
||||
|
||||
if [[ $MASTER == 'BACKUP' ]]; then
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
if [[ $KEY == "" ]]; then
|
||||
ansible-playbook $PWD/roles/keepalived.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH ETH_SLAVE=$ETH_SLAVE keepalived_path_logs=$keepalived_path_logs IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id HAPROXY=$HAPROXY NGINX=$NGINX SSH_PORT=$SSH_PORT" -i $PWD/$HOST
|
||||
else
|
||||
ansible-playbook $PWD/roles/keepalived.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH ETH_SLAVE=$ETH_SLAVE keepalived_path_logs=$keepalived_path_logs IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id HAPROXY=$HAPROXY NGINX=$NGINX SSH_PORT=$SSH_PORT" -i $PWD/$HOST
|
||||
fi
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
echo "error: Can't install keepalived service <br />"
|
||||
rm -f $PWD/$HOST
|
||||
exit 1
|
||||
fi
|
||||
rm -f $PWD/$HOST
|
|
@ -1,64 +0,0 @@
|
|||
#!/bin/bash
|
||||
for ARGUMENT in "$@"
|
||||
do
|
||||
KEY=$(echo $ARGUMENT | cut -f1 -d=)
|
||||
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
|
||||
|
||||
case "$KEY" in
|
||||
PROXY) PROXY=${VALUE} ;;
|
||||
HOST) HOST=${VALUE} ;;
|
||||
USER) USER=${VALUE} ;;
|
||||
PASS) PASS=${VALUE} ;;
|
||||
KEY) KEY=${VALUE} ;;
|
||||
SYN_FLOOD) SYN_FLOOD=${VALUE} ;;
|
||||
STAT_PORT) STAT_PORT=${VALUE} ;;
|
||||
STAT_PAGE) STAT_PAGE=${VALUE} ;;
|
||||
STATS_USER) STATS_USER=${VALUE} ;;
|
||||
STATS_PASS) STATS_PASS=${VALUE} ;;
|
||||
SSH_PORT) SSH_PORT=${VALUE} ;;
|
||||
CONFIG_PATH) CONFIG_PATH=${VALUE} ;;
|
||||
DOCKER) DOCKER=${VALUE} ;;
|
||||
CONT_NAME) CONT_NAME=${VALUE} ;;
|
||||
service_dir) service_dir=${VALUE} ;;
|
||||
*)
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -d "/var/www/haproxy-wi/app/scripts/ansible/roles/nginxinc.nginx" ]; then
|
||||
if [ ! -z $PROXY ];then
|
||||
export https_proxy="$PROXY"
|
||||
export http_proxy="$PROXY"
|
||||
fi
|
||||
ansible-galaxy install nginxinc.nginx --roles-path /var/www/haproxy-wi/app/scripts/ansible/roles/
|
||||
fi
|
||||
|
||||
if [[ $DOCKER == '1' ]]; then
|
||||
tags='docker'
|
||||
else
|
||||
tags='system'
|
||||
fi
|
||||
|
||||
export ANSIBLE_HOST_KEY_CHECKING=False
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
|
||||
export ACTION_WARNINGS=False
|
||||
export LOCALHOST_WARNING=False
|
||||
export COMMAND_WARNINGS=False
|
||||
|
||||
PWD=/var/www/haproxy-wi/app/scripts/ansible/
|
||||
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
|
||||
|
||||
if [[ $KEY == "" ]]; then
|
||||
ansible-playbook $PWD/roles/nginx.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST PROXY=$PROXY CONT_NAME=$CONT_NAME service_dir=$service_dir SYN_FLOOD=$SYN_FLOOD STAT_PAGE=$STAT_PAGE STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS=$STATS_PASS CONFIG_PATH=$CONFIG_PATH SSH_PORT=$SSH_PORT service=nginx" -i $PWD/$HOST -t $tags
|
||||
else
|
||||
ansible-playbook $PWD/roles/nginx.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST PROXY=$PROXY CONT_NAME=$CONT_NAME service_dir=$service_dir SYN_FLOOD=$SYN_FLOOD STAT_PAGE=$STAT_PAGE STAT_PORT=$STAT_PORT STATS_USER=$STATS_USER STATS_PASS=$STATS_PASS CONFIG_PATH=$CONFIG_PATH SSH_PORT=$SSH_PORT service=nginx" -i $PWD/$HOST -t $tags
|
||||
fi
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
echo "error: Can't install NGINX service <br /><br />"
|
||||
rm -f $PWD/$HOST
|
||||
exit 1
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
rm -f $PWD/$HOST
|
|
@ -0,0 +1,16 @@
|
|||
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
||||
{% from 'include/input_macros.html' import input %}
|
||||
{% for slave in slaves %}
|
||||
<div class="{{ loop.cycle('odd', 'even') }}" style="height: 25px; padding-top: 10px; padding-left: 10px;" id="vip_slave-{{slave.0}}">
|
||||
<div style="float: left; width: 205px">{{slave.1}}</div>
|
||||
{%- if not slave.31 -%}
|
||||
<span class="slave_int" id="slave_int_div-{{slave.0}}" data-ip="{{slave.2}}">
|
||||
{{ input('slave_int-'+slave.0|string(), placeholder='eth0', value=slave.32, size='7', title=lang.phrases.int_vrrp + ' ' +lang.ha_page.start_enter) }}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="master_int" id="master_int_div-{{slave.0}}" data-ip="{{slave.2}}">
|
||||
{{ input('master_int-'+slave.0|string(), placeholder='eth0', value=slave.32, size='7', title=lang.phrases.int_vrrp + ' ' +lang.ha_page.start_enter) }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -0,0 +1,76 @@
|
|||
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
||||
{% from 'include/input_macros.html' import input, checkbox, copy_to_clipboard %}
|
||||
{% for cluster in clusters %}
|
||||
<div id="cluster-{{cluster.id}}" class="div-server-hapwi">
|
||||
<div class="server-name">
|
||||
<a href="/app/ha/cluster/{{cluster.id}}" style="color: #5d9ceb" title="{{lang.words.open|title()}} {{lang.words.cluster}}">
|
||||
<span id="cluster-name-{{cluster.id}}">{{cluster.name}}</span>
|
||||
<span id="cluster-desc-{{cluster.id}}">{% if cluster.desc != '' %} ({{cluster.desc}}) {% endif %}</span>
|
||||
</a>
|
||||
<span class="server-action">
|
||||
{% if role <= 2 %}
|
||||
<a class="plus" onclick="add_vip_ha_cluster('{{cluster.id}}', '{{cluster.name}}')"></a>
|
||||
<a class="edit" onclick="createHaClusterStep1(true, '{{cluster.id}}')"></a>
|
||||
<a class="delete" onclick="confirmDeleteCluster('{{cluster.id}}')"></a>
|
||||
<span class="portlet-header" title="{{lang.words.change2|title()}} {{lang.words.position}} {{cluster.name}}">
|
||||
<i class="fas fa-grip-vertical"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="server-desc">
|
||||
{% for slave in slaves %}
|
||||
{% if slave.31 %}
|
||||
Master name: {{ copy_to_clipboard(id='master-server-'+cluster.id|string(), value=slave.1) }}<br>
|
||||
Master IP: {{ copy_to_clipboard(id='master-ip-'+cluster.id|string(), value=slave.2) }}<br>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{lang.words.slaves|title()}}:
|
||||
{% for slave in slaves %}
|
||||
{% if not slave.31 %}
|
||||
<span class="cluster-server">{{slave.1}}</span> ({{slave.2}})
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div>
|
||||
{{lang.words.virtual|title()}} {{lang.words.servers}}:
|
||||
{% for virt in virts %}
|
||||
{% if virt.cluster_id|string() == cluster.id|string() %}
|
||||
{% for server in servers %}
|
||||
{% if virt.virt_id|string() == server.0|string() %}
|
||||
<span class="cluster-server">{{server.1}}</span> ({{server.2}})
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div>
|
||||
VIP:
|
||||
<span id="cluster-vip">
|
||||
{%- for vip in vips %}
|
||||
{% if role <= 2 %}
|
||||
<a style="cursor: pointer;" onclick="add_vip_ha_cluster('{{vip.cluster_id}}', '{{cluster.name}}', '{{vip.router_id}}', '{{vip.vip}}', 1)" title="{{lang.words.edit|title()}} VIP">{{vip.vip}}</a>
|
||||
{% else %}
|
||||
{{vip.vip}}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
{{lang.words.services|title()}}:
|
||||
{% for c_s in cluster_services %}
|
||||
{% if c_s.cluster_id|string() == cluster.id|string() %}
|
||||
{% for service in services %}
|
||||
{% if c_s.service_id|string() == service.service_id|string() %}
|
||||
<a href="/app/service/{{service.slug}}">{{service.service}}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- <div>-->
|
||||
<!-- {{lang.ha_page.return_master_desc}}: {% if cluster.return_master %} {{lang.words.true|title()}} {% else %} {{lang.words.false|title()}} {% endif %}-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
{{ input('router_id-'+ cluster.id|string(), type='hidden') }}
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -0,0 +1,4 @@
|
|||
<option value="------" disabled selected>-------</option>
|
||||
{% for server in free_servers %}
|
||||
<option value="{{server.ip}}">{{server.hostname}}</option>
|
||||
{% endfor %}
|
|
@ -0,0 +1,25 @@
|
|||
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
||||
{% from 'include/input_macros.html' import input %}
|
||||
<div class="enabled-check" id="enabled-check">
|
||||
{%- for s in slaves -%}
|
||||
{%- if not s.31 -%}
|
||||
<div class="{{ loop.cycle('odd', 'even') }}" id="remove_check-{{s.0}}" data-name="{{ s.1 }}">
|
||||
<div class="check-name">
|
||||
<div style="width: 150px; display: inline-block;">{{ s.1.replace("'", '') }}</div>
|
||||
<span class="slave_int" id="slave_int_div-{{s.0}}" data-ip="{{s.2}}">
|
||||
{{ input('slave_int-'+s.0|string(), value=s.32, size='7', title=lang.phrases.int_vrrp + ' ' +lang.ha_page.start_enter) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="add_user_group check-button" onclick="removeCheckFromStatus({{s.0}}, '{{s.2}}')">-</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
<div id="all-checks">
|
||||
{% for s in free_servers %}
|
||||
<div class="{{ loop.cycle('odd', 'even') }} all-checks" id="add_check-{{ s.server_id }}" data-name="{{ s.hostname }}">
|
||||
<div class="check-name" title="{{s.desc}}" data-help="{{s.desc}}">{{ s.hostname.replace("'", '') }}</div>
|
||||
<div class="add_user_group check-button" title="{{lang.words.add|title()}} {{lang.words.service}}" onclick="addCheckToStatus('{{ s.server_id }}', '{{s.ip}}')">+</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
|
@ -20,7 +20,10 @@
|
|||
data-stop="{{lang.words.stop|title()}}" data-reload="{{lang.words.reload|title()}}" data-user_groups="{{lang.phrases.user_groups}}" data-settings="{{lang.words.settings|title()}}"
|
||||
data-for="{{lang.words.for}}" data-show="{{lang.words.show|title()}}" data-hide="{{lang.words.hide|title()}}" data-logs="{{lang.words.logs}}" data-name="{{lang.words.name}}"
|
||||
data-value="{{lang.words.value}}" data-if-title="{{lang.words.if|title()}}" data-then="{{lang.words.then}}" data-autorefresh="{{lang.words.auto|title()}}-{{lang.words.refresh}}"
|
||||
data-raw="{{lang.words.raw|title()}}" data-resp_time="{{lang.smon_page.desc.resp_time}}" data-next="{{lang.words.next|title()}}" data-back="{{lang.words.back|title()}}" />
|
||||
data-raw="{{lang.words.raw|title()}}" data-resp_time="{{lang.smon_page.desc.resp_time}}" data-next="{{lang.words.next|title()}}" data-back="{{lang.words.back|title()}}"
|
||||
data-installing="{{lang.words.installing|title()}}" data-creating="{{lang.words.creating|title()}}" data-roxywi_timeout="{{lang.ha_page.roxywi_timeout}}"
|
||||
data-check_apache_log="{{lang.ha_page.check_apache_log}}" data-was_installed="{{lang.ha_page.was_installed}}" data-start_enter="{{lang.ha_page.start_enter}}"
|
||||
data-apply="{{lang.words.apply|title()}}" />
|
||||
{% if title == 'Login page' %}
|
||||
<meta name="viewport" content="width=device-width, user-scalable=1">
|
||||
{% endif %}
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}{{ lang.menu_links.ha.title }} {% endblock %}
|
||||
{% block h2 %}{{ lang.menu_links.ha.title }} {% endblock %}
|
||||
{% block content %}
|
||||
{% from 'include/input_macros.html' import input, checkbox %}
|
||||
<script src="/inc/users.js"></script>
|
||||
<script src="/inc/ha.js"></script>
|
||||
<link href="/inc/css/ha.css" rel="stylesheet">
|
||||
<style>
|
||||
p {margin: 0;}
|
||||
</style>
|
||||
{% if user_status == 0 or user_plan == 'user' %}
|
||||
{% include 'include/no_sub.html' %}
|
||||
{% elif not is_needed_tool %}
|
||||
<div style="text-align: center;">
|
||||
<h3>You have not installed Ansible</h3>.
|
||||
<img src="{{ url_for('static', filename='images/no_servers.png')}}" alt="There is no server">
|
||||
<h4>
|
||||
Read <a href="https://roxy-wi.org/installation#ansible" title="{{lang.words.installing|title()}} Ansible" target="_blank">here</a> how to install Ansible.
|
||||
</h4>
|
||||
</div>
|
||||
{% else %}
|
||||
<table class="overview" style="margin-bottom: 20px;">
|
||||
<caption><h3>{{lang.words.create|title()}} {{lang.words.w_a}} {{lang.words.new}} HA {{lang.words.cluster}}</h3></caption>
|
||||
<tr class="overviewHead">
|
||||
<td class="padding10 first-collumn">{{lang.words.current2|title()}} {{lang.words.installation}}</td>
|
||||
<td class="padding10 first-collumn">{{lang.words.current2|title()}}</td>
|
||||
<td class="padding10 first-collumn">{{lang.words.current2|title()}} {{lang.words.installation}}</td>
|
||||
<td>{{lang.words.slave|title()}}</td>
|
||||
<td><span title="{{lang.phrases.int_vrrp}}">{{lang.words.master|title()}} {{lang.words.interface|title()}}</span></td>
|
||||
<td><span title="{{lang.phrases.int_vrrp}}">{{lang.words.slave|title()}} {{lang.words.interface|title()}}</span></td>
|
||||
<td>VRRP IP</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding10 first-collumn" id="cur_master_ver"></td>
|
||||
<td class="padding10 first-collumn">
|
||||
<select id="master">
|
||||
<option disabled selected>------</option>
|
||||
{% for select in selects %}
|
||||
<option value="{{ select.2 }}">{{ select.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td class="padding10 first-collumn" id="cur_slave_ver"></td>
|
||||
<td>
|
||||
<select id="slave">
|
||||
<option disabled selected>------</option>
|
||||
{% for select in selects %}
|
||||
<option value="{{ select.2 }}">{{ select.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>{{ input('interface', size='7', title=lang.phrases.int_vrrp) }}</td>
|
||||
<td>{{ input('slave_interface', size='7', title=lang.phrases.int_vrrp) }}</td>
|
||||
<td>{{ input('vrrp-ip', size='14') }}</td>
|
||||
</tr>
|
||||
<tr class="overviewHead">
|
||||
<td class="padding10 first-collumn"></td>
|
||||
<td class="help_cursor"><span title="Roxy-WI will add VRRP address as a separated server">{{lang.words.add|title()}} VIRT</span></td>
|
||||
<td class="checkbox-head help_cursor" style="padding-left: 20px;" title="If checked, the Keepalived master will not release VRRP if the service is down">{{lang.words.stay|title()}} {{lang.words.as}} {{lang.words.master|title()}}</td>
|
||||
<td class="checkbox-head">SYN-flood {{lang.words.protection}}</td>
|
||||
<td class="checkbox-head help_cursor" style="padding: 10px 10px 10px 5px;"><span title="Roxy-WI will try to install HAProxy">HAProxy</span></td>
|
||||
<td class="checkbox-head help_cursor" style="display: none" id="haproxy_docker_td_header"><span title="Roxy-WI will install HAProxy as Docker container">Docker</span></td>
|
||||
<td class="help_cursor" style="padding-left: 5px;"><span title="Roxy-WI will try to install NGINX">NGINX</span></td>
|
||||
<td class="checkbox-head help_cursor" style="display: none" id="nginx_docker_td_header"><span title="Roxy-WI will install NGINX as Docker container">Docker</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding10 first-collumn"></td>
|
||||
<td class="checkbox help_cursor">{{ checkbox('virt_server', title='Roxy-WI will add VRRP address as a separated server', checked='checked') }}</td>
|
||||
<td class="syn-flood-protection-field help_cursor">{{ checkbox('return_to_master', title='If checked, the Keepalived master will not release VRRP if the service is down') }}</td>
|
||||
<td class="syn-flood-protection-field">{{ checkbox('syn_flood') }}</td>
|
||||
<td class="checkbox help_cursor" style="padding: 10px 10px 10px 15px;">{{ checkbox('hap', title='Roxy-WI will try to install HAProxy') }}</td>
|
||||
<td class="checkbox help_cursor" style="display: none" id="haproxy_docker_td">{{ checkbox('hap_docker', title='Roxy-WI will install HAProxy as a Docker container') }}</td>
|
||||
<td class="checkbox help_cursor">{{ checkbox('nginx', title='Roxy-WI will try to install NGINX') }}</td>
|
||||
<td class="checkbox help_cursor" style="display: none" id="nginx_docker_td">{{ checkbox('nginx_docker', title='Roxy-WI will install NGINX as a Docker container') }}</td>
|
||||
<td>
|
||||
<button id="create" title="Create HA cluster">{{lang.words.create|title()}}</button>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="overview">
|
||||
<caption><h3>{{lang.words.add|title()}} VRRP {{lang.words.to}} {{lang.words.an}} {{lang.words.existing2}} {{lang.words.cluster}}</h3></caption>
|
||||
<tr class="overviewHead">
|
||||
<td class="padding10 first-collumn">{{lang.words.current2|title()}} {{lang.words.installation}}</td>
|
||||
<td class="padding10 first-collumn">{{lang.words.master|title()}}</td>
|
||||
<td class="padding10 first-collumn">{{lang.words.current2|title()}} {{lang.words.installation}}</td>
|
||||
<td>{{lang.words.slave|title()}}</td>
|
||||
<td><span title="{{lang.phrases.int_vrrp}}">{{lang.words.master|title()}} {{lang.words.interface|title()}}</span></td>
|
||||
<td><span title="{{lang.phrases.int_vrrp}}">{{lang.words.slave|title()}} {{lang.words.interface|title()}}</span></td>
|
||||
<td>VRRP IP</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding10 first-collumn" id="cur_master_ver-add"></td>
|
||||
<td class="padding10 first-collumn">
|
||||
<select id="master-add">
|
||||
<option disabled selected>------</option>
|
||||
{% for select in selects %}
|
||||
<option value="{{ select.2 }}">{{ select.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td class="padding10 first-collumn" id="cur_slave_ver-add"></td>
|
||||
<td>
|
||||
<select id="slave-add">
|
||||
<option disabled selected>------</option>
|
||||
{% for select in selects %}
|
||||
<option value="{{ select.2 }}">{{ select.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>{{ input('interface-add', size='7', title=lang.phrases.int_vrrp) }}</td>
|
||||
<td>{{ input('slave_interface-add', size='7', title=lang.phrases.int_vrrp) }}</td>
|
||||
<td>{{ input('vrrp-ip-add', size='14') }}</td>
|
||||
</tr>
|
||||
<tr class="overviewHead">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="padding10 first-collumn" style="padding-left: 10px;"><span title="If checked Roxy-WI will restart Keepalived">{{lang.words.restart|title()}}</span></td>
|
||||
<td class="help_cursor" title="If checked, Keepalived master will reclaim VRRP after recovered">{{lang.words.return|title()}} {{lang.words.to}} {{lang.words.master|title()}} state</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="padding10 first-collumn checkbox help_cursor">{{ checkbox('kp', title='If checked Roxy-WI will restart Keepalived') }}</td>
|
||||
<td class="syn-flood-protection-field">{{ checkbox('add_return_to_master', checked='checked') }}</td>
|
||||
<td>
|
||||
<button id="add-vrrp" title="Add a HA configuration" style="width: 70px;">{{lang.words.add|title()}}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="ajax"></div>
|
||||
<div class="add-note alert addName alert-info" style="width: inherit; margin-right: 15px;">
|
||||
{{lang.words.read|title()}} <a href="https://roxy-wi.org/howto/ha-cluster" title="How to create high available cluster" target="_blank">{{lang.phrases.howto_ha}}</a>
|
||||
</div>
|
||||
<div id="server_creating" style="display: none;" title="{{lang.phrases.creating_ha}}">
|
||||
<ul style="padding: 20px 20px 0px 20px;font-size: 15px;">
|
||||
<li id="creating-master" class="server-creating proccessing">{{lang.words.installing|title()}} {{lang.words.master|title()}} Keepalived...</li>
|
||||
<li id="creating-slave" class="server-creating proccessing">{{lang.words.installing|title()}} {{lang.words.slave|title()}} Keepalived...</li>
|
||||
<div id="haproxy_installing_div" style="display: none">
|
||||
<li id="creating-haproxy-master" class="server-creating">{{lang.words.installing|title()}} {{lang.words.master|title()}} Haproxy...</li>
|
||||
<li id="creating-haproxy-slave" class="server-creating">{{lang.words.installing|title()}} {{lang.words.slave|title()}} Haproxy...</li>
|
||||
</div>
|
||||
<div id="nginx_installing_div" style="display: none">
|
||||
<li id="creating-nginx-master" class="server-creating">{{lang.words.installing|title()}} {{lang.words.master|title()}} NGINX...</li>
|
||||
<li id="creating-nginx-slave" class="server-creating">{{lang.words.installing|title()}} {{lang.words.slave|title()}} NGINX...</li>
|
||||
</div>
|
||||
</ul>
|
||||
<div id="wait-mess"></div>
|
||||
<div id="created-mess" class="alert alert-success" style="display:none;"></div>
|
||||
<div id="creating-error" class="alert alert-danger" style="display:none;"></div>
|
||||
<div id="creating-warning" class="alert alert-warning" style="display:none;"></div>
|
||||
<div class="progress-bar-striped">
|
||||
<div id="creating-progress" style="width: 0%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="address_creating" style="display: none;" title="{{lang.phrases.adding_vrrp}}">
|
||||
<ul style="padding: 20px 20px 0px 20px;font-size: 15px;">
|
||||
<li id="creating-master-add" class="server-creating proccessing">{{lang.words.creating|title()}} {{lang.words.a}} {{lang.words.new}} {{lang.words.address}} {{lang.words.on}} {{lang.words.master|title()}} Keepalived...</li>
|
||||
<li id="creating-slave-add" class="server-creating proccessing">{{lang.words.creating|title()}} {{lang.words.a}} {{lang.words.new}} {{lang.words.address}} {{lang.words.on}} {{lang.words.slave|title()}} Keepalived...</li>
|
||||
</ul>
|
||||
<div id="wait-mess-add"></div>
|
||||
<div id="created-mess-add" class="alert alert-success" style="display:none;"></div>
|
||||
<div id="creating-error-add" class="alert alert-danger" style="display:none;"></div>
|
||||
<div id="creating-warning-add" class="alert alert-warning" style="display:none;"></div>
|
||||
<div class="progress-bar-striped">
|
||||
<div id="creating-progress-add" style="width: 0%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,209 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}{{ lang.ha_page.has }} {% endblock %}
|
||||
{% block h2 %}{{ lang.ha_page.has }} {% endblock %}
|
||||
{% block content %}
|
||||
{% from 'include/input_macros.html' import input, checkbox, copy_to_clipboard %}
|
||||
<script src="/inc/users.js"></script>
|
||||
<script src="/inc/ha.js"></script>
|
||||
<script src="/inc/overview.js"></script>
|
||||
<link href="/inc/css/servers.css" rel="stylesheet"/>
|
||||
<link href="/inc/css/smon.css" rel="stylesheet">
|
||||
<link href="/inc/css/ha.css" rel="stylesheet">
|
||||
<script>
|
||||
$( function() {
|
||||
$( ".sortable" ).sortable({
|
||||
revert: true,
|
||||
placeholder: "ui-state-highlight"
|
||||
});
|
||||
$( ".sortable" ).disableSelection();
|
||||
|
||||
$( ".sortable" ).sortable({
|
||||
handle: ".portlet-header",
|
||||
stop: function(event, ui) {
|
||||
var itemOrder = $('.sortable').sortable("toArray");
|
||||
for (var i = 0; i < itemOrder.length; i++) {
|
||||
var pos = i;
|
||||
var id = itemOrder[i].split('-')[2]
|
||||
change_pos(pos, id);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% if user_subscription.user_status == 0 or user_subscription.user_plan == 'user' %}
|
||||
{% include 'include/no_sub.html' %}
|
||||
{% elif not is_needed_tool %}
|
||||
<div style="text-align: center;">
|
||||
<h3>{{lang.admin_page.desc.no_ansible}} Ansible</h3>.
|
||||
<img src="{{ url_for('static', filename='images/no_servers.png')}}" alt="There is no server">
|
||||
<h4>
|
||||
{{lang.words.read|title()}} <a href="https://roxy-wi.org/installation#ansible" title="{{lang.words.install|title()}} Ansible" target="_blank">here</a> {{lang.phrases.how_to_install}} Ansible.
|
||||
</h4>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if role <= 2 %}
|
||||
<div class="add-button add-button-status-page" title="{{lang.phrases.create_ha}}" onclick="createHaClusterStep1();">+ {{lang.ha_page.create_ha}}</div>
|
||||
{% endif %}
|
||||
<div class="up-pannel">
|
||||
{% for cluster in clusters %}
|
||||
<div id="cluster-{{cluster.id}}" class="div-server-hapwi animated-background"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div id="create-status-page-step-1" style="display: none;">
|
||||
<table class="overview" id="create-ha-cluster-step-1-overview"
|
||||
title="{{lang.words.create|title()}} {{lang.ha_page.ha}} {{lang.words.cluster}}"
|
||||
data-edit="{{lang.words.edit|title()}} {{lang.ha_page.ha}} {{lang.words.cluster}}">
|
||||
{% include 'include/tr_validate_tips.html' %}
|
||||
<tr>
|
||||
<td class="padding20" style="width: 50%">
|
||||
{{lang.words.name|title()}}
|
||||
<span class="need-field">*</span>
|
||||
</td>
|
||||
<td>
|
||||
{{ input('ha-cluster-name', autofocus='autofocus') }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
{{lang.words.desc|title()}}
|
||||
</td>
|
||||
<td>
|
||||
{{ input('ha-cluster-desc', autofocus='autofocus') }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
{{lang.words.master|title()}}
|
||||
<span class="need-field">*</span>
|
||||
</td>
|
||||
<td>
|
||||
<select id="ha-cluster-master"></select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding10">{{lang.words.current2|title()}} {{lang.words.installation}}</td>
|
||||
<td id="cur_master_ver"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
{{lang.words.master|title()}} {{lang.words.interface|title()}}
|
||||
<span class="need-field">*</span>
|
||||
</td>
|
||||
<td>{{ input('ha-cluster-master-interface', size='7', title=lang.phrases.int_vrrp, placeholder='eth0') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
VIP
|
||||
<span class="need-field">*</span>
|
||||
</td>
|
||||
<td>{{ input('vrrp-ip', size='14') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
{{lang.words.all|title()}} {{lang.words.servers}}
|
||||
</td>
|
||||
<td>{{lang.words.slaves|title()}} {{lang.words.servers}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="checks"></div>
|
||||
</div>
|
||||
<div id="create-status-page-step-2" style="display: none;">
|
||||
<table class="overview" id="create-ha-cluster-step-2-overview"
|
||||
title="{{lang.words.create|title()}} {{lang.ha_page.ha}} {{lang.words.cluster}}"
|
||||
data-edit="{{lang.words.edit|title()}} {{lang.ha_page.ha}} {{lang.words.cluster}}">
|
||||
<tr>
|
||||
<td class="padding20 help_cursor"><span title="{{lang.ha_page.create_virt_server}}">{{lang.words.add|title()}} VIRT {{lang.words.server}}</span></td>
|
||||
<td class="help_cursor">{{ checkbox('virt_server', title=lang.ha_page.create_virt_server, checked='checked') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20" style="width: 50%" title="{{lang.ha_page.return_master}}">
|
||||
{{lang.words.stay|title()}} {{lang.words.as}} {{lang.words.master|title()}}
|
||||
</td>
|
||||
<td>
|
||||
{{ checkbox('return_to_master', title=lang.ha_page.return_master) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
SYN-flood {{lang.words.protection}}
|
||||
</td>
|
||||
<td>
|
||||
{{ checkbox('syn_flood') }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20 help_cursor"><span title="{{lang.ha_page.try_install}} HAProxy">HAProxy</span></td>
|
||||
<td class="help_cursor">{{ checkbox('hap', title=lang.ha_page.try_install+' HAProxy') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20 help_cursor" style="display: none" id="haproxy_docker_td_header">
|
||||
<span title="{{lang.ha_page.try_install}} HAProxy {{lang.ha_page.as_docker}}">Docker</span>
|
||||
</td>
|
||||
<td class="help_cursor" style="display: none" id="haproxy_docker_td">
|
||||
{{ checkbox('hap_docker', title=lang.ha_page.try_install+' HAProxy '+lang.ha_page.as_docker) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20 help_cursor"><span title="{{lang.ha_page.try_install}} NGINX">NGINX</span></td>
|
||||
<td class="help_cursor">{{ checkbox('nginx', title=lang.ha_page.try_install+' NGINX') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20 help_cursor" style="display: none" id="nginx_docker_td_header">
|
||||
<span title="{{lang.ha_page.try_install}} NGINX {{lang.ha_page.as_docker}}">Docker</span>
|
||||
</td>
|
||||
<td class="help_cursor" style="display: none" id="nginx_docker_td">
|
||||
{{ checkbox('nginx_docker', title=lang.ha_page.try_install+' NGINX '+lang.ha_page.as_docker) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="alert alert-warning">
|
||||
{{lang.ha_page.save_apply|safe}}
|
||||
</div>
|
||||
</div>
|
||||
<div id="add-vip" style="display: none">
|
||||
<table class="overview" id="add-vip-table" title="{{lang.ha_page.add_vip}}" data-edit="{{lang.words.edit|title()}} VIP">
|
||||
<tr>
|
||||
<td class="padding20">
|
||||
VIP
|
||||
<span class="need-field">*</span>
|
||||
</td>
|
||||
<td>{{ input('vrrp-ip-add', size='14') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20">{{lang.words.servers|title()}}</td>
|
||||
<td id="vip_servers"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20" style="width: 50%" title="{{lang.ha_page.return_master}}">
|
||||
{{lang.words.stay|title()}} {{lang.words.as}} {{lang.words.master|title()}}
|
||||
</td>
|
||||
<td>
|
||||
{{ checkbox('vrrp-ip-add-return_to_master', title=lang.ha_page.return_master) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="padding20 help_cursor"><span title="{{lang.ha_page.create_virt_server}}">{{lang.words.add|title()}} VIRT {{lang.words.server}}</span></td>
|
||||
<td class="help_cursor">{{ checkbox('vrrp-ip-add-virt_server', title=lang.ha_page.create_virt_server, checked='checked') }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="dialog-confirm" style="display: none;">
|
||||
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>{{lang.phrases.are_you_sure}}</p>
|
||||
</div>
|
||||
<div id="server_creating1" style="display: none;" title="{{lang.phrases.creating_ha}}">
|
||||
<ul style="padding: 20px 20px 0px 20px;font-size: 15px;" id="server_creating_list"></ul>
|
||||
<div id="created-mess" class="alert alert-success" style="display:none;"></div>
|
||||
<div id="creating-error" class="alert alert-danger" style="display:none;"></div>
|
||||
<div id="creating-warning" class="alert alert-warning" style="display:none;"></div>
|
||||
<div id="wait-mess"></div>
|
||||
<div class="progress-bar-striped">
|
||||
<div id="creating-progress" style="width: 5%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
{% for cluster in clusters %}
|
||||
getHaCluster('{{cluster.id}}');
|
||||
{% endfor %}
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -10,6 +10,11 @@
|
|||
<nav id="menu">
|
||||
<ul class="menu">
|
||||
<li><a href="{{ url_for('overview.index') }}" title="{{lang.menu_links.overview.title}}" class="overview-link ">{{lang.menu_links.overview.link}}</a></li>
|
||||
{% if '5' in user_services %}
|
||||
{% if role <= 3 %}
|
||||
{% endif %}
|
||||
<li><a href="{{ url_for('ha.cluster_function', service='cluster') }}" title="{{lang.menu_links.ha.title}}" class="keepalived">HA {{lang.words.cluster}}</a></li>
|
||||
{% endif %}
|
||||
{% if '1' in user_services %}
|
||||
<li class="p_menu">
|
||||
<a href="{{ url_for('service.services', service='haproxy') }}" title="{{lang.menu_links.hapservers.haproxy.title}}" class="config-show">HAProxy</a>
|
||||
|
@ -96,9 +101,6 @@
|
|||
<li class="p_menu">
|
||||
<a href="{{ url_for('install.install_monitoring') }}" title="{{lang.menu_links.servers.title}}" class="hap-menu">{{lang.words.installation|title()}}</a>
|
||||
<ul class="v_menu">
|
||||
{% if '3' in user_services %}
|
||||
<li><a href="{{ url_for('install.ha') }}" title="{{lang.menu_links.ha.title}}" class="keepalived head-submenu">HA {{lang.words.cluster}}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{{ url_for('install.install_monitoring') }}#service" title="{{lang.words.servers|title()}}: {{lang.words.proxy|title()}} {{lang.words.services}} {{lang.words.installation}}" class="hap-menu service installproxy head-submenu">{{lang.words.proxy|title()}} {{lang.words.services}}</a> </li>
|
||||
<li><a href="{{ url_for('install.install_monitoring') }}#monitoring" title="{{lang.words.servers|title()}}: {{lang.words.monitoring|title()}} {{lang.words.services}} {{lang.words.installation}}" class="hap-menu monitoring installmon head-submenu">{{lang.words.monitoring|title()}}</a> </li>
|
||||
<li><a href="{{ url_for('install.install_monitoring') }}#geolite2" title="{{lang.words.installation|title()}} GeoLite2" class="hap-menu geolite2 installgeo head-submenu">GeoLite2</a> </li>
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
"title": "Add proxy: Create and upload whitelists or blacklists"
|
||||
},
|
||||
"ha": {
|
||||
"title": "Create and configure a high availability cluster"
|
||||
"title": "Create and configure a high availability cluster",
|
||||
},
|
||||
"monitoring": {
|
||||
"link": "Monitoring",
|
||||
|
@ -479,7 +479,28 @@
|
|||
}
|
||||
}
|
||||
%}
|
||||
{% set ha_page = {
|
||||
"ha": "High availability cluster",
|
||||
"has": "High availability clusters",
|
||||
"create_virt_server": "Roxy-WI will add VRRP address as a separate server",
|
||||
"return_master_desc": "Return to master",
|
||||
"return_master": "If this flag is checked, the Keepalived master will return VRRP when the service is running again",
|
||||
"try_install": "Roxy-WI will install",
|
||||
"as_docker": "as Docker container",
|
||||
"add_vip": "Add VIP to HA cluster",
|
||||
"create_ha": "Create high availability cluster",
|
||||
"start_enter": "Start typing the network interface name to add VIP",
|
||||
"roxywi_timeout": "Roxy-WI answer timeout",
|
||||
"check_apache_log": "Check <a href='/app/logs/internal' target='_blank' title='Internal logs'>Apache error log</a> for more information.",
|
||||
"was_installed": "was installed on",
|
||||
"start_enter": "Start typing into the network interface to add VIP",
|
||||
"save_apply": "<b>Save</b> - means saving the HA cluster settings for Roxy-WI, without changing the component settings on the cluster members. <br /> <b>Apply</b> - recreate the HA cluster configuration on the cluster member servers and install additional services.",
|
||||
}
|
||||
%}
|
||||
{% set words = {
|
||||
"apply": "apply",
|
||||
"true": "true",
|
||||
"false": "false",
|
||||
"cache": "cache",
|
||||
"compression": "compression",
|
||||
"acceleration": "acceleration",
|
||||
|
@ -771,6 +792,7 @@
|
|||
"diff3": "diff",
|
||||
"master": "master",
|
||||
"slave": "slave",
|
||||
"slaves": "slaves",
|
||||
"interface": "interface",
|
||||
"as": "as",
|
||||
"stay": "stay",
|
||||
|
|
|
@ -479,7 +479,28 @@
|
|||
}
|
||||
}
|
||||
%}
|
||||
{% set ha_page = {
|
||||
"ha": "La haute disponibilité cluster",
|
||||
"has": "La haute disponibilité clusters",
|
||||
"create_virt_server": "Roxy-WI ajoutera l'adresse VRRP en tant que serveur distinct",
|
||||
"return_master": "Si cet indicateur est coché, le maître Keepalived renverra VRRP lorsque le service sera à nouveau exécuté",
|
||||
"return_master_desc": "Retour au maître",
|
||||
"try_install": "Roxy-WI va installer",
|
||||
"as_docker": "comme conteneur Docker",
|
||||
"add_vip": "Ajouter un VIP au cluster HA",
|
||||
"create_ha": "Créer un cluster haute disponibilité",
|
||||
"start_enter": "Commencez à taper le nom de l'interface réseau pour ajouter VIP",
|
||||
"roxywi_timeout": "Délai d'attente de réponse Roxy-WI",
|
||||
"check_apache_log": "Consultez <a href='/app/logs/internal' target='_blank' title='Journaux internes'>le journal des erreurs Apache</a> pour plus d’informations.",
|
||||
"was_installed": "a été installé sur",
|
||||
"start_enter": "Commencez à taper dans l'interface réseau pour ajouter VIP",
|
||||
"save_apply": "<b>Enregistrer</b> - signifie enregistrer les paramètres du cluster HA pour Roxy-WI, sans modifier les paramètres des composants sur les membres du cluster. <br /> <b>Appliquer </b>: recréez la configuration du cluster HA sur les serveurs membres du cluster et installez des services supplémentaires.",
|
||||
}
|
||||
%}
|
||||
{% set words = {
|
||||
"apply": "appliquer",
|
||||
"true": "vrai",
|
||||
"false": "faux",
|
||||
"cache": "cache",
|
||||
"compression": "compression",
|
||||
"acceleration": "accélération",
|
||||
|
@ -770,7 +791,8 @@
|
|||
"diff2": "diff",
|
||||
"diff3": "diff",
|
||||
"master": "master",
|
||||
"slave": "slave",
|
||||
"slave": "esclave",
|
||||
"slaves": "des esclaves",
|
||||
"interface": "interface",
|
||||
"as": "comme",
|
||||
"stay": "rester",
|
||||
|
|
|
@ -479,7 +479,28 @@
|
|||
}
|
||||
}
|
||||
%}
|
||||
{% set ha_page = {
|
||||
"ha": "Alta disponibilidade cluster",
|
||||
"has": "Alta disponibilidade clusters",
|
||||
"create_virt_server": "Roxy-WI adicionará endereço VRRP como um servidor separado",
|
||||
"return_master": "Se este sinalizador estiver marcado, o mestre Keepalived retornará VRRP quando o serviço estiver em execução novamente",
|
||||
"return_master_desc": "Voltar ao mestre",
|
||||
"try_install": "Roxy-WI irá instalar",
|
||||
"as_docker": "como contêiner Docker",
|
||||
"add_vip": "Adicionar VIP ao cluster HA",
|
||||
"create_ha": "Criar cluster de alta disponibilidade",
|
||||
"start_enter": "Comece a digitar o nome da interface de rede para adicionar VIP",
|
||||
"roxywi_timeout": "Tempo limite de resposta do Roxy-WI",
|
||||
"check_apache_log": "Verifique <a href='/app/logs/internal' target='_blank' title='Registros internos'>o log de erros do Apache</a> para obter mais informações.",
|
||||
"was_installed": "foi instalado em",
|
||||
"start_enter": "Comece a digitar na interface de rede para adicionar VIP",
|
||||
"save_apply": "<b>Salvar</b> - significa salvar as configurações do cluster HA para Roxy-WI, sem alterar as configurações do componente nos membros do cluster. <br /> <b>Aplicar</b> – recrie a configuração do cluster HA nos servidores membros do cluster e instale serviços adicionais.",
|
||||
}
|
||||
%}
|
||||
{% set words = {
|
||||
"apply": "aplicar",
|
||||
"true": "verídico",
|
||||
"false": "falso",
|
||||
"cache": "cache",
|
||||
"compression": "compressão",
|
||||
"acceleration": "aceleração",
|
||||
|
@ -771,6 +792,7 @@
|
|||
"diff3": "diff",
|
||||
"master": "mestre",
|
||||
"slave": "escravo",
|
||||
"slaves": "escravos",
|
||||
"interface": "interface",
|
||||
"as": "como",
|
||||
"stay": "ficar",
|
||||
|
|
|
@ -479,7 +479,28 @@
|
|||
}
|
||||
}
|
||||
%}
|
||||
{% set ha_page = {
|
||||
"ha": "кластер высокой доступности",
|
||||
"has": "Кластера высокой доступности",
|
||||
"create_virt_server": "Roxy-WI добавит адрес VRRP в качестве отдельного сервера",
|
||||
"return_master": "Если этот флаг установлен, мастер Keepalived вернет VRRP, когда служба снова запустится",
|
||||
"return_master_desc": "Возврат мастера",
|
||||
"try_install": "Roxy-WI установит",
|
||||
"as_docker": "как Docker контейнер",
|
||||
"add_vip": "Добавить VIP в HA кластер",
|
||||
"create_ha": "Создать кластер высокой доступности",
|
||||
"start_enter": "Начните вводить имя сетевого интерфейса для добавления VIP",
|
||||
"roxywi_timeout": "Слишком долгий ответ Roxy-WI",
|
||||
"check_apache_log": "Проверьте <a href='/app/logs/internal' target='_blank' title='Внутренние логи'>журнал ошибок Apache</a> для получения дополнительной информации.",
|
||||
"was_installed": "был установлен на",
|
||||
"start_enter": "Начните вводить в сетевой интерфейс для добавления VIP",
|
||||
"save_apply": "<b>Сохранить</b> - подразумевает сохранение настроек HА кластера для Roxy-WI, без изменения настроек компонентов на участниках кластера. <br /> <b>Применить</b> - пересоздать конфигурацию HА кластера на серверах участниках кластера и установит дополнительные сервисы."
|
||||
}
|
||||
%}
|
||||
{% set words = {
|
||||
"apply": "применить",
|
||||
"true": "да",
|
||||
"false": "нет",
|
||||
"cache": "кэш",
|
||||
"compression": "сжатие",
|
||||
"acceleration": "ускорение",
|
||||
|
@ -771,6 +792,7 @@
|
|||
"diff3": "разницы",
|
||||
"master": "мастер",
|
||||
"slave": "подчиненный",
|
||||
"slaves": "подчиненные",
|
||||
"interface": "интерфейс",
|
||||
"as": "как",
|
||||
"stay": "оставаться",
|
||||
|
|
|
@ -16,3 +16,4 @@ python3-nmap<=1.5.1
|
|||
aio-pika>=7.1.0
|
||||
pika>=1.2.0
|
||||
websockets>=9.0
|
||||
ansible-runner==2.3.2
|
||||
|
|
|
@ -17,3 +17,4 @@ python3-nmap<=1.5.1
|
|||
aio-pika>=7.1.0
|
||||
pika>=1.2.0
|
||||
websockets>=9.0
|
||||
ansible-runner==2.3.2
|
||||
|
|
|
@ -18,3 +18,4 @@ python3-nmap<=1.5.1
|
|||
aio-pika>=7.1.0
|
||||
pika>=1.2.0
|
||||
websockets>=9.0
|
||||
ansible-runner==2.3.2
|
||||
|
|
|
@ -18,3 +18,4 @@ aio-pika>=7.1.0
|
|||
pika>=1.2.0
|
||||
websockets>=9.0
|
||||
tzlocal==2.0.0
|
||||
ansible-runner==2.3.2
|
||||
|
|
|
@ -1,21 +1,30 @@
|
|||
.padding20{ width: 160px;}
|
||||
.server-creating {padding-bottom: 10px;}
|
||||
.proccessing, .processing_error, .proccessing_done {font-weight: bold; color: var(--blue-color);}
|
||||
.proccessing_done {color: var(--green-color);}
|
||||
.proccessing, .processing_error {font-weight: bold; color: var(--green-color);}
|
||||
.proccessing::before {
|
||||
display: none;
|
||||
font-family: "Font Awesome 5 Solid";
|
||||
content: "\f35a";
|
||||
}
|
||||
.proccessing .fa-arrow-alt-circle-right {
|
||||
.proccessing_done::before {
|
||||
display: none;
|
||||
font-family: "Font Awesome 5 Solid";
|
||||
content: "\f058";
|
||||
}
|
||||
/*.proccessing .fa-arrow-alt-circle-right {*/
|
||||
/* padding-right: 10px !important;*/
|
||||
/* margin-bottom: -1px !important;*/
|
||||
/*}*/
|
||||
.proccessing .fa-arrow-alt-circle-right, .processing_error .svg-inline--fa {
|
||||
padding-right: 10px !important;
|
||||
margin-bottom: -1px !important;
|
||||
}
|
||||
.processing_error .svg-inline--fa {
|
||||
.proccessing_done .fa-check-circle {
|
||||
padding-right: 10px !important;
|
||||
margin-bottom: -1px !important;
|
||||
}
|
||||
.processing_error { color: red;}
|
||||
.processing_error { color: var(--red-color);}
|
||||
.processing_warning { color: #efba22;}
|
||||
.processing_error::before, .processing_warning::before {
|
||||
display: none;
|
||||
|
@ -90,3 +99,24 @@
|
|||
.first-collumn {
|
||||
width: 15%;
|
||||
}
|
||||
.fa-plus, .fa-edit, .fa-trash-alt {
|
||||
width: 3px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.fa-plus {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.delete {
|
||||
float: unset;
|
||||
margin: 0;
|
||||
}
|
||||
.checks {
|
||||
height: 100px;
|
||||
}
|
||||
.add-button-status-page {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.div-server-hapwi {
|
||||
height: 135px;
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
--light-blue-color: #d1ecf1;
|
||||
--menu-color: #06212a;
|
||||
--right-menu-blue-rolor: #5D9CEB;
|
||||
--yellow-color: #ffcc00;
|
||||
--border-radius: 3px;
|
||||
--indent: 15px;
|
||||
}
|
||||
|
@ -412,7 +413,7 @@ pre {
|
|||
padding-left: var(--indent);
|
||||
font-size: 15px;
|
||||
}
|
||||
.serverUp, .serverDown, .serverNone {
|
||||
.serverUp, .serverDown, .serverNone, .serverWarn {
|
||||
padding: 3px;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
|
@ -421,6 +422,9 @@ pre {
|
|||
.serverUp {
|
||||
background-color: var(--green-color);
|
||||
}
|
||||
.serverWarn {
|
||||
background-color: var(--yellow-color);
|
||||
}
|
||||
.serverNone {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
@ -1380,3 +1384,23 @@ label {
|
|||
position: relative;
|
||||
bottom: 3px;
|
||||
}
|
||||
@keyframes placeHolderShimmer {
|
||||
0% {
|
||||
background-position: -800px 0
|
||||
}
|
||||
100% {
|
||||
background-position: 800px 0
|
||||
}
|
||||
}
|
||||
|
||||
.animated-background {
|
||||
animation-duration: 2s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: placeHolderShimmer;
|
||||
animation-timing-function: linear;
|
||||
background-color: #f6f7f8;
|
||||
background: linear-gradient(to right, #eeeeee 8%, #bbbbbb 18%, #eeeeee 33%);
|
||||
background-size: 800px 104px;
|
||||
position: relative;
|
||||
}
|
195
inc/users.js
195
inc/users.js
|
@ -7,49 +7,43 @@ $( function() {
|
|||
var cancel_word = $('#translate').attr('data-cancel');
|
||||
$( "#backup_tabs" ).tabs();
|
||||
$('#install').click(function() {
|
||||
$("#ajax").html('')
|
||||
var syn_flood = 0;
|
||||
var docker = 0;
|
||||
if ($('#syn_flood').is(':checked')) {
|
||||
syn_flood = '1';
|
||||
}
|
||||
if ($('#haproxy_docker').is(':checked')) {
|
||||
docker = '1';
|
||||
}
|
||||
if ($('#haproxyaddserv').val() == '------' || $('#haproxyaddserv').val() === null) {
|
||||
var select_server = $('#translate').attr('data-select_server');
|
||||
toastr.warning(select_server);
|
||||
return false
|
||||
}
|
||||
$("#ajax").html(wait_mess);
|
||||
$.ajax({
|
||||
url: "/app/install/haproxy/" + $('#haproxyaddserv').val(),
|
||||
data: {
|
||||
syn_flood: syn_flood,
|
||||
hapver: $('#hapver option:selected').val(),
|
||||
docker: docker,
|
||||
token: $('#token').val()
|
||||
},
|
||||
type: "POST",
|
||||
success: function (data) {
|
||||
data = data.replace(/\s+/g, ' ');
|
||||
$("#ajax").html('')
|
||||
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
|
||||
var p_err = show_pretty_ansible_error(data);
|
||||
toastr.error(p_err);
|
||||
} else if (data.indexOf('success') != '-1') {
|
||||
toastr.remove();
|
||||
toastr.success(data);
|
||||
$("#haproxyaddserv").trigger("selectmenuchange");
|
||||
} else if (data.indexOf('Info') != '-1') {
|
||||
toastr.remove();
|
||||
toastr.info(data);
|
||||
} else {
|
||||
toastr.remove();
|
||||
toastr.info(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
// $("#ajax").html('')
|
||||
// var syn_flood = 0;
|
||||
// var docker = 0;
|
||||
// var jsonData = {'servers': {'0': {}}, 'services': {'haproxy': {}}};
|
||||
// if ($('#syn_flood').is(':checked')) {
|
||||
// syn_flood = '1';
|
||||
// }
|
||||
// if ($('#haproxy_docker').is(':checked')) {
|
||||
// docker = '1';
|
||||
// }
|
||||
// if ($('#haproxyaddserv').val() == '------' || $('#haproxyaddserv').val() === null) {
|
||||
// var select_server = $('#translate').attr('data-select_server');
|
||||
// toastr.warning(select_server);
|
||||
// return false
|
||||
// }
|
||||
// jsonData['syn_flood'] = syn_flood;
|
||||
// jsonData['servers']['0']['ip'] = $('#haproxyaddserv').val();
|
||||
// jsonData['servers']['0']['master'] = '0';
|
||||
// jsonData['servers']['0']['name'] = $('#haproxyaddserv option:selected').text();
|
||||
// jsonData['servers']['0']['version'] = $('#hapver option:selected').val();
|
||||
// jsonData['services']['haproxy']['enabled'] = 1;
|
||||
// jsonData['services']['haproxy']['docker'] = docker;
|
||||
// $("#ajax").html(wait_mess);
|
||||
// $.ajax({
|
||||
// url: "/app/install/haproxy/" + $('#haproxyaddserv').val(),
|
||||
// data: {
|
||||
// jsonData: JSON.stringify(jsonData),
|
||||
// token: $('#token').val()
|
||||
// },
|
||||
// type: "POST",
|
||||
// success: function (data) {
|
||||
// data = data.replace(/\s+/g, ' ');
|
||||
// parseAnsibleJsonOutput(data, 'HAProxy');
|
||||
// $("#haproxyaddserv").trigger("selectmenuchange");
|
||||
// }
|
||||
// });
|
||||
installService('haproxy')
|
||||
});
|
||||
$('#nginx_install').click(function() {
|
||||
installService('nginx');
|
||||
|
@ -2477,8 +2471,8 @@ function uploadOvpn() {
|
|||
toastr.error(data);
|
||||
} else if (data.indexOf('success') != '-1') {
|
||||
toastr.clear();
|
||||
toastr.success(data)
|
||||
location.reload()
|
||||
toastr.success(data);
|
||||
location.reload();
|
||||
} else {
|
||||
toastr.error('Something wrong, check and try again');
|
||||
}
|
||||
|
@ -2882,41 +2876,92 @@ function installService(service) {
|
|||
if ($('#' + service + '_docker').is(':checked')) {
|
||||
docker = '1';
|
||||
}
|
||||
if ($('#' + service + 'addserv').val() == '------') {
|
||||
if ($('#haproxyaddserv').val() == '------' || $('#' + service + 'addserv').val() === null) {
|
||||
var select_server = $('#translate').attr('data-select_server');
|
||||
toastr.warning(select_server);
|
||||
return false
|
||||
}
|
||||
var jsonData = {};
|
||||
jsonData['servers'] = {'0': {}}
|
||||
jsonData['services'] = {};
|
||||
jsonData['services'][service] = {};
|
||||
jsonData['syn_flood'] = syn_flood;
|
||||
jsonData['servers']['0']['ip'] = $('#' + service + 'addserv').val();
|
||||
jsonData['servers']['0']['master'] = '0';
|
||||
jsonData['servers']['0']['name'] = $('#' + service + 'addserv option:selected').text();
|
||||
if (service == 'haproxy') {
|
||||
jsonData['servers']['0']['version'] = $('#hapver option:selected').val();
|
||||
}
|
||||
console.log(jsonData)
|
||||
jsonData['services'][service]['enabled'] = 1;
|
||||
jsonData['services'][service]['docker'] = docker;
|
||||
var nice_names = {'haproxy': 'HAProxy', 'nginx': 'NGINX', 'apache': 'Apache'};
|
||||
$("#ajax").html(wait_mess);
|
||||
$.ajax({
|
||||
url: "/app/install/" + service + "/" + $('#' + service + 'addserv').val(),
|
||||
url: "/app/install/" + service,
|
||||
500: function () {
|
||||
showErrorStatus(ice_names[service], $('#' + service + 'addserv option:selected').text());
|
||||
},
|
||||
504: function () {
|
||||
showErrorStatus(ice_names[service], $('#' + service + 'addserv option:selected').text());
|
||||
},
|
||||
data: {
|
||||
syn_flood: syn_flood,
|
||||
docker: docker,
|
||||
jsonData: JSON.stringify(jsonData),
|
||||
token: $('#token').val()
|
||||
},
|
||||
type: "POST",
|
||||
success: function (data) {
|
||||
data = data.replace(/\s+/g, ' ');
|
||||
$("#ajax").html('')
|
||||
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
|
||||
toastr.clear();
|
||||
var p_err = show_pretty_ansible_error(data);
|
||||
toastr.error(p_err);
|
||||
} else if (data.indexOf('success') != '-1') {
|
||||
toastr.clear();
|
||||
toastr.success(data);
|
||||
$('#' + service + 'addserv').trigger("selectmenuchange");
|
||||
} else if (data.indexOf('Info') != '-1') {
|
||||
toastr.clear();
|
||||
toastr.info(data);
|
||||
} else {
|
||||
toastr.clear();
|
||||
toastr.info(data);
|
||||
}
|
||||
// data = data.replace(/\s+/g, ' ');
|
||||
parseAnsibleJsonOutput(data, nice_names[service]);
|
||||
$("#" + service + "yaddserv").trigger("selectmenuchange");
|
||||
}
|
||||
});
|
||||
}
|
||||
// function installService(service) {
|
||||
// $("#ajax").html('')
|
||||
// var syn_flood = 0;
|
||||
// var docker = 0;
|
||||
// if ($('#' + service + '_syn_flood').is(':checked')) {
|
||||
// syn_flood = '1';
|
||||
// }
|
||||
// if ($('#' + service + '_docker').is(':checked')) {
|
||||
// docker = '1';
|
||||
// }
|
||||
// if ($('#' + service + 'addserv').val() == '------') {
|
||||
// var select_server = $('#translate').attr('data-select_server');
|
||||
// toastr.warning(select_server);
|
||||
// return false
|
||||
// }
|
||||
// $("#ajax").html(wait_mess);
|
||||
// $.ajax({
|
||||
// url: "/app/install/" + service + "/" + $('#' + service + 'addserv').val(),
|
||||
// data: {
|
||||
// syn_flood: syn_flood,
|
||||
// docker: docker,
|
||||
// token: $('#token').val()
|
||||
// },
|
||||
// type: "POST",
|
||||
// success: function (data) {
|
||||
// data = data.replace(/\s+/g, ' ');
|
||||
// $("#ajax").html('')
|
||||
// if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
|
||||
// toastr.clear();
|
||||
// var p_err = show_pretty_ansible_error(data);
|
||||
// toastr.error(p_err);
|
||||
// } else if (data.indexOf('success') != '-1') {
|
||||
// toastr.clear();
|
||||
// toastr.success(data);
|
||||
// $('#' + service + 'addserv').trigger("selectmenuchange");
|
||||
// } else if (data.indexOf('Info') != '-1') {
|
||||
// toastr.clear();
|
||||
// toastr.info(data);
|
||||
// } else {
|
||||
// toastr.clear();
|
||||
// toastr.info(data);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
function showServiceVersion(service) {
|
||||
$.ajax({
|
||||
url: "/app/install/" + service + "/version/" + $('#' + service + 'addserv option:selected').val(),
|
||||
|
@ -3178,3 +3223,21 @@ function changeServerServices(server_id) {
|
|||
}
|
||||
});
|
||||
}
|
||||
function showErrorStatus(service_name, server) {
|
||||
var something_wrong = $('#translate').attr('data-something_wrong');
|
||||
toastr.error(something_wrong + ' ' + service_name + ' ' + server);
|
||||
}
|
||||
function parseAnsibleJsonOutput(output, service_name) {
|
||||
output = JSON.parse(JSON.stringify(output));
|
||||
var check_apache_log = $('#translate').attr('data-check_apache_log');
|
||||
var was_installed = $('#translate').attr('data-was_installed');
|
||||
for (var k in output['ok']) {
|
||||
toastr.success(service_name + ' ' + was_installed +' ' + k);
|
||||
}
|
||||
for (var k in output['failures']) {
|
||||
showErrorStatus(service_name, k);
|
||||
}
|
||||
for (var k in output['dark']) {
|
||||
showErrorStatus(service_name, k);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,3 +21,4 @@ Flask==2.2.5
|
|||
Flask-Login==0.6.2
|
||||
Flask-APScheduler==1.13.0
|
||||
Flask-Caching==2.1.0
|
||||
ansible-runner==2.3.2
|
||||
|
|
Loading…
Reference in New Issue