This commit is contained in:
Alexey Berezhok
2026-07-19 01:18:52 +03:00
parent 49812505b2
commit e85d945984
4 changed files with 118 additions and 3 deletions

View File

@@ -67,7 +67,7 @@ _packages/ispmanager-plugin-nginx_mod_rewrite_plugin-0.0.1-1.el9.x86_64.rpm
Для установки нужно установить собранный в предыдущем пункте пакет: Для установки нужно установить собранный в предыдущем пункте пакет:
``` ```
sudo rpm -ihv _packages/ispmanager-plugin-nginx_mod_rewrite_plugin-0.0.1-1.el9.x86_64.rpm sudo dnf install _packages/ispmanager-plugin-nginx_mod_rewrite_plugin-0.0.1-1.el9.x86_64.rpm
``` ```
Если вдруг установка провалилась, лог установки можно изучить здесь - `/usr/local/mgr5/var/nginx-mod-rewrite-plugin.log` Если вдруг установка провалилась, лог установки можно изучить здесь - `/usr/local/mgr5/var/nginx-mod-rewrite-plugin.log`

View File

@@ -32,11 +32,14 @@ mkdir -p %{buildroot}/usr/local/ispmanager-mod_rewrite/utils
wget -O %{buildroot}/usr/local/ispmanager-mod_rewrite/mod_rewrite.zip https://github.com/bayrepo/ngx_http_apache_rewrite_module/archive/refs/heads/main.zip wget -O %{buildroot}/usr/local/ispmanager-mod_rewrite/mod_rewrite.zip https://github.com/bayrepo/ngx_http_apache_rewrite_module/archive/refs/heads/main.zip
cp utils/build_mod_rewrite.py %{buildroot}/usr/local/ispmanager-mod_rewrite/utils cp utils/build_mod_rewrite.py %{buildroot}/usr/local/ispmanager-mod_rewrite/utils
mkdir -p %{buildroot}/usr/local/ispmanager-mod_rewrite/settings mkdir -p %{buildroot}/usr/local/ispmanager-mod_rewrite/settings
touch %{buildroot}/usr/local/ispmanager-mod_rewrite/.lock
mkdir -p %{buildroot}/usr/local/ispmanager-mod_rewrite/patches mkdir -p %{buildroot}/usr/local/ispmanager-mod_rewrite/patches
cp payload/* %{buildroot}/usr/local/ispmanager-mod_rewrite/patches/ cp payload/* %{buildroot}/usr/local/ispmanager-mod_rewrite/patches/
%triggerin -- nginx %triggerin -- nginx
/usr/local/ispmanager-mod_rewrite/utils/build_mod_rewrite.py --nodeps if [ -e /usr/local/ispmanager-mod_rewrite/settings/installed.cfg ]; then
/usr/local/ispmanager-mod_rewrite/utils/build_mod_rewrite.py --nodeps
fi
%posttrans %posttrans
killall core killall core
@@ -53,6 +56,7 @@ fi
if [ "$1" == "0" ]; then if [ "$1" == "0" ]; then
rm -f /usr/share/nginx/modules/ngx_http_apache_rewrite_module.conf rm -f /usr/share/nginx/modules/ngx_http_apache_rewrite_module.conf
rm -f /usr/lib64/nginx/modules/ngx_http_apache_rewrite_module.so rm -f /usr/lib64/nginx/modules/ngx_http_apache_rewrite_module.so
rm -f /usr/local/ispmanager-mod_rewrite/settings/installed.cfg
systemctl restart nginx systemctl restart nginx
fi fi
@@ -69,6 +73,7 @@ fi
%attr(644, root, root) /usr/local/mgr5/skins/common/plugin-logo/ispmanager-plugin-nginx_mod_rewrite_plugin.png %attr(644, root, root) /usr/local/mgr5/skins/common/plugin-logo/ispmanager-plugin-nginx_mod_rewrite_plugin.png
%attr(600, root, root) /usr/local/ispmanager-mod_rewrite/patches/nginx-vhosts.template.patch %attr(600, root, root) /usr/local/ispmanager-mod_rewrite/patches/nginx-vhosts.template.patch
%attr(600, root, root) /usr/local/ispmanager-mod_rewrite/patches/nginx-vhosts-ssl.template.patch %attr(600, root, root) /usr/local/ispmanager-mod_rewrite/patches/nginx-vhosts-ssl.template.patch
%attr(600, root, root) /usr/local/ispmanager-mod_rewrite/.lock
%changelog %changelog
* Mon Jun 29 2026 Alexey BayRepo <a@bayrepo.ru> - 0.0.1-1 * Mon Jun 29 2026 Alexey BayRepo <a@bayrepo.ru> - 0.0.1-1

View File

@@ -8,6 +8,7 @@ import datetime
from xml.dom import minidom from xml.dom import minidom
import shutil import shutil
import subprocess import subprocess
import fcntl
CONFIG_PATH = "/usr/share/nginx/modules/ngx_http_apache_rewrite_module.conf" CONFIG_PATH = "/usr/share/nginx/modules/ngx_http_apache_rewrite_module.conf"
MODULE_LINE = 'load_module "/usr/lib64/nginx/modules/ngx_http_apache_rewrite_module.so";' MODULE_LINE = 'load_module "/usr/lib64/nginx/modules/ngx_http_apache_rewrite_module.so";'
@@ -58,6 +59,74 @@ def dump_all_to_log(root):
except Exception: except Exception:
pass pass
def unlock_plugin():
"""
Release the lock on the plugin lock file.
Returns:
bool: True if lock was successfully released, False otherwise (e.g., no lock held)
"""
lock_path = '/usr/local/ispmanager-mod_rewrite/.lock'
try:
if not os.path.exists(lock_path):
return False
with open(lock_path, 'r+') as lock_file:
fcntl.flock(lock_file, fcntl.LOCK_UN)
lock_file.truncate(0)
lock_file.seek(0)
return True
except Exception:
return False
def lock_plugin_with_to():
"""
Acquire an exclusive (write) lock on the plugin lock file.
Returns:
bool: True if lock was successfully acquired, False otherwise
"""
lock_path = '/usr/local/ispmanager-mod_rewrite/.lock'
try:
if not os.path.exists(lock_path):
return False
with open(lock_path, 'r+') as lock_file:
fcntl.flock(lock_file, fcntl.LOCK_EX)
# Add timestamp and PID to indicate this process holds the lock
lock_file.write(f'Locked by PID {os.getpid()} at {datetime.datetime.now()}\n')
lock_file.truncate(0)
return True
except Exception:
return False
def lock_plugin_with_to_read():
"""
Acquire a shared (read) lock on the plugin lock file.
Allows multiple readers but prevents writers from acquiring exclusive lock.
Returns:
bool: True if lock was successfully acquired, False otherwise
"""
lock_path = '/usr/local/ispmanager-mod_rewrite/.lock'
try:
if not os.path.exists(lock_path):
return False
with open(lock_path, 'r+') as lock_file:
fcntl.flock(lock_file, fcntl.LOCK_SH)
# Add timestamp to indicate this reader holds a shared lock
lock_file.write(f'Read lock by PID {os.getpid()} at {datetime.datetime.now()}\n')
lock_file.truncate(0)
return True
except Exception:
return False
def site_state(param): def site_state(param):
""" """
Get or set the state of a site in sites_settings.cfg. Get or set the state of a site in sites_settings.cfg.
@@ -67,8 +136,10 @@ def site_state(param):
config_path = "/usr/local/ispmanager-mod_rewrite/settings/sites_settings.cfg" config_path = "/usr/local/ispmanager-mod_rewrite/settings/sites_settings.cfg"
if isinstance(param, str): if isinstance(param, str):
lock_plugin_with_to_read()
param_name = param param_name = param
if not os.path.exists(config_path): if not os.path.exists(config_path):
unlock_plugin()
return "off" return "off"
try: try:
with open(config_path, 'r', encoding='utf-8') as f: with open(config_path, 'r', encoding='utf-8') as f:
@@ -79,17 +150,22 @@ def site_state(param):
pattern = rf'^\s*{re.escape(param_name)}\s*=\s*(.*)$' pattern = rf'^\s*{re.escape(param_name)}\s*=\s*(.*)$'
m = re.match(pattern, line) m = re.match(pattern, line)
if m: if m:
unlock_plugin()
return m.group(1).strip() return m.group(1).strip()
except Exception: except Exception:
unlock_plugin()
return "off" return "off"
unlock_plugin()
return "off" return "off"
elif isinstance(param, dict): elif isinstance(param, dict):
# Write mode # Write mode
lock_plugin_with_to()
dir_path = os.path.dirname(config_path) dir_path = os.path.dirname(config_path)
try: try:
os.makedirs(dir_path, exist_ok=True) os.makedirs(dir_path, exist_ok=True)
except Exception: except Exception:
unlock_plugin()
return None return None
lines = [] lines = []
if os.path.exists(config_path): if os.path.exists(config_path):
@@ -97,6 +173,7 @@ def site_state(param):
with open(config_path, 'r', encoding='utf-8') as f: with open(config_path, 'r', encoding='utf-8') as f:
lines = f.readlines() lines = f.readlines()
except Exception: except Exception:
unlock_plugin()
return None return None
for key, val in param.items(): for key, val in param.items():
actual_value = 'on' if val == 'on' else 'off' actual_value = 'on' if val == 'on' else 'off'
@@ -116,7 +193,9 @@ def site_state(param):
with open(config_path, 'w', encoding='utf-8') as f: with open(config_path, 'w', encoding='utf-8') as f:
f.writelines(lines) f.writelines(lines)
except Exception: except Exception:
unlock_plugin()
return None return None
unlock_plugin()
return None return None
else: else:
return None return None
@@ -133,9 +212,12 @@ def read_global_config(params):
param_value = params.get('param_value') param_value = params.get('param_value')
config_path = "/usr/local/ispmanager-mod_rewrite/settings/global_settings.cfg" config_path = "/usr/local/ispmanager-mod_rewrite/settings/global_settings.cfg"
if param_value is None: if param_value is None:
lock_plugin_with_to_read()
# Read mode # Read mode
if not os.path.exists(config_path): if not os.path.exists(config_path):
unlock_plugin()
return None return None
try: try:
with open(config_path, 'r', encoding='utf-8') as f: with open(config_path, 'r', encoding='utf-8') as f:
@@ -146,16 +228,21 @@ def read_global_config(params):
pattern = rf'^\s*{re.escape(param_name)}\s*=\s*(.*)$' pattern = rf'^\s*{re.escape(param_name)}\s*=\s*(.*)$'
m = re.match(pattern, line) m = re.match(pattern, line)
if m: if m:
unlock_plugin()
return m.group(1).strip() return m.group(1).strip()
except Exception: except Exception:
unlock_plugin()
return None return None
unlock_plugin()
return None return None
else: else:
lock_plugin_with_to()
# Write mode # Write mode
dir_path = os.path.dirname(config_path) dir_path = os.path.dirname(config_path)
try: try:
os.makedirs(dir_path, exist_ok=True) os.makedirs(dir_path, exist_ok=True)
except Exception: except Exception:
unlock_plugin()
return None return None
lines = [] lines = []
found = False found = False
@@ -164,6 +251,7 @@ def read_global_config(params):
with open(config_path, 'r', encoding='utf-8') as f: with open(config_path, 'r', encoding='utf-8') as f:
lines = f.readlines() lines = f.readlines()
except Exception: except Exception:
unlock_plugin()
return None return None
for idx, line in enumerate(lines): for idx, line in enumerate(lines):
stripped = line.strip() stripped = line.strip()
@@ -180,7 +268,9 @@ def read_global_config(params):
with open(config_path, 'w', encoding='utf-8') as f: with open(config_path, 'w', encoding='utf-8') as f:
f.writelines(lines) f.writelines(lines)
except Exception: except Exception:
unlock_plugin()
return None return None
unlock_plugin()
return None return None
def check_nginx_rewrite_module(): def check_nginx_rewrite_module():
@@ -188,6 +278,7 @@ def check_nginx_rewrite_module():
if not os.path.exists(CONFIG_PATH): if not os.path.exists(CONFIG_PATH):
_log(f"Config file {CONFIG_PATH} does not exist") _log(f"Config file {CONFIG_PATH} does not exist")
return False return False
lock_plugin_with_to_read()
try: try:
with open(CONFIG_PATH, 'r') as f: with open(CONFIG_PATH, 'r') as f:
for line in f: for line in f:
@@ -196,15 +287,19 @@ def check_nginx_rewrite_module():
continue continue
if MODULE_PATTERN.match(line): if MODULE_PATTERN.match(line):
_log("Module found and enabled in config") _log("Module found and enabled in config")
unlock_plugin()
return True return True
_log("Module not found in config") _log("Module not found in config")
unlock_plugin()
return False return False
except Exception as e: except Exception as e:
_log(f"Error reading config file {CONFIG_PATH}: {e}") _log(f"Error reading config file {CONFIG_PATH}: {e}")
unlock_plugin()
return False return False
def set_nginx_rewrite_module(enable: bool): def set_nginx_rewrite_module(enable: bool):
_log(f"set_nginx_rewrite_module called with enable={enable}") _log(f"set_nginx_rewrite_module called with enable={enable}")
lock_plugin_with_to()
if enable: if enable:
if not os.path.exists(CONFIG_PATH): if not os.path.exists(CONFIG_PATH):
try: try:
@@ -266,6 +361,7 @@ def set_nginx_rewrite_module(enable: bool):
_log("No uncommented module line found to disable") _log("No uncommented module line found to disable")
except Exception as e: except Exception as e:
_log(f"Error disabling module in config file {CONFIG_PATH}: {e}") _log(f"Error disabling module in config file {CONFIG_PATH}: {e}")
unlock_plugin()
def make_nginx_custom_template() -> bool: def make_nginx_custom_template() -> bool:
tmpl = "/usr/local/mgr5/etc/templates/nginx-vhosts.template" tmpl = "/usr/local/mgr5/etc/templates/nginx-vhosts.template"
@@ -281,6 +377,8 @@ def make_nginx_custom_template() -> bool:
default_ssl_tmpl = os.path.join(default_dir, "nginx-vhosts-ssl.template") default_ssl_tmpl = os.path.join(default_dir, "nginx-vhosts-ssl.template")
target_dir = "/usr/local/mgr5/etc/templates" target_dir = "/usr/local/mgr5/etc/templates"
lock_plugin_with_to()
# Copy default templates if they exist # Copy default templates if they exist
try: try:
if os.path.exists(default_tmpl): if os.path.exists(default_tmpl):
@@ -296,6 +394,7 @@ def make_nginx_custom_template() -> bool:
os.remove(f) os.remove(f)
except Exception: except Exception:
pass pass
unlock_plugin()
return False return False
# Ensure copied files exist # Ensure copied files exist
@@ -307,6 +406,7 @@ def make_nginx_custom_template() -> bool:
os.remove(f) os.remove(f)
except Exception: except Exception:
pass pass
unlock_plugin()
return False return False
patches_dir = "/usr/local/ispmanager-mod_rewrite/patches" patches_dir = "/usr/local/ispmanager-mod_rewrite/patches"
@@ -316,6 +416,7 @@ def make_nginx_custom_template() -> bool:
def apply_patch(target, patch_file): def apply_patch(target, patch_file):
if not os.path.exists(patch_file): if not os.path.exists(patch_file):
_log(f"Patch file {patch_file} does not exist.") _log(f"Patch file {patch_file} does not exist.")
unlock_plugin()
return False return False
try: try:
result = subprocess.run( result = subprocess.run(
@@ -326,10 +427,13 @@ def make_nginx_custom_template() -> bool:
) )
if result.returncode != 0: if result.returncode != 0:
_log(f"Patch failed for {target}: {result.stderr.decode(errors='ignore')}") _log(f"Patch failed for {target}: {result.stderr.decode(errors='ignore')}")
unlock_plugin()
return False return False
unlock_plugin()
return True return True
except Exception as e: except Exception as e:
_log(f"Exception applying patch to {target}: {e}") _log(f"Exception applying patch to {target}: {e}")
unlock_plugin()
return False return False
patch_success = True patch_success = True
@@ -346,8 +450,9 @@ def make_nginx_custom_template() -> bool:
os.remove(f) os.remove(f)
except Exception: except Exception:
pass pass
unlock_plugin()
return False return False
unlock_plugin()
read_global_config({'param_name': 'templates_created', 'param_value': 'on'}) read_global_config({'param_name': 'templates_created', 'param_value': 'on'})
_log("Success: Custom Nginx templates created and patched successfully.") _log("Success: Custom Nginx templates created and patched successfully.")
return True return True

View File

@@ -44,6 +44,11 @@ def BuildModule():
if result.returncode != 0: if result.returncode != 0:
# Extract error message from stderr (already captured in stdout due to redirect) # Extract error message from stderr (already captured in stdout due to redirect)
return f'Build utility failed with exit code {result.returncode}' return f'Build utility failed with exit code {result.returncode}'
installed_cfg_path = '/usr/local/ispmanager-mod_rewrite/settings/installed.cfg'
with open(installed_cfg_path, 'w') as cfg_file:
cfg_file.write('')
os.chmod(installed_cfg_path, 0o600)
except Exception as exc: except Exception as exc:
log_path_error = os.path.join(os.path.dirname(log_path), 'error.log') log_path_error = os.path.join(os.path.dirname(log_path), 'error.log')
with open(log_path_error, 'a') as error_file: with open(log_path_error, 'a') as error_file: