2023-09-17 09:42:39 +00:00
|
|
|
import os
|
|
|
|
|
2023-10-16 10:48:38 +00:00
|
|
|
from flask import render_template, request, g
|
2024-08-02 09:50:02 +00:00
|
|
|
from flask_jwt_extended import jwt_required, get_jwt
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
from app.routes.config import bp
|
2023-09-30 08:48:54 +00:00
|
|
|
import app.modules.db.sql as sql
|
2024-03-03 07:11:48 +00:00
|
|
|
import app.modules.db.config as config_sql
|
|
|
|
import app.modules.db.server as server_sql
|
|
|
|
import app.modules.db.service as service_sql
|
2024-04-04 11:30:07 +00:00
|
|
|
from app.middleware import check_services, get_user_params
|
2023-09-30 08:48:54 +00:00
|
|
|
import app.modules.common.common as common
|
|
|
|
import app.modules.roxywi.auth as roxywi_auth
|
|
|
|
import app.modules.roxywi.common as roxywi_common
|
|
|
|
import app.modules.config.config as config_mod
|
2024-02-04 07:28:17 +00:00
|
|
|
import app.modules.config.common as config_common
|
2023-09-30 08:48:54 +00:00
|
|
|
import app.modules.config.section as section_mod
|
|
|
|
import app.modules.service.haproxy as service_haproxy
|
|
|
|
import app.modules.server.server as server_mod
|
2024-08-20 07:39:40 +00:00
|
|
|
from app.views.service.views import ServiceConfigView, ServiceConfigVersionsView
|
2024-08-05 07:29:46 +00:00
|
|
|
from app.modules.roxywi.class_models import DataStrResponse
|
2024-08-02 09:50:02 +00:00
|
|
|
|
|
|
|
bp.add_url_rule('/<service>/<server_id>', view_func=ServiceConfigView.as_view('config_view_ip'), methods=['POST'])
|
2024-08-20 07:39:40 +00:00
|
|
|
bp.add_url_rule('/<service>/<server_id>/versions', view_func=ServiceConfigVersionsView.as_view('config_version'), methods=['DELETE'])
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.before_request
|
2024-08-02 09:50:02 +00:00
|
|
|
@jwt_required()
|
2023-09-17 09:42:39 +00:00
|
|
|
def before_request():
|
2024-02-04 07:28:17 +00:00
|
|
|
""" Protect all the admin endpoints. """
|
2023-09-17 09:42:39 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/<service>/show', methods=['POST'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def show_config(service):
|
2024-09-01 17:51:12 +00:00
|
|
|
config_file_name = request.json.get('config_file_name')
|
|
|
|
configver = request.json.get('configver')
|
|
|
|
server_ip = request.json.get('serv')
|
2024-08-02 09:50:02 +00:00
|
|
|
claims = get_jwt()
|
2023-09-17 09:42:39 +00:00
|
|
|
|
2024-09-01 17:51:12 +00:00
|
|
|
try:
|
|
|
|
data = config_mod.show_config(server_ip, service, config_file_name, configver, claims)
|
|
|
|
return DataStrResponse(data=data).model_dump(mode='json'), 200
|
|
|
|
except Exception as e:
|
|
|
|
return roxywi_common.handler_exceptions_for_json_data(e, '')
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/<service>/show-files', methods=['POST'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def show_config_files(service):
|
|
|
|
server_ip = request.form.get('serv')
|
|
|
|
config_file_name = request.form.get('config_file_name')
|
|
|
|
|
2024-09-01 17:51:12 +00:00
|
|
|
try:
|
|
|
|
return config_mod.show_config_files(server_ip, service, config_file_name)
|
|
|
|
except Exception as e:
|
|
|
|
return f'error: {e}'
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/<service>/find-in-config', methods=['POST'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def find_in_config(service):
|
|
|
|
server_ip = common.is_ip_or_dns(request.form.get('serv'))
|
|
|
|
finding_words = request.form.get('words')
|
|
|
|
log_path = sql.get_setting(service + '_dir')
|
|
|
|
log_path = common.return_nice_path(log_path)
|
2024-03-03 07:11:48 +00:00
|
|
|
commands = f'sudo grep "{finding_words}" {log_path}*/*.conf -C 2 -Rn'
|
2023-09-17 09:42:39 +00:00
|
|
|
try:
|
|
|
|
return_find = server_mod.ssh_command(server_ip, commands, raw=1)
|
|
|
|
return_find = config_mod.show_finding_in_config(return_find, grep=finding_words)
|
|
|
|
except Exception as e:
|
|
|
|
return str(e)
|
|
|
|
|
|
|
|
if 'error: ' in return_find:
|
|
|
|
return return_find
|
|
|
|
|
|
|
|
return return_find
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/<service>/', defaults={'serv': None, 'edit': None, 'config_file_name': None, 'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/<edit>/', defaults={'config_file_name': None, 'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/show', defaults={'edit': None, 'config_file_name': None, 'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/show/<config_file_name>', defaults={'edit': None, 'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/show-files', defaults={'edit': None, 'config_file_name': None, 'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/<edit>/<config_file_name>', defaults={'new': None}, methods=['GET', 'POST'])
|
|
|
|
@bp.route('/<service>/<serv>/<edit>/<config_file_name>/<new>', methods=['GET', 'POST'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params(0)
|
2023-09-17 09:42:39 +00:00
|
|
|
def config(service, serv, edit, config_file_name, new):
|
|
|
|
config_read = ""
|
|
|
|
cfg = ""
|
|
|
|
error = ""
|
|
|
|
is_restart = ''
|
|
|
|
is_serv_protected = ''
|
|
|
|
new_config = new
|
|
|
|
|
|
|
|
if serv and edit and new_config is None:
|
|
|
|
roxywi_common.check_is_server_in_group(serv)
|
2024-03-03 07:11:48 +00:00
|
|
|
is_serv_protected = server_sql.is_serv_protected(serv)
|
|
|
|
server_id = server_sql.select_server_id_by_ip(serv)
|
|
|
|
is_restart = service_sql.select_service_setting(server_id, service, 'restart')
|
2024-09-01 19:39:57 +00:00
|
|
|
cfg = config_mod.return_cfg(service, serv, config_file_name)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
error = config_mod.get_config(serv, cfg, service=service, config_file_name=config_file_name)
|
|
|
|
except Exception as e:
|
2023-10-16 10:12:36 +00:00
|
|
|
return f'error: Cannot download config: {e}'
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
roxywi_common.logging(serv, f" {service.title()} config has been opened")
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
|
|
|
conf = open(cfg, "r")
|
|
|
|
config_read = conf.read()
|
|
|
|
conf.close()
|
|
|
|
except IOError as e:
|
|
|
|
return f'Cannot read imported config file {e}', 200
|
|
|
|
|
|
|
|
os.system("/bin/mv %s %s.old" % (cfg, cfg))
|
|
|
|
|
|
|
|
if new_config is not None:
|
|
|
|
config_read = ' '
|
|
|
|
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
|
|
|
'serv': serv,
|
|
|
|
'aftersave': '',
|
|
|
|
'config': config_read,
|
|
|
|
'cfg': cfg,
|
|
|
|
'stderr': '',
|
|
|
|
'error': error,
|
|
|
|
'service': service,
|
|
|
|
'is_restart': is_restart,
|
|
|
|
'config_file_name': config_file_name,
|
|
|
|
'is_serv_protected': is_serv_protected,
|
2024-03-03 07:11:48 +00:00
|
|
|
'service_desc': service_sql.select_service(service),
|
2024-01-17 06:08:27 +00:00
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
|
|
|
|
|
|
|
return render_template('config.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
2024-08-20 07:39:40 +00:00
|
|
|
@bp.route('/versions/<service>', defaults={'server_ip': None}, methods=['GET'])
|
|
|
|
@bp.route('/versions/<service>/<server_ip>', methods=['GET'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params(disable=1)
|
2023-09-17 09:42:39 +00:00
|
|
|
def versions(service, server_ip):
|
|
|
|
roxywi_auth.page_for_admin(level=3)
|
|
|
|
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
|
|
|
'serv': server_ip,
|
|
|
|
'service': service,
|
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
|
|
|
return render_template('delver.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/version/<service>/list', methods=['POST'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def list_of_version(service):
|
|
|
|
server_ip = common.is_ip_or_dns(request.form.get('serv'))
|
2024-08-02 09:50:02 +00:00
|
|
|
config_ver = common.checkAjaxInput(request.form.get('configver'))
|
2023-09-17 09:42:39 +00:00
|
|
|
for_delver = common.checkAjaxInput(request.form.get('for_delver'))
|
|
|
|
|
2024-08-02 09:50:02 +00:00
|
|
|
return config_mod.list_of_versions(server_ip, service, config_ver, for_delver)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
2024-08-20 07:39:40 +00:00
|
|
|
@bp.route('/versions/<service>/<server_ip>/<configver>', methods=['GET'])
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params(disable=1)
|
2024-08-20 07:39:40 +00:00
|
|
|
def show_version(service, server_ip, configver):
|
2023-09-17 09:42:39 +00:00
|
|
|
roxywi_auth.page_for_admin(level=3)
|
|
|
|
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
|
|
|
'serv': server_ip,
|
|
|
|
'service': service,
|
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
|
|
|
|
|
|
|
return render_template('configver.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
2024-08-20 07:39:40 +00:00
|
|
|
@bp.route('/versions/<service>/<server_ip>/<configver>/save', methods=['POST'])
|
|
|
|
@check_services
|
|
|
|
@get_user_params()
|
|
|
|
def save_version(service, server_ip, configver):
|
|
|
|
roxywi_auth.page_for_admin(level=3)
|
|
|
|
config_dir = config_common.get_config_dir('haproxy')
|
|
|
|
configver = config_dir + configver
|
|
|
|
service_desc = service_sql.select_service(service)
|
|
|
|
save_action = request.json.get('action')
|
|
|
|
try:
|
|
|
|
roxywi_common.logging(
|
|
|
|
server_ip, f"Version of config has been uploaded {configver}", login=1, keep_history=1, service=service
|
|
|
|
)
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if service == 'keepalived':
|
|
|
|
stderr = config_mod.upload_and_restart(server_ip, configver, save_action, service)
|
|
|
|
elif service in ('nginx', 'apache'):
|
|
|
|
config_file_name = config_sql.select_remote_path_from_version(server_ip=server_ip, service=service, local_path=configver)
|
|
|
|
stderr = config_mod.master_slave_upload_and_restart(server_ip, configver, save_action, service_desc.slug, config_file_name=config_file_name)
|
|
|
|
else:
|
|
|
|
stderr = config_mod.master_slave_upload_and_restart(server_ip, configver, save_action, service)
|
|
|
|
|
|
|
|
return DataStrResponse(data=stderr).model_dump(mode='json'), 201
|
|
|
|
|
|
|
|
|
2023-09-17 09:42:39 +00:00
|
|
|
@bp.route('/section/haproxy/<server_ip>')
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params()
|
2023-09-17 09:42:39 +00:00
|
|
|
def haproxy_section(server_ip):
|
2024-02-04 07:28:17 +00:00
|
|
|
cfg = config_common.generate_config_path('haproxy', server_ip)
|
2023-09-17 09:42:39 +00:00
|
|
|
error = config_mod.get_config(server_ip, cfg)
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
|
|
|
'is_restart': 0,
|
|
|
|
'config': '',
|
|
|
|
'serv': server_ip,
|
|
|
|
'sections': section_mod.get_sections(cfg),
|
|
|
|
'error': error,
|
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
2023-09-17 09:42:39 +00:00
|
|
|
|
2024-01-17 06:08:27 +00:00
|
|
|
return render_template('sections.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/section/haproxy/<server_ip>/<section>')
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params()
|
2023-09-17 09:42:39 +00:00
|
|
|
def haproxy_section_show(server_ip, section):
|
2024-02-04 07:28:17 +00:00
|
|
|
cfg = config_common.generate_config_path('haproxy', server_ip)
|
2023-09-17 09:42:39 +00:00
|
|
|
error = config_mod.get_config(server_ip, cfg)
|
|
|
|
start_line, end_line, config_read = section_mod.get_section_from_config(cfg, section)
|
2024-03-03 07:11:48 +00:00
|
|
|
server_id = server_sql.select_server_id_by_ip(server_ip)
|
2024-01-17 06:08:27 +00:00
|
|
|
sections = section_mod.get_sections(cfg)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
os.system(f"/bin/mv {cfg} {cfg}.old")
|
|
|
|
|
2023-10-16 10:12:36 +00:00
|
|
|
try:
|
|
|
|
roxywi_common.logging(server_ip, f"A section {section} has been opened")
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
2024-03-03 07:11:48 +00:00
|
|
|
'is_restart': service_sql.select_service_setting(server_id, 'haproxy', 'restart'),
|
2024-01-17 06:08:27 +00:00
|
|
|
'serv': server_ip,
|
|
|
|
'sections': sections,
|
|
|
|
'cfg': cfg,
|
|
|
|
'config': config_read,
|
|
|
|
'start_line': start_line,
|
|
|
|
'end_line': end_line,
|
|
|
|
'section': section,
|
|
|
|
'error': error,
|
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
|
|
|
|
|
|
|
return render_template('sections.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/section/haproxy/<server_ip>/save', methods=['POST'])
|
2024-07-08 12:53:05 +00:00
|
|
|
@get_user_params()
|
2023-09-17 09:42:39 +00:00
|
|
|
def haproxy_section_save(server_ip):
|
2024-02-04 07:28:17 +00:00
|
|
|
hap_configs_dir = config_common.get_config_dir('haproxy')
|
|
|
|
cfg = config_common.generate_config_path('haproxy', server_ip)
|
2024-08-05 07:29:46 +00:00
|
|
|
config_file = request.json.get('config')
|
|
|
|
oldcfg = request.json.get('oldconfig')
|
|
|
|
save = request.json.get('action')
|
|
|
|
start_line = request.json.get('start_line')
|
|
|
|
end_line = request.json.get('end_line')
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
if save == 'delete':
|
2023-10-07 18:48:23 +00:00
|
|
|
config_file = ''
|
2023-09-17 09:42:39 +00:00
|
|
|
save = 'reload'
|
|
|
|
|
2023-10-07 18:48:23 +00:00
|
|
|
config_file = section_mod.rewrite_section(start_line, end_line, oldcfg, config_file)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
with open(cfg, "w") as conf:
|
2023-10-07 18:48:23 +00:00
|
|
|
conf.write(config_file)
|
2023-09-17 09:42:39 +00:00
|
|
|
except IOError as e:
|
|
|
|
return f"error: Cannot read import config file: {e}"
|
|
|
|
|
|
|
|
stderr = config_mod.master_slave_upload_and_restart(server_ip, cfg, save, 'haproxy', oldcfg=oldcfg)
|
|
|
|
|
|
|
|
config_mod.diff_config(oldcfg, cfg)
|
|
|
|
|
2024-02-04 07:28:17 +00:00
|
|
|
try:
|
|
|
|
os.remove(f"{hap_configs_dir}*.old")
|
|
|
|
except IOError:
|
|
|
|
pass
|
2023-09-17 09:42:39 +00:00
|
|
|
|
2024-08-05 07:29:46 +00:00
|
|
|
return DataStrResponse(data=stderr).model_dump(mode='json'), 201
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/compare/<service>/<serv>')
|
|
|
|
@bp.route('/map/<service>/<serv>')
|
2023-10-16 10:12:36 +00:00
|
|
|
@get_user_params()
|
2023-09-17 09:42:39 +00:00
|
|
|
def show_compare_config(service, serv):
|
2024-01-17 06:08:27 +00:00
|
|
|
kwargs = {
|
|
|
|
'aftersave': '',
|
|
|
|
'serv': serv,
|
|
|
|
'cfg': '',
|
|
|
|
'config': '',
|
|
|
|
'config_file_name': '',
|
|
|
|
'is_serv_protected': '',
|
|
|
|
'is_restart': '',
|
|
|
|
'service': service,
|
|
|
|
'stderr': '',
|
|
|
|
'error': '',
|
2024-03-03 07:11:48 +00:00
|
|
|
'service_desc': service_sql.select_service(service),
|
2024-01-17 06:08:27 +00:00
|
|
|
'lang': g.user_params['lang']
|
|
|
|
}
|
|
|
|
|
|
|
|
return render_template('config.html', **kwargs)
|
2023-09-17 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/compare/<service>/<server_ip>/files')
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def show_configs_for_compare(service, server_ip):
|
|
|
|
return config_mod.show_compare_config(server_ip, service)
|
|
|
|
|
|
|
|
|
2023-10-16 10:12:36 +00:00
|
|
|
@bp.post('/compare/<service>/<server_ip>/show')
|
2023-10-03 19:56:34 +00:00
|
|
|
@check_services
|
2023-09-17 09:42:39 +00:00
|
|
|
def show_compare(service, server_ip):
|
|
|
|
left = common.checkAjaxInput(request.form.get('left'))
|
|
|
|
right = common.checkAjaxInput(request.form.get('right'))
|
|
|
|
|
|
|
|
return config_mod.compare_config(service, left, right)
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/map/haproxy/<server_ip>/show')
|
|
|
|
def show_map(server_ip):
|
|
|
|
return service_haproxy.show_map(server_ip)
|