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"
 | 
			
		||||
| 
						 | 
				
			
			@ -149,8 +144,8 @@ def logging(server_ip: str, action: str, **kwargs) -> None:
 | 
			
		|||
	if kwargs.get('keep_history'):
 | 
			
		||||
		try:
 | 
			
		||||
			keep_action_history(kwargs.get('service'), action, server_ip, login, ip)
 | 
			
		||||
			except Exception:
 | 
			
		||||
				pass
 | 
			
		||||
		except Exception as e:
 | 
			
		||||
			print(f'error: Cannot save history: {e}')
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		with open(log_file, 'a') as log:
 | 
			
		||||
| 
						 | 
				
			
			@ -160,9 +155,6 @@ 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:
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +162,14 @@ def keep_action_history(service: str, action: str, server_ip: str, login: str, u
 | 
			
		|||
	if user_ip == '':
 | 
			
		||||
		user_ip = 'localhost'
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
| 
						 | 
				
			
			@ -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')
 | 
			
		||||
	syn_flood_protect = str(json_data['syn_flood'])
 | 
			
		||||
	routers = {}
 | 
			
		||||
	vips = sql.select_cluster_vips(cluster_id)
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
	return inv, server_ips
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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')
 | 
			
		||||
	proxy_serv = ''
 | 
			
		||||
	ssh_settings = return_ssh_keys_path(master)
 | 
			
		||||
	full_path = '/var/www/haproxy-wi/app'
 | 
			
		||||
	service = 'master 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
 | 
			
		||||
 | 
			
		||||
		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} "
 | 
			
		||||
		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']}"
 | 
			
		||||
	]
 | 
			
		||||
	result = ansible_runner.run(**kwargs)
 | 
			
		||||
	stats = result.stats
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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"
 | 
			
		||||
	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'
 | 
			
		||||
 | 
			
		||||
	if proxy is not None and proxy != '' and proxy != 'None':
 | 
			
		||||
		proxy_serv = proxy
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		os.system(f"cp {full_path}/scripts/{script} {full_path}/{script}")
 | 
			
		||||
	except Exception as e:
 | 
			
		||||
		raise Exception(f'error: {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']}"
 | 
			
		||||
	]
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
        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)
 | 
			
		||||
    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}'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<service>/version/<server_ip>')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -151,10 +151,13 @@ 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')
 | 
			
		||||
        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':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,30 @@
 | 
			
		|||
/var/log/haproxy.log {
 | 
			
		||||
/var/log/haproxy/access.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/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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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: check if Keepalived is installed
 | 
			
		||||
  package_facts:
 | 
			
		||||
    manager: "auto"
 | 
			
		||||
 | 
			
		||||
- name: Add installation tasks
 | 
			
		||||
  include_tasks: install.yml
 | 
			
		||||
  when: (ADD_VRRP is not defined) or (ADD_VRRP != "1")
 | 
			
		||||
- 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: Add add vrrp tasks
 | 
			
		||||
  include_tasks: add_vrrp.yml
 | 
			
		||||
  when: (ADD_VRRP is defined) and (ADD_VRRP|length > 0)
 | 
			
		||||
- 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 }}"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{%- if NGINX %}
 | 
			
		||||
#NGINX health-check for keepalive
 | 
			
		||||
vrrp_script chk_nginx {
 | 
			
		||||
    script "systemctl is-active --quiet nginx"
 | 
			
		||||
    interval 2
 | 
			
		||||
    weight 3
 | 
			
		||||
}
 | 
			
		||||
vrrp_instance VI_1 {
 | 
			
		||||
    state {{MASTER}}
 | 
			
		||||
    interface {% if MASTER == 'MASTER' %}{{ETH}} {% else %} {{ETH_SLAVE}} {% endif %}
 | 
			
		||||
{% 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 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