blob: e31f1285adbd186694dc9962ad14eacbc64a1ff1 [file] [log] [blame] [edit]
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import shutil
import subprocess
import sys
from abc import abstractmethod
from ..constants import MNT_PATH, SITE_PATH, SITE_PLUGIN_PATH
from ..helpers import git, log
from .download_plugins import get_installer
from .pull_replication_configurator import PullReplicationConfigurator
from .reindex import get_reindexer
from .validate_notedb import NoteDbValidator
LOG = log.get_logger("init")
PID_FILE = f"{SITE_PATH}/logs/gerrit.pid"
class GerritInit:
def __init__(self, gerrit_config, config):
self.config = config
self.gerrit_config = gerrit_config
self.plugin_installer = get_installer(self.gerrit_config, self.config)
self.installed_plugins = self._get_installed_plugins()
self.is_replica = self.gerrit_config.get_boolean("container.replica")
@abstractmethod
def _symlink_mounted_site_components(self):
pass
@abstractmethod
def _symlink_configuration(self):
pass
def _get_gerrit_version(self, gerrit_war_path):
command = f"java -jar {gerrit_war_path} version"
version_process = subprocess.run(
command.split(), stdout=subprocess.PIPE, check=True
)
return version_process.stdout.decode().strip()
def _get_installed_plugins(self):
installed_plugins = set()
if os.path.exists(SITE_PLUGIN_PATH):
for f in os.listdir(SITE_PLUGIN_PATH):
if os.path.isfile(os.path.join(SITE_PLUGIN_PATH, f)) and f.endswith(
".jar"
):
installed_plugins.add(os.path.splitext(f)[0])
return installed_plugins
def _gerrit_war_updated(self):
installed_war_path = os.path.join(SITE_PATH, "bin", "gerrit.war")
installed_version = self._get_gerrit_version(installed_war_path)
provided_version = self._get_gerrit_version("/var/war/gerrit.war")
LOG.info(
"Installed Gerrit version: %s; Provided Gerrit version: %s). ",
installed_version,
provided_version,
)
return installed_version != provided_version
def _needs_init(self):
installed_war_path = os.path.join(SITE_PATH, "bin", "gerrit.war")
if not os.path.exists(installed_war_path):
LOG.info("Gerrit is not yet installed. Initializing new site.")
return True
if self._gerrit_war_updated():
LOG.info("Reinitializing site to perform update.")
return True
if self.plugin_installer.plugins_changed:
LOG.info("Plugins were installed or updated. Initializing.")
return True
if self.config.get_plugin_names().difference(self.installed_plugins):
LOG.info("Reininitializing site to install additional plugins.")
return True
LOG.info("No initialization required.")
return False
def _symlink(self, src, target, required=True):
if os.path.islink(target) and not os.path.exists(os.readlink(target)):
LOG.warn(f"Removing broken symlink {target}")
os.unlink(target)
if not os.path.exists(src):
if required:
raise FileNotFoundError(f"Unable to find mounted dir: {src}")
else:
return
if os.path.exists(target):
if os.path.isdir(target) and not os.path.islink(target):
shutil.rmtree(target)
else:
os.remove(target)
os.symlink(src, target)
def _symlink_or_make_data_dir(self):
data_dir = f"{SITE_PATH}/data"
if os.path.exists(data_dir):
for file_or_dir in os.listdir(data_dir):
abs_path = os.path.join(data_dir, file_or_dir)
if os.path.islink(abs_path) and not os.path.exists(
os.path.realpath(abs_path)
):
os.unlink(abs_path)
else:
os.makedirs(data_dir)
mounted_data_dir = f"{MNT_PATH}/data"
if os.path.exists(mounted_data_dir):
for file_or_dir in os.listdir(mounted_data_dir):
abs_path = os.path.join(data_dir, file_or_dir)
abs_mounted_path = os.path.join(mounted_data_dir, file_or_dir)
if os.path.isdir(abs_mounted_path):
self._symlink(abs_mounted_path, abs_path)
def _remove_auto_generated_ssh_keys(self):
etc_dir = f"{SITE_PATH}/etc"
if not os.path.exists(etc_dir):
return
for file_or_dir in os.listdir(etc_dir):
full_path = os.path.join(etc_dir, file_or_dir)
if os.path.isfile(full_path) and file_or_dir.startswith("ssh_host_"):
os.remove(full_path)
def execute(self):
if not self.is_replica:
self._symlink_mounted_site_components()
elif not NoteDbValidator().check():
LOG.info("NoteDB not ready. Initializing repositories.")
self._symlink_mounted_site_components()
self._symlink_configuration()
if os.path.exists(PID_FILE):
os.remove(PID_FILE)
self.plugin_installer.execute()
self._symlink_configuration()
if PullReplicationConfigurator.has_pull_replication():
PullReplicationConfigurator(self.config).configure_pull_replication()
if self._needs_init():
if self.gerrit_config:
LOG.info("Existing gerrit.config found.")
dev_option = (
"--dev"
if self.gerrit_config.get(
"auth.type", "development_become_any_account"
).lower()
== "development_become_any_account"
else ""
)
else:
LOG.info("No gerrit.config found. Initializing default site.")
dev_option = "--dev"
flags = f"--no-auto-start --batch {dev_option}"
command = f"java -jar /var/war/gerrit.war init {flags} -d {SITE_PATH}"
init_process = subprocess.run(
command.split(), stdout=subprocess.PIPE, check=True
)
if init_process.returncode > 0:
LOG.error(
"An error occurred, when initializing Gerrit. Exit code: %d",
init_process.returncode,
)
sys.exit(1)
self._remove_auto_generated_ssh_keys()
self._symlink_configuration()
if PullReplicationConfigurator.has_pull_replication():
PullReplicationConfigurator(
self.config
).configure_gerrit_configuration()
if self.is_replica:
self._symlink_mounted_site_components()
# Ensure that the temporary directory for Java exists
java_tmp_dir = os.path.join(SITE_PATH, "tmp", "java")
os.makedirs(java_tmp_dir, exist_ok=True)
get_reindexer(self.gerrit_config, self.config).start(False)