diff --git a/api/api.py b/api/api.py index f0080b69..9311738d 100644 --- a/api/api.py +++ b/api/api.py @@ -46,7 +46,7 @@ def index(): 'login': 'get temporarily token. Must be JSON body: login, password and group for which getting token. METHOD: POST', 'servers':'show info about all servers. METHOD: GET', 'servers/status':'show status all HAProxyes. METHOD: GET', - 'haproxy/':'show info about the haproxy by id or hostname or ip. METHOD: GET', + 'haproxy/':'show info about the HAProxy by id or hostname or ip. METHOD: GET', 'haproxy//status':'show HAProxy status by id or hostname or ip. METHOD: GET', 'haproxy//runtime':'exec HAProxy runtime commands by id or hostname or ip. Must be JSON body: "command". METHOD: POST', 'haproxy//backends':'show backends by id or hostname or ip. METHOD: GET', @@ -54,13 +54,27 @@ def index(): 'haproxy//action/stop':'stop HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy//action/restart':'restart HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy//config':'get HAProxy config from a server by id or hostname or ip. METHOD: GET', - 'haproxy//config':'upload HAProxy config to a server by id or hostname or ip. Body must consist a whole HAProxy config. METHOD: POST', - 'haproxy//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//config':'upload HAProxy config to a server by id or hostname or ip. Headers: action: save/reload/restart. Body must consist a whole HAProxy config. METHOD: POST', + 'haproxy//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//section':'show a certain section, headers: section-name. METHOD: GET', 'haproxy//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//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//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//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' + 'haproxy//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', + 'nginx/': 'show info about the NGINX by id or hostname or ip. METHOD: GET', + 'nginx//status': 'show NGINX status by id or hostname or ip. METHOD: GET', + 'nginx//action/start': 'start NGINX service by id or hostname or ip. METHOD: GET', + 'nginx//action/stop': 'stop NGINX service by id or hostname or ip. METHOD: GET', + 'nginx//action/restart': 'restart NGINX service by id or hostname or ip. METHOD: GET', + 'nginx//config': 'get NGINX config from a server by id or hostname or ip. Headers: The full path to a config file, like: /etc/nginx/conf.d/default.conf. METHOD: GET', + 'nginx//config': 'upload NGINX config to a server by id or hostname or ip. Headers: action: save/reload/restart, config-file: the full path to the config, like /etc/nginx/conf.d/example.com.conf. Body must consist a whole HAProxy config. METHOD: POST', + 'apache/': 'show info about the Apache by id or hostname or ip. METHOD: GET', + 'apache//status': 'show Apache status by id or hostname or ip. METHOD: GET', + 'apache//action/start': 'start Apache service by id or hostname or ip. METHOD: GET', + 'apache//action/stop': 'stop Apache service by id or hostname or ip. METHOD: GET', + 'apache//action/restart': 'restart Apache service by id or hostname or ip. METHOD: GET', + 'apache//config': 'get Apache config from a server by id or hostname or ip. Headers: The full path to a config file, like: /etc/httpd/conf.d/default.conf. METHOD: GET', + 'apache//config': 'upload Apache config to a server by id or hostname or ip. Headers: action: save/reload/restart, config-file: the full path to the config, like /etc/httpd/conf.d/example.com.conf. Body must consist a whole HAProxy config. METHOD: POST', } return dict(help=data) @@ -98,8 +112,8 @@ def get_servers(): pass return dict(servers=data) - - + + @route('/servers/status', method=['GET']) def callback(): if not check_login(): @@ -107,62 +121,22 @@ def callback(): return api_funct.get_all_statuses() -@route('/haproxy/', method=['GET']) -@route('/haproxy/', method=['GET']) -def callback(haproxy_id): - if not check_login(required_service=1): - return dict(error=_error_auth) - return api_funct.get_server(haproxy_id) - - -@route('/haproxy//status', method=['GET']) -@route('/haproxy//status', method=['GET']) -def callback(haproxy_id): - if not check_login(required_service=1): - return dict(error=_error_auth) - return api_funct.get_status(haproxy_id) - - -@route('/haproxy//action/', method=['GET']) -@route('/haproxy//action/', method=['GET']) -def callback(haproxy_id, action): - if not check_login(required_service=1): - return dict(error=_error_auth) - return api_funct.actions(haproxy_id, action) - - @route('/haproxy//runtime', method=['POST']) @route('/haproxy//runtime', method=['POST']) def callback(haproxy_id): if not check_login(required_service=1): return dict(error=_error_auth) return api_funct.runtime(haproxy_id) - - + + @route('/haproxy//backends', method=['GET']) @route('/haproxy//backends', method=['GET']) def callback(haproxy_id): if not check_login(required_service=1): return dict(error=_error_auth) return api_funct.show_backends(haproxy_id) - - -@route('/haproxy//config', method=['GET']) -@route('/haproxy//config', method=['GET']) -def callback(haproxy_id): - if not check_login(required_service=1): - return dict(error=_error_auth) - return api_funct.get_config(haproxy_id) -@route('/haproxy//config', method=['POST']) -@route('/haproxy//config', method=['POST']) -def callback(haproxy_id): - if not check_login(required_service=1): - return dict(error=_error_auth) - return api_funct.upload_config(haproxy_id) - - @route('/haproxy//log', method=['GET']) @route('/haproxy//log', method=['GET']) def callback(haproxy_id): @@ -209,6 +183,53 @@ def add_acl(haproxy_id): return api_funct.del_acl(haproxy_id) +@route('//', method=['GET']) +@route('//', method=['GET']) +def callback(server_id, service): + required_service = api_funct.return_requred_serivce(service) + if not check_login(required_service=required_service): + return dict(error=_error_auth) + return api_funct.get_server(server_id, service) + + +@route('///status', method=['GET']) +@route('///status', method=['GET']) +def callback(server_id, service): + required_service = api_funct.return_requred_serivce(service) + if not check_login(required_service=required_service): + return dict(error=_error_auth) + return api_funct.get_status(server_id, service) + + +@route('///action/', method=['GET']) +@route('///action/', method=['GET']) +def callback(server_id, action, service): + required_service = api_funct.return_requred_serivce(service) + if not check_login(required_service=required_service): + return dict(error=_error_auth) + return api_funct.actions(server_id, action, service) + + +@route('///config', method=['GET']) +@route('///config', method=['GET']) +def callback(server_id, service): + required_service = api_funct.return_requred_serivce(service) + if not check_login(required_service=required_service): + return dict(error=_error_auth) + config_path = request.headers.get('config-file') + return api_funct.get_config(server_id, service=service, config_path=config_path) + + +@route('///config', method=['POST']) +@route('///config', method=['POST']) +def callback(server_id, service): + required_service = api_funct.return_requred_serivce(service) + if not check_login(required_service=required_service): + return dict(error=_error_auth) + config_path = request.headers.get('config-file') + return api_funct.upload_config(server_id, service=service, config_path=config_path) + + if __name__ == '__main__': print(sys.path) port = int(os.environ.get('PORT', 8080)) diff --git a/api/api_funct.py b/api/api_funct.py index dc9106bf..380d7c9f 100644 --- a/api/api_funct.py +++ b/api/api_funct.py @@ -9,6 +9,19 @@ import funct def get_token(): + try: + user_status, user_plan = funct.return_user_status() + except Exception as e: + funct.logging('API', 'Cannot get a user plan: ' + str(e), haproxywi=1) + return False + + if user_status == 0: + funct.logging('API', 'You are not subscribed. Please subscribe to have access to this feature.', haproxywi=1) + return False + elif user_plan == 'user': + funct.logging('API', 'This feature is not available for your plan.', haproxywi=1) + return False + try: body = request.body.getvalue().decode('utf-8') login_pass = json.loads(body) @@ -40,6 +53,19 @@ def get_token(): def check_login(required_service=0): + try: + user_status, user_plan = funct.return_user_status() + except Exception as e: + funct.logging('API', 'Cannot get a user plan: ' + str(e), haproxywi=1) + return False + + if user_status == 0: + funct.logging('API', 'You are not subscribed. Please subscribe to have access to this feature.', haproxywi=1) + return False + elif user_plan == 'user': + funct.logging('API', 'This feature is not available for your plan.', haproxywi=1) + return False + token = request.headers.get('token') if sql.get_api_token(token): if required_service != 0: @@ -69,24 +95,41 @@ def return_dict_from_out(server_id, out): return data -def check_permit_to_server(server_id): +def check_permit_to_server(server_id, service='haproxy'): servers = sql.select_servers(id_hostname=server_id) token = request.headers.get('token') login, group_id = sql.get_username_groupid_from_api_token(token) for s in servers: - server = sql.get_dick_permit(username=login, group_id=group_id, ip=s[2], token=token) + server = sql.get_dick_permit(username=login, group_id=group_id, ip=s[2], token=token, service=service) return server - -def get_server(server_id): + +def return_requred_serivce(service): + if service == 'haproxy': + required_service = 1 + elif service == 'nginx': + required_service = 2 + elif service == 'apache': + required_service = 4 + elif service == 'keepalived': + required_service = 3 + else: + required_service = 0 + + return required_service + + +def get_server(server_id, service): + if service != 'apache' and service != 'nginx' and service != 'haproxy' and service != 'keepalived': + return dict(status='wrong service') data = {} try: - servers = check_permit_to_server(server_id) + servers = check_permit_to_server(server_id, service=service) for s in servers: - data = { + data = { 'server_id':s[0], 'hostname':s[1], 'ip':s[2], @@ -101,16 +144,49 @@ def get_server(server_id): return dict(server=data) -def get_status(server_id): +def get_status(server_id, service): + if service != 'apache' and service != 'nginx' and service != 'haproxy': + return dict(status='wrong service') try: - servers = check_permit_to_server(server_id) + servers = check_permit_to_server(server_id, service=service) for s in servers: - cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|Maxco\|MB\|Uptime:"' % (s[2], sql.get_setting('haproxy_sock_port')) - - out = funct.subprocess_execute(cmd) - data = return_dict_from_out(server_id, out[0]) - + if service == 'haproxy': + cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|Maxco\|MB\|Uptime:"' % (s[2], sql.get_setting('haproxy_sock_port')) + out = funct.subprocess_execute(cmd) + data = return_dict_from_out(server_id, out[0]) + elif service == 'nginx': + cmd = [ + "/usr/sbin/nginx -v 2>&1|awk '{print $3}' && systemctl status nginx |grep -e 'Active' |awk '{print $2, $9$10$11$12$13}' && ps ax |grep nginx:|grep -v grep |wc -l"] + try: + out = funct.ssh_command(s[2], cmd) + out1 = out.split() + json_for_sending = {server_id: {"Version": out1[0].split('/')[1], "Uptime": out1[2], "Process": out1[3]}} + data = json_for_sending + except Exception as e: + data = {server_id: {"error": "Cannot get status: " + str(e)}} + elif service == 'apache': + apache_stats_user = sql.get_setting('apache_stats_user') + apache_stats_password = sql.get_setting('apache_stats_password') + apache_stats_port = sql.get_setting('apache_stats_port') + apache_stats_page = sql.get_setting('apache_stats_page') + cmd = "curl -s -u %s:%s http://%s:%s/%s?auto |grep 'ServerVersion\|Processes\|ServerUptime:'" % ( + apache_stats_user, apache_stats_password, s[2], apache_stats_port, apache_stats_page) + servers_with_status = list() + try: + out = funct.subprocess_execute(cmd) + if out != '': + for k in out: + servers_with_status.append(k) + json_for_sending = { + server_id: {"Version": servers_with_status[0][0].split('/')[1], + "Uptime": servers_with_status[0][1].split(':')[1].strip(), + "Process": servers_with_status[0][2].split(' ')[1]}} + data = json_for_sending + except Exception as e: + data = {server_id: {"error": "Cannot get status: " + str(e)}} + + except: data = {server_id: {"error": "Cannot find the server"}} return dict(error=data) @@ -141,23 +217,28 @@ def get_all_statuses(): return dict(status=data) -def actions(server_id, action): - if action == 'start' or action == 'stop' or action == 'restart': - try: - servers = check_permit_to_server(server_id) - - for s in servers: - cmd = [ "sudo systemctl %s haproxy" % action ] - error = funct.ssh_command(s[2], cmd) - done = error if error else 'done' - - data = {'server_id':s[0],'ip':s[2],'action':action,'hostname':s[1],'status':done} - - return dict(status=data) - except: - return dict(status='error') - else: +def actions(server_id, action, service): + if action != 'start' and action != 'stop' and action != 'restart' and action != 'reload': return dict(status='wrong action') + if service != 'apache' and service != 'nginx' and service != 'haproxy' and service != 'keepalived': + return dict(status='wrong service') + + try: + servers = check_permit_to_server(server_id, service=service) + + + for s in servers: + if service == 'apache': + service = funct.get_correct_apache_service_name(server_ip=s[2]) + cmd = [ "sudo systemctl %s %s" % (action, service) ] + error = funct.ssh_command(s[2], cmd) + done = error if error else 'done' + + data = {'server_id':s[0],'ip':s[2],'action':action,'hostname':s[1],'status':done} + + return dict(status=data) + except Exception as e: + return dict(status=str(e)) @@ -200,14 +281,18 @@ def show_backends(server_id): return dict(backends=data) -def get_config(server_id): +def get_config(server_id, **kwargs): + service = kwargs.get('service') + if service != 'apache' and service != 'nginx' and service != 'haproxy' and service != 'keepalived': + return dict(status='wrong service') + data = {} try: servers = check_permit_to_server(server_id) for s in servers: cfg = '/tmp/'+s[2]+'.cfg' - out = funct.get_config(s[2], cfg) + out = funct.get_config(s[2], cfg, service=service, config_file_name=kwargs.get('config_path')) os.system("sed -i 's/\\n/\n/g' "+cfg) try: conf = open(cfg, "r") @@ -215,12 +300,12 @@ def get_config(server_id): conf.close except IOError: - conf = '
Can\'t read import config file' + conf = '
Cannot read import config file' data = {server_id: config_read} - except: - data = {server_id: {"error": "Cannot find the server"}} + except Exception as e: + data = {server_id: {"error": "Cannot find the server " + str(e)}} return dict(error=data) return dict(config=data) @@ -290,13 +375,29 @@ def edit_section(server_id): return dict(config=data) -def upload_config(server_id): - data = {} +def upload_config(server_id, **kwargs): + service = kwargs.get('service') + if service != 'apache' and service != 'nginx' and service != 'haproxy': + return dict(status='wrong service') + body = request.body.getvalue().decode('utf-8') save = request.headers.get('action') token = request.headers.get('token') login, group_id = sql.get_username_groupid_from_api_token(token) - hap_configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir') + nginx = '' + apache = '' + + if service == 'nginx': + configs_dir = funct.get_config_var('configs', 'nginx_save_configs_dir') + service_name = 'Apache' + nginx = 1 + elif service == 'apache': + configs_dir = funct.get_config_var('configs', 'apache_save_configs_dir') + service_name = 'NGINX' + apache = 1 + else: + configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir') + service_name = 'HAProxy' if save == '': save = 'save' @@ -311,22 +412,29 @@ def upload_config(server_id): for s in servers: ip = s[2] cfg = '/tmp/'+ip+'.cfg' - cfg_for_save = hap_configs_dir + ip + "-" + funct.get_data('config') + ".cfg" + cfg_for_save = configs_dir + ip + "-" + funct.get_data('config') + ".cfg" try: with open(cfg, "w") as conf: conf.write(body) return_mess = 'config has been uploaded' os.system("/bin/cp %s %s" % (cfg, cfg_for_save)) - out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login) + + if kwargs.get('service') == 'nginx': + out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login, nginx=nginx, config_file_name=kwargs.get('config_path')) + elif kwargs.get('service') == 'apache': + out = funct.master_slave_upload_and_restart(ip, cfg, save, login=login, apache=apache, config_file_name=kwargs.get('config_path')) + else: + 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(ip, 'Config has been uploaded via API', haproxywi=1, login=login, - keep_history=1, service='haproxy') + keep_history=1, service=service_name) if out: return_mess = out - except IOError: - return_mess = "cannot upload config" + except IOError as e: + return_mess = "cannot upload config" + str(e) data = {server_id: return_mess} except Exception as e: diff --git a/app/create_db.py b/app/create_db.py index 69f72cac..e87099c8 100644 --- a/app/create_db.py +++ b/app/create_db.py @@ -694,7 +694,7 @@ def update_db_v_6_0_1(**kwargs): def update_ver(): - query = Version.update(version='6.0.1.0') + query = Version.update(version='6.0.2.0') try: query.execute() except: diff --git a/app/templates/base.html b/app/templates/base.html index b53d43ff..3635cf6f 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -144,8 +144,8 @@
  • Servers
  • SSH credentials
  • Settings
  • -
  • Proxy installation
  • -
  • Monitoring installation
  • +
  • Proxy installation
  • +
  • Monitoring installation
  • Server provisioning
  • Internal logs
  • Backups
  • diff --git a/inc/script.js b/inc/script.js index c06deb91..f6c89f74 100644 --- a/inc/script.js +++ b/inc/script.js @@ -1072,21 +1072,21 @@ $( function() { }); $( "#tabs" ).tabs( "option", "active", 4 ); } ); - $( ".hap" ).on( "click", function() { + $( ".installproxy" ).on( "click", function() { $('.menu li ul li').each(function () { $(this).find('a').css('padding-left', '20px') $(this).find('a').css('border-left', '0px solid #5D9CEB'); - $(this).children(".hap").css('padding-left', '30px'); - $(this).children(".hap").css('border-left', '4px solid #5D9CEB'); + $(this).children(".installproxy").css('padding-left', '30px'); + $(this).children(".installproxy").css('border-left', '4px solid #5D9CEB'); }); $( "#tabs" ).tabs( "option", "active", 5 ); } ); - $( ".hap1" ).on( "click", function() { + $( ".installmon" ).on( "click", function() { $('.menu li ul li').each(function () { $(this).find('a').css('padding-left', '20px') $(this).find('a').css('border-left', '0px solid #5D9CEB'); - $(this).children(".hap1").css('padding-left', '30px'); - $(this).children(".hap1").css('border-left', '4px solid #5D9CEB'); + $(this).children(".installmon").css('padding-left', '30px'); + $(this).children(".installmon").css('border-left', '4px solid #5D9CEB'); }); $( "#tabs" ).tabs( "option", "active", 6 ); } );