Pavel Loginov 2021-12-03 16:39:15 +06:00
parent 59d5a8c0b0
commit e99fc6b5ea
11 changed files with 590 additions and 45 deletions

View File

@ -53,13 +53,14 @@ def index():
'haproxy/<id,hostname,ip>/action/start':'start HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/action/start':'start HAProxy service by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/action/stop':'stop HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/action/stop':'stop HAProxy service by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/action/restart':'restart HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/action/restart':'restart HAProxy service by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/config':'get HAProxy config from the server by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/config':'get HAProxy config from a server by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/log':'show HAProxy log by id or hostname or ip. May to have config next headers: rows(format INT) default: 10 grep, waf(if needs WAF log) default: 0, start_hour(format: 24) default: 00, start_minute, end_hour(format: 24) default: 24, end_minute. METHOD: GET', 'haproxy/<id,hostname,ip>/config':'upload HAProxy config to a server by id or hostname or ip. Body must consist a whole HAProxy config. METHOD: POST',
'haproxy/<id,hostname,ip>/section':'show certain section, headers: section-name. METHOD: GET', 'haproxy/<id,hostname,ip>/log':'show HAProxy logs by id or hostname or ip. May to have config next headers: rows(format INT) default: 10 grep, waf(if needs WAF log) default: 0, start_hour(format: 24) default: 00, start_minute, end_hour(format: 24) default: 24, end_minute. METHOD: GET',
'haproxy/<id,hostname,ip>/section/add':'add section to the HAProxy config by id or hostname or ip. Has to have config header with section and action header for action after upload. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST', 'haproxy/<id,hostname,ip>/section':'show a certain section, headers: section-name. METHOD: GET',
'haproxy/<id,hostname,ip>/section/edit':'edit section in the HAProxy config by id or hostname or ip. Has to have config header with section, action header for action after upload and body of a new section configuration. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST', 'haproxy/<id,hostname,ip>/section/add':'add a section to the HAProxy config by id or hostname or ip. Has to have config header with section and action header for action after upload. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST',
'haproxy/<id,hostname,ip>/acl':'add acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: POST', 'haproxy/<id,hostname,ip>/section/edit':'edit a section in the HAProxy config by id or hostname or ip. Has to have config header with section, action header for action after upload and body of a new section configuration. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST',
'haproxy/<id,hostname,ip>/acl':'delete acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: DELETE' 'haproxy/<id,hostname,ip>/acl':'add an acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: POST',
'haproxy/<id,hostname,ip>/acl':'delete an acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: DELETE'
} }
return dict(help=data) return dict(help=data)
@ -152,14 +153,14 @@ def callback(haproxy_id):
if not check_login(required_service=1): if not check_login(required_service=1):
return dict(error=_error_auth) return dict(error=_error_auth)
return api_funct.get_config(haproxy_id) return api_funct.get_config(haproxy_id)
#
#
# @route('/haproxy/<haproxy_id>/config', method=['POST']) @route('/haproxy/<haproxy_id>/config', method=['POST'])
# @route('/haproxy/<haproxy_id:int>/config', method=['POST']) @route('/haproxy/<haproxy_id:int>/config', method=['POST'])
# def callback(haproxy_id): def callback(haproxy_id):
# if not check_login(required_service=1): if not check_login(required_service=1):
# return dict(error=_error_auth) return dict(error=_error_auth)
# return api_funct.upload_config(haproxy_id) return api_funct.upload_config(haproxy_id)
@route('/haproxy/<haproxy_id>/log', method=['GET']) @route('/haproxy/<haproxy_id>/log', method=['GET'])

View File

@ -274,7 +274,7 @@ def edit_section(server_id):
os.system("/bin/cp %s %s" % (cfg, cfg_for_save)) os.system("/bin/cp %s %s" % (cfg, cfg_for_save))
out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login) out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login)
funct.logging('localhost', " section " + section_name + " has been edited via API", login=login) funct.logging('localhost', " section " + section_name + " has been edited via API", login=login)
funct.logging(ip, 'section ' + section_name + ' has been edited via API', haproxywi=1, login=login, funct.logging(ip, 'Section ' + section_name + ' has been edited via API', haproxywi=1, login=login,
keep_history=1, service='haproxy') keep_history=1, service='haproxy')
if out: if out:
@ -320,7 +320,7 @@ def upload_config(server_id):
os.system("/bin/cp %s %s" % (cfg, cfg_for_save)) os.system("/bin/cp %s %s" % (cfg, cfg_for_save))
out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login) out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login)
funct.logging('localhost', " config has been uploaded via API", login=login) funct.logging('localhost', " config has been uploaded via API", login=login)
funct.logging(ip, 'config has been uploaded via API', haproxywi=1, login=login, funct.logging(ip, 'Config has been uploaded via API', haproxywi=1, login=login,
keep_history=1, service='haproxy') keep_history=1, service='haproxy')
if out: if out:

View File

@ -859,7 +859,7 @@ def update_db_v_5_3_2_2(**kwargs):
def update_ver(): def update_ver():
query = Version.update(version='5.3.3.0') query = Version.update(version='5.3.4.0')
try: try:
query.execute() query.execute()
except: except:

