require 'io/console' class PostgreSQL class DecompositionMigration def initialize(ctl) @ctl = ctl end def migrate! unless @ctl.service_enabled?('postgresql') puts 'There is no PostgreSQL instance enabled in Omnibus, exiting...' exit 1 end puts <<~MSG This script will migrate this GitLab instance to a two-database setup. WARNING: - This script is experimental. See https://docs.gitlab.com/ee/administration/postgresql/multiple_databases.html - Once migrated to a two-database setup, you cannot migrate it back. Ensure: - The new database 'gitlabhq_production_ci' has been created, for example: gitlab-psql -c "CREATE DATABASE gitlabhq_production_ci WITH OWNER 'gitlab'" - The following changes are added to /etc/gitlab/gitlab.rb configuration file but do **not** run 'gitlab-ctl reconfigure' yet: gitlab_rails['env'] = { 'GITLAB_ALLOW_SEPARATE_CI_DATABASE' => 'true' } gitlab_rails['databases']['ci']['enable'] = true gitlab_rails['databases']['ci']['db_database'] = 'gitlabhq_production_ci' This script will: - Disable background migrations because they should not be active during this migration See https://docs.gitlab.com/ee/development/database/batched_background_migrations.html#enable-or-disable-background-migrations - Stop the Gitlab Instance - Copy data in gitlabhq_production to gitlabhq_production_ci (by dumping, then restoring) - Apply configuration changes in /etc/gitlab/gitlab.rb using 'gitlab-ctl reconfigure' - Prevent errorneous database access - Re-enable background migrations - Restart GitLab This script will not: - Clean up data in the databases Please confirm the upgrade by pressing 'y': MSG prompt = $stdin.gets.chomp exit(1) unless prompt.casecmp('y').zero? disable_background_migrations unless background_migrations_initally_disabled? stop_gitlab_services run_migration post_migrate puts <<~MSG GitLab is now running on two databases. Data related to CI is now written to the ci database. You can also remove duplicated data by running: 'sudo gitlab-rake gitlab:db:truncate_legacy_tables:main' 'sudo gitlab-rake gitlab:db:truncate_legacy_tables:ci' MSG end private def background_migrations_initally_disabled? @background_migrations_initally_disabled ||= GitlabCtl::Util.run_command( 'gitlab-rails runner "puts (Feature.disabled?(:execute_background_migrations, type: :ops) && Feature.disabled?(:execute_batched_migrations_on_schedule, type: :ops)).to_s"' ).stdout.chomp == "true" end def disable_background_migrations puts "Disabling Background Migrations..." run_command <<~CMD gitlab-rails runner "Feature.disable(:execute_background_migrations) && Feature.disable(:execute_batched_migrations_on_schedule)" CMD end def enable_background_migrations puts "Enabling Background Migrations..." run_command <<~CMD gitlab-rails runner "Feature.enable(:execute_background_migrations) && Feature.enable(:execute_batched_migrations_on_schedule)" CMD end def stop_gitlab_services puts "Stopping GitLab..." run_command("gitlab-ctl stop && gitlab-ctl start postgresql") end def run_migration puts "Copying data to new database..." run_command("gitlab-rake gitlab:db:decomposition:migrate", timeout: 84_600) end def post_migrate puts "Reconfigure GitLab..." run_command("gitlab-ctl reconfigure") puts "Enable write locks..." run_command("gitlab-rake gitlab:db:lock_writes") enable_background_migrations unless background_migrations_initally_disabled? puts "Restarting GitLab..." run_command("gitlab-ctl restart") end def run_command(cmd, timeout: nil) GitlabCtl::Util.run_command(cmd, timeout: timeout).tap do |status| if status.error? enable_background_migrations unless background_migrations_initally_disabled? puts status.stdout puts status.stderr puts "[ERROR] Failed to execute: #{cmd}" puts "This GitLab instance is still disabled." exit 1 end end end end end