Files
CyberPanel/manageServices/application_elasticsearch.py
master3395 82ec34f339 Manage Applications: Elasticsearch, Redis, RabbitMQ installers and UI hardening
Add modular application packages with backup-aware install/upgrade/downgrade,
DNF-backed version lists with TTL caching, and HTML bootstrap for faster loads.
Improve the version picker (labels, selection state, background meta refresh) and
route applicationMeta through shared page meta cache. Update static assets and
cache buster for manageServices.js. Repository also includes related updates to
serviceManager, upgrade tooling, website functions, and user management from this
development tree.
2026-04-01 00:35:22 +02:00

213 lines
7.8 KiB
Python

import os
import subprocess
import time
from serverStatus.serverStatusUtil import ServerStatusUtil
from plogical import CyberCPLogFileWriter as logging
from manageServices.application_backup import (
CHOWN_CMDS,
cleanup_managed_backup,
create_managed_app_backup,
merge_data_from_backup,
restore_full_backup,
service_is_active,
)
from manageServices.application_detection import detect_app_state, is_debian_family
def _es_major_normalized(es_major):
m = str(es_major).strip()
if m in ('7', '8', '9'):
return m
return '8'
def _write_repo(es_major):
major = _es_major_normalized(es_major)
if is_debian_family():
repo_file = '/etc/apt/sources.list.d/elastic-{0}.x.list'.format(major)
cmd = 'echo "deb https://artifacts.elastic.co/packages/{0}.x/apt stable main" | sudo tee {1}'.format(major, repo_file)
subprocess.call(cmd, shell=True)
return repo_file
repo_file = '/etc/yum.repos.d/elasticsearch.repo'
content = '''
[elasticsearch]
name=Elasticsearch repository for {0}.x packages
baseurl=https://artifacts.elastic.co/packages/{0}.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
'''.format(major)
with open(repo_file, 'w') as handle:
handle.write(content)
return repo_file
def _ensure_tmpdir(status_file):
ServerStatusUtil.executioner('mkdir -p /home/elasticsearch/tmp', status_file)
ServerStatusUtil.executioner('chown elasticsearch:elasticsearch /home/elasticsearch/tmp', status_file)
jvm_options = '/etc/elasticsearch/jvm.options'
line = '-Djava.io.tmpdir=/home/elasticsearch/tmp\n'
try:
if os.path.exists(jvm_options):
with open(jvm_options, 'r') as handle:
body = handle.read()
if line.strip() not in body:
with open(jvm_options, 'a') as handle:
handle.write(line)
except Exception:
pass
def adopt_or_reconcile(status_file):
state = detect_app_state('Elasticsearch')
if state['installed'] and not state['markerExists']:
ServerStatusUtil.executioner('touch /home/cyberpanel/elasticsearch', status_file)
logging.CyberCPLogFileWriter.statusWriter(
ServerStatusUtil.lswsInstallStatusPath,
'Elasticsearch detected and adopted by marker reconciliation.\n'
)
return state
def _resolve_target_version(version, es_major):
if version and str(version).strip() != 'latest':
return str(version).strip()
from manageServices.application_versions import get_latest_version
return get_latest_version('Elasticsearch', es_major, '3') or ''
def _run_elasticsearch_packages(version, es_major, status_file, allow_downgrade):
if is_debian_family():
subprocess.call(
'wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -',
shell=True,
)
ServerStatusUtil.executioner('apt-get install apt-transport-https -y', status_file)
_write_repo(es_major)
ServerStatusUtil.executioner('apt-get update -y', status_file)
if version and version != 'latest':
cmd = (
'DEBIAN_FRONTEND=noninteractive apt-get install -y '
'--allow-downgrades elasticsearch={0}'
).format(version)
else:
cmd = 'DEBIAN_FRONTEND=noninteractive apt-get install elasticsearch -y'
ServerStatusUtil.executioner(cmd, status_file)
return
ServerStatusUtil.executioner(
'rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch', status_file
)
_write_repo(es_major)
ad = ' --allow-downgrade' if allow_downgrade else ''
if version and version != 'latest':
cmd = 'dnf install{0} -y --enablerepo=elasticsearch elasticsearch-{1}'.format(
ad, version
)
ServerStatusUtil.executioner(cmd, status_file)
else:
cmd = 'dnf install{0} -y --enablerepo=elasticsearch elasticsearch'.format(ad)
ServerStatusUtil.executioner(cmd, status_file)
def install(version='latest', es_major='8'):
status_file = open(ServerStatusUtil.lswsInstallStatusPath, 'w')
adopt_or_reconcile(status_file)
from manageServices.application_versions import version_compare
state = detect_app_state('Elasticsearch')
backup_dir = ''
allow_downgrade = False
target = _resolve_target_version(version, es_major)
if state['installed'] and state.get('installedVersion'):
status_file.write(
'Pre-version-change backup and service stop (Elasticsearch)...\n'
)
status_file.flush()
iv = state['installedVersion']
if target and version_compare(iv, target) > 0:
allow_downgrade = True
status_file.write(
'Downgrade path: allowing package manager downgrade where supported.\n'
)
status_file.flush()
backup_dir = create_managed_app_backup('Elasticsearch', status_file)
ServerStatusUtil.executioner('systemctl stop elasticsearch', status_file)
_run_elasticsearch_packages(version, es_major, status_file, allow_downgrade)
if backup_dir:
merge_data_from_backup('Elasticsearch', backup_dir, status_file)
ServerStatusUtil.executioner(CHOWN_CMDS['Elasticsearch'], status_file)
_ensure_tmpdir(status_file)
ServerStatusUtil.executioner('systemctl enable elasticsearch', status_file)
ServerStatusUtil.executioner('systemctl start elasticsearch', status_file)
time.sleep(3)
if backup_dir:
if service_is_active('Elasticsearch'):
cleanup_managed_backup(backup_dir, status_file)
status_file.write(
'Elasticsearch version change completed; backup removed after success.\n'
)
else:
status_file.write(
'Elasticsearch failed to start; restoring from backup...\n'
)
restore_full_backup(backup_dir, status_file)
ServerStatusUtil.executioner(CHOWN_CMDS['Elasticsearch'], status_file)
ServerStatusUtil.executioner('systemctl start elasticsearch', status_file)
time.sleep(2)
if not service_is_active('Elasticsearch'):
status_file.write(
'Recovery unclear — backup kept at {0}\n'.format(backup_dir)
)
else:
status_file.write(
'Prior state restored from backup. Backup retained for safety.\n'
)
status_file.flush()
ServerStatusUtil.executioner('touch /home/cyberpanel/elasticsearch', status_file)
logging.CyberCPLogFileWriter.statusWriter(
ServerStatusUtil.lswsInstallStatusPath, 'Elasticsearch installed.[200]\n', 1
)
return 0
def upgrade(version='latest', es_major='8'):
return install(version=version, es_major=es_major)
def remove():
status_file = open(ServerStatusUtil.lswsInstallStatusPath, 'w')
if is_debian_family():
for major in ('7', '8', '9'):
path = '/etc/apt/sources.list.d/elastic-{0}.x.list'.format(major)
try:
os.remove(path)
except Exception:
pass
ServerStatusUtil.executioner(
'DEBIAN_FRONTEND=noninteractive apt-get remove elasticsearch -y', status_file
)
else:
try:
os.remove('/etc/yum.repos.d/elasticsearch.repo')
except Exception:
pass
ServerStatusUtil.executioner('yum erase elasticsearch -y', status_file)
ServerStatusUtil.executioner('rm -rf /home/elasticsearch/tmp', status_file)
ServerStatusUtil.executioner('rm -f /home/cyberpanel/elasticsearch', status_file)
logging.CyberCPLogFileWriter.statusWriter(
ServerStatusUtil.lswsInstallStatusPath, 'Elasticsearch removed.[200]\n', 1
)
return 0