View File

@ -454,9 +454,24 @@ class ConfigVersion(BaseModel):
class Meta: class Meta:
table_name = 'config_versions' table_name = 'config_versions'
class SystemInfo(BaseModel):
id = AutoField()
server_id = IntegerField()
os_info = CharField()
sys_info = CharField()
cpu = CharField()
ram = CharField()
disks = CharField()
network = TextField()
class Meta:
table_name = 'system_info'
def create_tables(): def create_tables():
with conn: with conn:
conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion, conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion,
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory, Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory,
PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds, ServiceSetting, PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds, ServiceSetting,
ProvisionedServers, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes, NginxMetrics]) ProvisionedServers, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes, NginxMetrics,
SystemInfo])

View File

@ -440,11 +440,15 @@ def get_config(server_ip, cfg, **kwargs):
sftp = ssh.open_sftp() sftp = ssh.open_sftp()
except Exception as e: except Exception as e:
logging('localhost', str(e), haproxywi=1) logging('localhost', str(e), haproxywi=1)
sftp.close()
ssh.close()
return return
try: try:
sftp.get(config_path, cfg) sftp.get(config_path, cfg)
except Exception as e: except Exception as e:
logging('localhost', str(e), haproxywi=1) logging('localhost', str(e), haproxywi=1)
sftp.close()
ssh.close()
return return
try: try:
sftp.close() sftp.close()
@ -1523,10 +1527,28 @@ def check_is_server_in_group(server_ip):
def check_service(server_ip, service_name): def check_service(server_ip, service_name):
server_ip = is_ip_or_dns(server_ip)
commands = ["systemctl is-active "+service_name] commands = ["systemctl is-active "+service_name]
return ssh_command(server_ip, commands) return ssh_command(server_ip, commands)
def get_service_version(server_ip, service_name):
server_ip = is_ip_or_dns(server_ip)
if service_name == 'haproxy_exporter':
commands = [ "/opt/prometheus/exporters/haproxy_exporter --version 2>&1 |head -1|awk '{print $3}'"]
elif service_name == 'nginx_exporter':
commands = ["/opt/prometheus/exporters/nginx_exporter 2>&1 |head -1 |awk -F\"=\" '{print $2}'|awk '{print $1}'"]
elif service_name == 'node_exporter':
commands = ["node_exporter --version 2>&1 |head -1|awk '{print $3}'"]
ver = ssh_command(server_ip, commands)
if ver != '':
return ver
else:
return 'no'
def get_services_status(): def get_services_status():
import distro import distro
services = [] services = []
@ -1586,3 +1608,183 @@ def is_service_active(server_ip: str, service_name: str):
out = ssh_command(server_ip, cmd) out = ssh_command(server_ip, cmd)
out = out.strip() out = out.strip()
return True if 'active' == out else False return True if 'active' == out else False
def get_system_info(server_ip: str) -> bool:
import json
import sql
server_ip = is_ip_or_dns(server_ip)
if server_ip == '':
return False
server_id = sql.select_server_id_by_ip(server_ip)
command = ["sudo lshw -quiet -json"]
sys_info_returned = ssh_command(server_ip, command)
command = ['sudo hostnamectl |grep "Operating System"|awk -F":" \'{print $2}\'']
os_info = ssh_command(server_ip, command)
os_info = os_info.strip()
system_info = json.loads(sys_info_returned)
sys_info = {'hostname': system_info['id'], 'family': ''}
cpu = {'cpu_model': '', 'cpu_core': 0, 'cpu_thread': 0, 'hz': 0}
network = {}
ram = {'slots': 0, 'size': 0}
disks = {}
try:
sys_info['family'] = system_info['configuration']['family']
except Exception:
pass
for i in system_info['children']:
if i['class'] == 'network':
try:
ip = i['configuration']['ip']
except Exception:
ip = ''
network[i['logicalname']] = {'description': i['description'],
'mac': i['serial'],
'ip': ip}
for k, j in i.items():
if isinstance(j, list):
for b in j:
try:
if b['class'] == 'processor':
cpu['cpu_model'] = b['product']
cpu['cpu_core'] += 1
cpu['hz'] = round(int(b['capacity']) / 1000000)
try:
cpu['cpu_thread'] += int(b['configuration']['threads'])
except Exception:
cpu['cpu_thread'] = 1
except Exception:
pass
try:
if b['id'] == 'memory':
ram['size'] = round(b['size'] / 1073741824)
for memory in b['children']:
ram['slots'] += 1
except Exception:
pass
try:
if b['class'] == 'bridge':
if 'children' in b:
for s in b['children']:
if s['class'] == 'network':
if 'children' in s:
for net in s['children']:
network[net['logicalname']] = {'description': net['description'],
'mac': net['serial']}
if s['class'] == 'storage':
for p, pval in s.items():
if isinstance(pval, list):
for disks_info in pval:
if 'children' in disks_info:
for volume_info in disks_info['children']:
if isinstance(volume_info['logicalname'], dict):
volume_name = volume_info['logicalname'][0]
mount_point = volume_info['logicalname'][1]
size = round(volume_info['size'] / 1073741824)
size = str(size) + 'Gb'
fs = volume_info['configuration']['mount.fstype']
state = volume_info['configuration']['state']
disks[volume_name] = {'mount_point': mount_point,
'size': size,
'fs': fs,
'state': state}
for z, n in s.items():
if isinstance(n, list):
for y in n:
if y['class'] == 'network':
try:
for q in y['children']:
try:
ip = q['configuration']['ip']
except Exception:
ip = ''
network[q['logicalname']] = {
'description': q['description'],
'mac': q['serial'],
'ip': ip}
except Exception:
try:
network[y['logicalname']] = {
'description': y['description'],
'mac': y['serial'],
'ip': y['configuration']['ip']}
except Exception:
pass
if y['class'] == 'disk':
try:
for q in y['children']:
try:
if isinstance(q['logicalname'], list):
volume_name = q['logicalname'][0]
mount_point = q['logicalname'][1]
size = round(q['capacity'] / 1073741824)
size = str(size) + 'Gb'
fs = q['configuration']['mount.fstype']
state = q['configuration']['state']
disks[volume_name] = {'mount_point': mount_point,
'size': size,
'fs': fs,
'state': state}
except Exception as e:
print(e)
except Exception:
pass
if y['class'] == 'storage' or y['class'] == 'generic':
try:
for q in y['children']:
for o in q['children']:
for w in o['children']:
try:
if isinstance(w['logicalname'], list):
volume_name = w['logicalname'][0]
mount_point = w['logicalname'][1]
size = round(w['size'] / 1073741824)
size = str(size) + 'Gb'
fs = w['configuration']['mount.fstype']
state = w['configuration']['state']
disks[volume_name] = {
'mount_point': mount_point,
'size': size,
'fs': fs,
'state': state}
except Exception:
pass
except Exception:
pass
try:
for q, qval in y.items():
if isinstance(qval, list):
for o in qval:
for w in o['children']:
if isinstance(w['logicalname'], list):
volume_name = w['logicalname'][0]
mount_point = w['logicalname'][1]
size = round(w['size'] / 1073741824)
size = str(size) + 'Gb'
fs = w['configuration']['mount.fstype']
state = w['configuration']['state']
disks[volume_name] = {
'mount_point': mount_point,
'size': size,
'fs': fs,
'state': state}
except Exception:
pass
except Exception:
pass
if sql.insert_system_info(server_id, os_info, sys_info, cpu, ram, network, disks):
return True
else:
return False
def string_to_dict(dict_string):
from ast import literal_eval
return literal_eval(dict_string)

