#!/mnt/ext/opt/HybridBackup/python/bin/python import os import sys import subprocess import cgi import requests import json import time from qswiss import qts_auth_get_session, qts_is_admin_group # error UNAUTHORIZED = 401 FORBIDDEN = 403 SERVER_ERROR = 500 BAD_GATEWAY = 502 STORAGE_SPACE_ERROR = 503 error_res = { 'error_code': '', 'message': '' } responses = { 401: 'Unauthorized', 403: 'Forbidden', 500: 'Internal Server Error', 502: 'Bad Gateway', 503: 'Insufficient Storage Space' } def output_response(msg, status_code=None, error_code=None): if error_code is None: print('Content-type: application/json; charset="UTF-8"') print('') print(msg) sys.exit(0) else: error_res['error_code'] = error_code error_res['message'] = msg print('Content-type: application/json; charset="UTF-8"') print('Status: %s %s' % (status_code, responses[status_code])) print('') print(json.dumps(error_res)) sys.exit(1) def is_admin_group(uid): if not qts_is_admin_group(uid): return False return True def query_port(port): try: cmd = ('lsof -i:%s' % (port)) process = subprocess.check_output(cmd, shell=True) process = process.decode('utf-8').split('\n') port_detail = json.dumps(process[1]).split() pid = port_detail[1] return pid except Exception: return False def check_port_use_in_hbs(pid): try: cmd = ('cat /proc/%s/cmdline' % (pid)) port_path = subprocess.check_output(cmd, shell=True).decode('utf-8') match_hbs = port_path.find('.qpkg/HybridBackup') if match_hbs == -1: return False return True except Exception: return False def test_server(): cmd = ('getcfg -f /etc/config/uLinux.conf -c System "Web Access Port" -d 8080') port = subprocess.check_output(cmd, shell=True).decode('utf-8').split('\n')[0] server_url = ('http://127.0.0.1:%s/cc3/v1' % (port)) api_header = {'Content-Type': 'application/json', 'X-QNAP-SID': os.environ['HTTP_X_QNAP_SID']} status = False; for i in range(10): resp = requests.get(server_url + '/users/system/setting', headers=api_header) if resp.status_code == 200: status = True break; time.sleep(5) return status def restart_server(): server_restart = '/mnt/ext/opt/HybridBackup/CloudConnector3/HBS_CloudConnector3.sh restart' result = subprocess.check_output(server_restart, shell=True).decode('utf-8') server_alive = test_server() return server_alive def execute(cmd): result = subprocess.run(cmd, shell=True, capture_output=True, text=True) return result.stdout.strip() def get_symbolic_actual_path(qpkg_mount_path): cache_path = execute(f"readlink -f {qpkg_mount_path}") cache_path = handle_path_slash(cache_path) return qpkg_mount_path if cache_path in ["/", ""] else cache_path def handle_path_slash(path): return path if path.endswith("/") else path + "/" def check_storage_space(): try: qpkg_mount_path = "/mnt/ext/opt/HybridBackup/" if not os.path.exists(qpkg_mount_path): qpkg_mount_path = handle_path_slash(execute("/sbin/getcfg HybridBackup Install_Path -f /etc/config/qpkg.conf")) qpkg_mount_path = get_symbolic_actual_path(qpkg_mount_path) statvfs = os.statvfs(qpkg_mount_path) free_space = statvfs.f_frsize * statvfs.f_bavail available_gb = free_space / (1024 ** 3) return { "status": "success", "result": {"available": available_gb} } except Exception as e: return { "status": "error", "result": {"error_message": "Unable to fetch system status details."}, "exception": str(e) } def check_server(): if 'HTTP_X_QNAP_SID' not in os.environ: output_response('SID is invalid', UNAUTHORIZED, 'unauthorized') sid = os.environ['HTTP_X_QNAP_SID'] session = qts_auth_get_session(sid) if session is None: output_response('SID is invalid', UNAUTHORIZED, 'unauthorized') is_admin = is_admin_group(int(session['uid'])) if not is_admin: output_response('Not admin group', FORBIDDEN, 'permission_error') port = '5050' pid = query_port(port) port_hbs_use = check_port_use_in_hbs(pid) form = cgi.FieldStorage() if form.getvalue('command') == 'restart' and (not pid or (port_hbs_use and not test_server())): output_response(json.dumps({'status': restart_server()})) if pid: if not port_hbs_use: output_response('5050 port is already in use.', BAD_GATEWAY, 'port_conflict') else: if not test_server(): storage_space = check_storage_space() if storage_space['status'] == 'success' and storage_space['result']['available'] <= 1: output_response('storage space error', STORAGE_SPACE_ERROR, 'insufficient_storage_space') else: output_response('api server error', SERVER_ERROR, 'api_server_error') else: if not test_server(): storage_space = check_storage_space() if storage_space['status'] == 'success' and storage_space['result']['available'] <= 1: output_response('storage space error', STORAGE_SPACE_ERROR, 'insufficient_storage_space') else: output_response('5050 port not used', BAD_GATEWAY, 'port_not_used') output_response(json.dumps({'status': True})) if __name__ == '__main__': check_server()