| # 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) |