View File

@ -372,8 +372,6 @@ if form.getvalue('sessions_select_show') is not None:
cmd = 'echo "show sess %s" |nc %s %s' % (sess_id, serv, haproxy_sock_port) cmd = 'echo "show sess %s" |nc %s %s' % (sess_id, serv, haproxy_sock_port)
output, stderr = funct.subprocess_execute(cmd) output, stderr = funct.subprocess_execute(cmd)
output, stderr = funct.subprocess_execute(cmd)
if stderr: if stderr:
print('error: ' + stderr[0]) print('error: ' + stderr[0])
else: else:
@ -476,6 +474,7 @@ if act == "overviewHapserverBackends":
env = Environment(loader=FileSystemLoader('templates/ajax'), autoescape=True) env = Environment(loader=FileSystemLoader('templates/ajax'), autoescape=True)
template = env.get_template('haproxyservers_backends.html') template = env.get_template('haproxyservers_backends.html')
service = form.getvalue('service') service = form.getvalue('service')
format_file = 'cfg'
if service == 'haproxy': if service == 'haproxy':
configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir') configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir')
@ -1411,6 +1410,7 @@ if form.getvalue('haproxy_exp_install'):
if form.getvalue('nginx_exp_install'): if form.getvalue('nginx_exp_install'):
serv = form.getvalue('nginx_exp_install') serv = form.getvalue('nginx_exp_install')
ver = form.getvalue('exporter_v')
script = "install_nginx_exporter.sh" script = "install_nginx_exporter.sh"
stats_user = sql.get_setting('nginx_stats_user') stats_user = sql.get_setting('nginx_stats_user')
stats_password = sql.get_setting('nginx_stats_password') stats_password = sql.get_setting('nginx_stats_password')
@ -2026,6 +2026,11 @@ if form.getvalue('newserver') is not None:
except: except:
pass pass
try:
funct.get_system_info(ip)
except Exception as e:
funct.logging('Cannot get information from ' + hostname, str(e), haproxywi=1, login=1)
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True) env = Environment(loader=FileSystemLoader('templates/'), autoescape=True)
@ -2038,7 +2043,6 @@ if form.getvalue('newserver') is not None:
page=page, page=page,
adding=1) adding=1)
print(template) print(template)
funct.logging('a new server ' + hostname, ' has been created ', haproxywi=1, login=1)
funct.logging(ip, 'A new server ' + hostname + ' has been created', haproxywi=1, login=1, funct.logging(ip, 'A new server ' + hostname + ' has been created', haproxywi=1, login=1,
keep_history=1, service='server') keep_history=1, service='server')
@ -2092,8 +2096,9 @@ if form.getvalue('serverdel') is not None:
sql.delete_port_scanner_settings(server_id) sql.delete_port_scanner_settings(server_id)
sql.delete_waf_rules(server_ip) sql.delete_waf_rules(server_ip)
sql.delete_action_history(server_id) sql.delete_action_history(server_id)
sql.delete_system_info(server_id)
print("Ok") print("Ok")
funct.logging(hostname, ' has been deleted server with ', haproxywi=1, login=1) funct.logging(server_ip, 'The server ' + hostname + ' has been deleted', haproxywi=1, login=1)
if form.getvalue('newgroup') is not None: if form.getvalue('newgroup') is not None:
newgroup = form.getvalue('groupname') newgroup = form.getvalue('groupname')
@ -2109,7 +2114,7 @@ if form.getvalue('newgroup') is not None:
output_from_parsed_template = template.render(groups=sql.select_groups(group=newgroup)) output_from_parsed_template = template.render(groups=sql.select_groups(group=newgroup))
print(output_from_parsed_template) print(output_from_parsed_template)
funct.logging('a new group ' + newgroup, ' has been created ', haproxywi=1, login=1) funct.logging('localhost','A new group ' + newgroup + ' has been created', haproxywi=1, login=1)
if form.getvalue('groupdel') is not None: if form.getvalue('groupdel') is not None:
groupdel = form.getvalue('groupdel') groupdel = form.getvalue('groupdel')
@ -2118,7 +2123,7 @@ if form.getvalue('groupdel') is not None:
groupname = g.name groupname = g.name
if sql.delete_group(groupdel): if sql.delete_group(groupdel):
print("Ok") print("Ok")
funct.logging(groupname, ' has been deleted group ', haproxywi=1, login=1) funct.logging('localhost', 'The ' + groupname + ' has been deleted', haproxywi=1, login=1)
if form.getvalue('updategroup') is not None: if form.getvalue('updategroup') is not None:
name = form.getvalue('updategroup') name = form.getvalue('updategroup')
@ -2129,7 +2134,7 @@ if form.getvalue('updategroup') is not None:
else: else:
try: try:
sql.update_group(name, descript, group_id) sql.update_group(name, descript, group_id)
funct.logging('the group ' + groupname, ' has been updated ', haproxywi=1, login=1) funct.logging('localhost', 'The ' + name + ' has been updated', haproxywi=1, login=1)
except Exception as e: except Exception as e:
print('error: ' + str(e)) print('error: ' + str(e))
@ -2155,7 +2160,7 @@ if form.getvalue('new_ssh'):
output_from_parsed_template = template.render(groups=sql.select_groups(), sshs=sql.select_ssh(name=name), output_from_parsed_template = template.render(groups=sql.select_groups(), sshs=sql.select_ssh(name=name),
page=page) page=page)
print(output_from_parsed_template) print(output_from_parsed_template)
funct.logging(name, ' has created a new SSH credentials ', haproxywi=1, login=1) funct.logging('localhost', 'A new SSH credentials ' + name +' has created', haproxywi=1, login=1)
if form.getvalue('sshdel') is not None: if form.getvalue('sshdel') is not None:
fullpath = funct.get_config_var('main', 'fullpath') fullpath = funct.get_config_var('main', 'fullpath')
@ -2174,7 +2179,7 @@ if form.getvalue('sshdel') is not None:
pass pass
if sql.delete_ssh(sshdel): if sql.delete_ssh(sshdel):
print("Ok") print("Ok")
funct.logging(name, ' has deleted the SSH credentials ', haproxywi=1, login=1) funct.logging('localhost', 'The SSH credentials ' + name + ' has deleted', haproxywi=1, login=1)
if form.getvalue('updatessh'): if form.getvalue('updatessh'):
ssh_id = form.getvalue('id') ssh_id = form.getvalue('id')
@ -2203,7 +2208,7 @@ if form.getvalue('updatessh'):
except Exception: except Exception:
pass pass
sql.update_ssh(ssh_id, name, enable, group, username, password) sql.update_ssh(ssh_id, name, enable, group, username, password)
funct.logging('the SSH ' + name, ' has updated credentials ', haproxywi=1, login=1) funct.logging('localhost', 'The SSH credentials ' + name + ' has been updated ', haproxywi=1, login=1)
if form.getvalue('ssh_cert'): if form.getvalue('ssh_cert'):
import paramiko import paramiko
@ -2245,7 +2250,7 @@ if form.getvalue('ssh_cert'):
except IOError as e: except IOError as e:
funct.logging('localhost', e.args[0], haproxywi=1) funct.logging('localhost', e.args[0], haproxywi=1)
funct.logging("localhost", " has been uploaded a new SSH cert %s" % ssh_keys, haproxywi=1, login=1) funct.logging("localhost", "A new SSH cert has been uploaded %s" % ssh_keys, haproxywi=1, login=1)
if form.getvalue('newtelegram'): if form.getvalue('newtelegram'):
token = form.getvalue('newtelegram') token = form.getvalue('newtelegram')
@ -2265,7 +2270,7 @@ if form.getvalue('newtelegram'):
output_from_parsed_template = template.render(groups=sql.select_groups(), output_from_parsed_template = template.render(groups=sql.select_groups(),
telegrams=sql.select_telegram(token=token), page=page) telegrams=sql.select_telegram(token=token), page=page)
print(output_from_parsed_template) print(output_from_parsed_template)
funct.logging(channel, ' a new Telegram channel has been created ', haproxywi=1, login=1) funct.logging('localhost', 'A new Telegram channel ' + channel + ' has been created ', haproxywi=1, login=1)
if form.getvalue('newslack'): if form.getvalue('newslack'):
token = form.getvalue('newslack') token = form.getvalue('newslack')
@ -2285,25 +2290,27 @@ if form.getvalue('newslack'):
output_from_parsed_template = template.render(groups=sql.select_groups(), output_from_parsed_template = template.render(groups=sql.select_groups(),
slacks=sql.select_slack(token=token), page=page) slacks=sql.select_slack(token=token), page=page)
print(output_from_parsed_template) print(output_from_parsed_template)
funct.logging(channel, ' has created a new Slack channel ', haproxywi=1, login=1) funct.logging('localhost', 'A new Slack channel ' + channel + ' has been created ', haproxywi=1, login=1)
if form.getvalue('telegramdel') is not None: if form.getvalue('telegramdel') is not None:
telegramdel = form.getvalue('telegramdel') telegramdel = form.getvalue('telegramdel')
telegram = sql.select_telegram(id=telegramdel) telegram = sql.select_telegram(id=telegramdel)
telegram_name = ''
for t in telegram: for t in telegram:
telegram_name = t.token telegram_name = t.token
if sql.delete_telegram(telegramdel): if sql.delete_telegram(telegramdel):
print("Ok") print("Ok")
funct.logging(telegram_name, ' has deleted the Telegram channel ', haproxywi=1, login=1) funct.logging('localhost', 'The Telegram channel ' + telegram_name + ' has been deleted ', haproxywi=1, login=1)
if form.getvalue('slackdel') is not None: if form.getvalue('slackdel') is not None:
slackdel = form.getvalue('slackdel') slackdel = form.getvalue('slackdel')
slack = sql.select_slack(id=slackdel) slack = sql.select_slack(id=slackdel)
slack_name = ''
for t in slack: for t in slack:
slack_name = t[1] slack_name = t[1]
if sql.delete_slack(slackdel): if sql.delete_slack(slackdel):
print("Ok") print("Ok")
funct.logging(slack_name, ' has deleted the Slack channel ', haproxywi=1, login=1) funct.logging('localhost', 'The Slack channel ' + slack_name + ' has been deleted ', haproxywi=1, login=1)
if form.getvalue('updatetoken') is not None: if form.getvalue('updatetoken') is not None:
token = form.getvalue('updatetoken') token = form.getvalue('updatetoken')
@ -2314,7 +2321,7 @@ if form.getvalue('updatetoken') is not None:
print(error_mess) print(error_mess)
else: else:
sql.update_telegram(token, channel, group, user_id) sql.update_telegram(token, channel, group, user_id)
funct.logging('group ' + group, ' Telegram token has updated channel: ' + channel, haproxywi=1, login=1) funct.logging('group ' + group, 'The Telegram token has been updated for channel: ' + channel, haproxywi=1, login=1)
if form.getvalue('update_slack_token') is not None: if form.getvalue('update_slack_token') is not None:
token = form.getvalue('update_slack_token') token = form.getvalue('update_slack_token')
@ -2325,13 +2332,13 @@ if form.getvalue('update_slack_token') is not None:
print(error_mess) print(error_mess)
else: else:
sql.update_slack(token, channel, group, user_id) sql.update_slack(token, channel, group, user_id)
funct.logging('group ' + group, ' Slack token has updated channel: ' + channel, haproxywi=1, login=1) funct.logging('group ' + group, 'The Slack token has been updated for channel: ' + channel, haproxywi=1, login=1)
if form.getvalue('updatesettings') is not None: if form.getvalue('updatesettings') is not None:
settings = form.getvalue('updatesettings') settings = form.getvalue('updatesettings')
val = form.getvalue('val') val = form.getvalue('val')
if sql.update_setting(settings, val): if sql.update_setting(settings, val):
funct.logging('value ' + val, ' changed settings ' + settings, haproxywi=1, login=1) funct.logging('localhost', 'The ' + settings +' setting has been changed to: ' + val, haproxywi=1, login=1)
print("Ok") print("Ok")
if form.getvalue('getuserservices'): if form.getvalue('getuserservices'):
@ -2370,7 +2377,7 @@ if form.getvalue('changeUserGroupId') is not None:
continue continue
sql.update_user_groups(groups=group[0], user_group_id=group_id) sql.update_user_groups(groups=group[0], user_group_id=group_id)
funct.logging('localhost', ' has been updated groups for user: ' + user, haproxywi=1, login=1) funct.logging('localhost', 'Groups has been updated for user: ' + user, haproxywi=1, login=1)
if form.getvalue('changeUserServicesId') is not None: if form.getvalue('changeUserServicesId') is not None:
user_id = form.getvalue('changeUserServicesId') user_id = form.getvalue('changeUserServicesId')
@ -2378,7 +2385,7 @@ if form.getvalue('changeUserServicesId') is not None:
user = form.getvalue('changeUserServicesUser') user = form.getvalue('changeUserServicesUser')
if sql.update_user_services(services=services, user_id=user_id): if sql.update_user_services(services=services, user_id=user_id):
funct.logging('localhost', ' has been updated services for user: ' + user, haproxywi=1, login=1) funct.logging('localhost', 'Access to the services has been updated for user: ' + user, haproxywi=1, login=1)
if form.getvalue('changeUserCurrentGroupId') is not None: if form.getvalue('changeUserCurrentGroupId') is not None:
group_id = form.getvalue('changeUserCurrentGroupId') group_id = form.getvalue('changeUserCurrentGroupId')
@ -2588,6 +2595,7 @@ if form.getvalue('lets_domain'):
ssl_path = sql.get_setting('cert_path') ssl_path = sql.get_setting('cert_path')
haproxy_dir = sql.get_setting('haproxy_dir') haproxy_dir = sql.get_setting('haproxy_dir')
script = "letsencrypt.sh" script = "letsencrypt.sh"
ssh_port = "22"
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(serv) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(serv)
if ssh_enable == 0: if ssh_enable == 0:
@ -2690,6 +2698,7 @@ if form.getvalue('actionvpn') is not None:
if form.getvalue('scan_ports') is not None: if form.getvalue('scan_ports') is not None:
serv_id = form.getvalue('scan_ports') serv_id = form.getvalue('scan_ports')
server = sql.select_servers(id=serv_id) server = sql.select_servers(id=serv_id)
ip = ''
for s in server: for s in server:
ip = s[2] ip = s[2]
@ -2751,6 +2760,7 @@ if form.getvalue('geoip_install'):
maxmind_key = sql.get_setting('maxmind_key') maxmind_key = sql.get_setting('maxmind_key')
haproxy_dir = sql.get_setting('haproxy_dir') haproxy_dir = sql.get_setting('haproxy_dir')
script = 'install_geoip.sh' script = 'install_geoip.sh'
ssh_port = '22'
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(serv) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(serv)
if ssh_enable == 0: if ssh_enable == 0:
@ -2784,6 +2794,7 @@ if form.getvalue('nettools_icmp_server_from'):
server_to = funct.is_ip_or_dns(server_to) server_to = funct.is_ip_or_dns(server_to)
action = form.getvalue('nettools_action') action = form.getvalue('nettools_action')
stderr = '' stderr = ''
action_for_sending = ''
if server_to == '': if server_to == '':
print('warning: enter a correct IP or DNS name') print('warning: enter a correct IP or DNS name')
@ -3885,4 +3896,59 @@ if act == 'showListOfVersion':
for_delver=for_delver, for_delver=for_delver,
configs=configs, configs=configs,
style=style) style=style)
print(template) print(template)
if act == 'getSystemInfo':
server_ip = form.getvalue('server_ip')
server_ip = funct.is_ip_or_dns(server_ip)
server_id = form.getvalue('server_id')
if server_ip == '':
print('error: IP or DNS name is not valid')
sys.exit()
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True,
extensions=["jinja2.ext.loopcontrols", "jinja2.ext.do"])
env.globals['string_to_dict'] = funct.string_to_dict
template = env.get_template('ajax/show_system_info.html')
if sql.is_system_info(server_id):
if funct.get_system_info(server_ip):
system_info = sql.select_one_system_info(server_id)
template = template.render(system_info=system_info, server_ip=server_ip, server_id=server_id)
print(template)
else:
print('error: Cannot update server info')
else:
system_info = sql.select_one_system_info(server_id)
template = template.render(system_info=system_info, server_ip=server_ip, server_id=server_id)
print(template)
if act == 'updateSystemInfo':
server_ip = form.getvalue('server_ip')
server_ip = funct.is_ip_or_dns(server_ip)
server_id = form.getvalue('server_id')
if server_ip == '':
print('error: IP or DNS name is not valid')
sys.exit()
sql.delete_system_info(server_id)
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True,
extensions=["jinja2.ext.loopcontrols", "jinja2.ext.do"])
env.globals['string_to_dict'] = funct.string_to_dict
template = env.get_template('ajax/show_system_info.html')
if funct.get_system_info(server_ip):
system_info = sql.select_one_system_info(server_id)
template = template.render(system_info=system_info, server_ip=server_ip, server_id=server_id)
print(template)
else:
print('error: Cannot update server info')

View File

@ -2941,3 +2941,56 @@ def delete_config_version(service: str, local_path: str):
return False return False
else: else:
return True return True
def insert_system_info(server_id: int, os_info: str, sys_info: str, cpu: str, ram: str, network: str, disks: str) -> bool:
try:
SystemInfo.insert(server_id=server_id, os_info=os_info, sys_info=sys_info, cpu=cpu, ram=ram,
network=network, disks=disks).on_conflict('replace').execute()
except Exception as e:
out_error(e)
return False
else:
return True
def delete_system_info(server_id: int):
query = SystemInfo.delete().where(SystemInfo.server_id == server_id)
try:
query.execute()
except Exception as e:
out_error(e)
def select_one_system_info(server_id: int):
query = SystemInfo.select().where(SystemInfo.server_id == server_id)
try:
query_res = query.execute()
except Exception as e:
out_error(e)
return
else:
return query_res
def select_system_info():
query = SystemInfo.select()
try:
query_res = query.execute()
except Exception as e:
out_error(e)
return
else:
return query_res
def is_system_info(server_id):
try:
query_res = SystemInfo.get(SystemInfo.server_id == server_id).server_id
except Exception:
return True
else:
if query_res != '':
return False
else:
return True

View File

@ -0,0 +1,154 @@
{% if not system_info %}
<td style="padding-top: 20px;" colspan="16">
<a onclick="updateServerInfo('{{server_ip}}', '{{server_id}}')" title="Refresh" style="float: right; margin-bottom: 10px;">
<span class="service-reload"></span>
</a>
</td>
{% else %}
{% for s_i in system_info %}
<td style="padding-top: 20px;" colspan="16">
<table class="overview-wi">
<tr class="overviewHead">
<td class="padding10 first-collumn-wi" colspan=2>
Base info
</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi">Linux</td>
<td>{{s_i.os_info}}</td>
</tr>
{% set base_info = string_to_dict(s_i.sys_info) %}
<tr class="even">
<td class="padding10 first-collumn-wi" style="width: 20%;">
Hostname
</td>
<td>{{base_info.hostname}}</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi">
Family
</td>
<td>{{base_info.family}}</td>
</tr>
</table>
<table class="overview-wi">
<tr class="overviewHead" colspan=2>
<td class="padding10 first-collumn-wi">
RAM
</td>
<td>
<a onclick="updateServerInfo('{{server_ip}}', '{{server_id}}')" title="Update System info" style="float: right; margin-right: 15px;">
<span class="service-reload"></span>
</a>
</td>
</tr>
{% set ram_info = string_to_dict(s_i.ram) %}
<tr class="odd">
<td class="padding10 first-collumn-wi" style="width: 20%;">
Slots
</td>
<td>{{ram_info.slots}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi">
Size
</td>
<td>{{ram_info.size}}Gb</td>
</tr>
</table>
<table class="overview-wi">
<tr class="overviewHead">
<td class="padding10 first-collumn-wi" colspan=2>
CPU
</td>
</tr>
{% set cpu_info = string_to_dict(s_i.cpu) %}
<tr class="odd">
<td class="padding10 first-collumn-wi">Model</td>
<td>{{cpu_info.cpu_model}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi" style="width: 20%;">
Cores
</td>
<td>{{cpu_info.cpu_core}}</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi">
Threads
</td>
<td>{{cpu_info.cpu_thread}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi">
Frequency
</td>
<td>{{cpu_info.hz}}Hz</td>
</tr>
</table>
{% set disks_info = string_to_dict(s_i.disks) %}
{% for v,d in disks_info.items() %}
<table class="overview-wi">
<tr class="overviewHead" colspan=2>
<td class="padding10 first-collumn-wi" colspan=2>
{{v}}
</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi" style="width: 20%;">
Mount point
</td>
<td>{{d.mount_point}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi">
Size
</td>
<td>{{d.size}}</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi" style="width: 20%;">
File system
</td>
<td>{{d.fs}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi">
State
</td>
<td>{{d.state}}</td>
</tr>
</table>
{% endfor %}
{% set network_info = string_to_dict(s_i.network) %}
{% for v,d in network_info.items() %}
<table class="overview-wi">
<tr class="overviewHead" colspan=2>
<td class="padding10 first-collumn-wi" colspan=2>
{{v}}
</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi" style="width: 20%;">
IP
</td>
<td>{{d.ip}}</td>
</tr>
<tr class="even">
<td class="padding10 first-collumn-wi">
MAC
</td>
<td>{{d.mac}}</td>
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi" style="width: 20%;">
Description
</td>
<td>{{d.description}}</td>
</tr>
</table>
{% endfor %}
</td>
{% endfor %}
{% endif %}

View File

@ -3,7 +3,7 @@
<table class="overview" id="ajax-servers"> <table class="overview" id="ajax-servers">
<thead> <thead>
<tr class="overviewHead"> <tr class="overviewHead">
<th class="padding10 first-collumn">Hostname</th> <th class="padding10 first-collumn">Name</th>
<th class="ip-field" style="width: 10%">IP</th> <th class="ip-field" style="width: 10%">IP</th>
<th class="checkbox-head" style="width: 5%" class="help_cursor"><span title="SSH port">Port</span></th> <th class="checkbox-head" style="width: 5%" class="help_cursor"><span title="SSH port">Port</span></th>
{% if page != "servers.py" %} {% if page != "servers.py" %}
@ -26,6 +26,7 @@
</th> </th>
<th class="cred-field">Credentials</th> <th class="cred-field">Credentials</th>
<th style="width: 100%">Description</th> <th style="width: 100%">Description</th>
<th style="min-width: 17px;"></th>
<th></th> <th></th>
<th></th> <th></th>
</tr> </tr>
@ -150,6 +151,9 @@
{{ input(id, size='20') }} {{ input(id, size='20') }}
{% endif %} {% endif %}
</td> </td>
<td style="min-width: 17px;">
<a class="info" onclick="showServerInfo('{{server.0}}', '{{server.2}}')" id="server_info_link-{{server.0}}" title="Show server info" style="cursor: pointer; color: var(--green-color)"></a>
</td>
<td> <td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a> <a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
</td> </td>
@ -157,6 +161,7 @@
<a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a> <a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>
</td> </td>
</tr> </tr>
<tr id="server_info-{{server.0}}" style="display: none"></tr>
{% endfor %} {% endfor %}
{% if not adding %} {% if not adding %}
</tbody> </tbody>

View File

@ -19,7 +19,6 @@ try:
settings = sql.get_setting('', all=1) settings = sql.get_setting('', all=1)
ldap_enable = sql.get_setting('ldap_enable') ldap_enable = sql.get_setting('ldap_enable')
grafana, stderr = funct.subprocess_execute("systemctl is-active grafana-server") grafana, stderr = funct.subprocess_execute("systemctl is-active grafana-server")
except Exception: except Exception:
pass pass

View File

@ -182,7 +182,6 @@ $( function() {
toastr.clear(); toastr.clear();
toastr.success(data); toastr.success(data);
$('#cur_haproxy_exp_ver').text('HAProxy exporter is installed'); $('#cur_haproxy_exp_ver').text('HAProxy exporter is installed');
$('#haproxy_exp_install').text('Update');
$("#haproxy_exp_addserv").trigger( "selectmenuchange" ); $("#haproxy_exp_addserv").trigger( "selectmenuchange" );
} else if (data.indexOf('Info') != '-1' ){ } else if (data.indexOf('Info') != '-1' ){
toastr.clear(); toastr.clear();
@ -213,7 +212,6 @@ $( function() {
toastr.clear(); toastr.clear();
toastr.success(data); toastr.success(data);
$('#cur_nginx_exp_ver').text('Nginx exporter is installed'); $('#cur_nginx_exp_ver').text('Nginx exporter is installed');
$('#nginx_exp_install').text('Update');
$("#nginx_exp_addserv").trigger( "selectmenuchange" ); $("#nginx_exp_addserv").trigger( "selectmenuchange" );
} else if (data.indexOf('Info') != '-1' ){ } else if (data.indexOf('Info') != '-1' ){
toastr.clear(); toastr.clear();
@ -244,7 +242,6 @@ $( function() {
toastr.clear(); toastr.clear();
toastr.success(data); toastr.success(data);
$('#cur_node_exp_ver').text('Node exporter is installed'); $('#cur_node_exp_ver').text('Node exporter is installed');
$('#node_exp_install').text('Update');
$("#node_exp_addserv").trigger( "selectmenuchange" ); $("#node_exp_addserv").trigger( "selectmenuchange" );
} else if (data.indexOf('Info') != '-1' ){ } else if (data.indexOf('Info') != '-1' ){
toastr.clear(); toastr.clear();
@ -270,6 +267,7 @@ $( function() {
if(data != '') { if(data != '') {
data = data+'-1'; data = data+'-1';
$('#cur_hap_ver').text(data); $('#cur_hap_ver').text(data);
$('#cur_hap_ver').css('font-weight', 'bold');
$('#install').text('Update'); $('#install').text('Update');
$('#install').attr('title', 'Update HAProxy'); $('#install').attr('title', 'Update HAProxy');
} else { } else {
@ -297,6 +295,7 @@ $( function() {
$('#nginx_install').attr('title', 'Install Nginx'); $('#nginx_install').attr('title', 'Install Nginx');
} else { } else {
$('#cur_nginx_ver').text(data); $('#cur_nginx_ver').text(data);
$('#cur_nginx_ver').css('font-weight', 'bold');
$('#nginx_install').text('Update'); $('#nginx_install').text('Update');
$('#nginx_install').attr('title', 'Update Nginx'); $('#nginx_install').attr('title', 'Update Nginx');
} }
@ -2424,3 +2423,54 @@ function checkSlack(slack_id) {
} }
} ); } );
} }
function updateServerInfo(ip, id) {
$.ajax({
url: "options.py",
data: {
act: 'updateSystemInfo',
server_ip: ip,
server_id: id,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') {
toastr.error(data);
} else {
$("#server_info-"+id).html(data);
$('#server_info-'+id).show();
$('#server_info_link-'+id).attr('title', 'Hide System info');
$.getScript(awesome);
}
}
} );
}
function showServerInfo(id, ip) {
if ($('#server_info-'+id).css('display') == 'none') {
$.ajax({
url: "options.py",
data: {
act: 'getSystemInfo',
server_ip: ip,
server_id: id,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') {
toastr.error(data);
} else {
$("#server_info-"+id).html(data);
$('#server_info-'+id).show();
$('#server_info_link-'+id).attr('title', 'Hide System info');
$.getScript(awesome);
}
}
} );
} else {
$('#server_info-'+id).hide();
$('#server_info_link-'+id).attr('title', 'Show System info');
}
}