diff --git a/definitions/features/system_repos.rb b/definitions/features/system_repos.rb index e95927d64..6227ed6ad 100644 --- a/definitions/features/system_repos.rb +++ b/definitions/features/system_repos.rb @@ -21,6 +21,10 @@ def enabled_repos_hash Hash[*repos.delete!(' ').split("\n")] end + def enabled_repos_ids + trim_repoids(enabled_repos_hash.keys) + end + def upstream_repos_ids trim_repoids(upstream_repos.keys) end @@ -29,6 +33,10 @@ def disable_repos(repo_ids) execute!("yum-config-manager --disable #{repo_ids.join(',')}") end + def enable_repos(repo_ids) + execute!("yum-config-manager --enable #{repo_ids.join(',')}") + end + private def trim_repoids(repos) diff --git a/definitions/procedures/repositories/backup_enabled_repos.rb b/definitions/procedures/repositories/backup_enabled_repos.rb new file mode 100644 index 000000000..25b10b1c4 --- /dev/null +++ b/definitions/procedures/repositories/backup_enabled_repos.rb @@ -0,0 +1,16 @@ +module Procedures::Repositories + class BackupEnabledRepos < ForemanMaintain::Procedure + metadata do + label :backup_enabled_repos + description 'Stores enabled repositories in yaml file' + end + + def run + enabled_repos_ids = feature(:system_repos).enabled_repos_ids + unless enabled_repos_ids.empty? + backup_dir = File.expand_path(ForemanMaintain.config.backup_dir) + File.write(File.join(backup_dir, 'enabled_repos.yml'), enabled_repos_ids.to_yaml) + end + end + end +end diff --git a/definitions/procedures/repositories/enable.rb b/definitions/procedures/repositories/enable.rb new file mode 100644 index 000000000..0148903bb --- /dev/null +++ b/definitions/procedures/repositories/enable.rb @@ -0,0 +1,13 @@ +module Procedures::Repositories + class Enable < ForemanMaintain::Procedure + metadata do + param :repos, 'List of repositories to enable' + description 'Enable repositories' + end + def run + with_spinner('Enabling repositories') do + feature(:system_repos).enable_repos(@repos) + end + end + end +end diff --git a/definitions/scenarios/self_upgrade.rb b/definitions/scenarios/self_upgrade.rb new file mode 100644 index 000000000..d7b5ce249 --- /dev/null +++ b/definitions/scenarios/self_upgrade.rb @@ -0,0 +1,102 @@ +module ForemanMaintain::Scenarios + class SelfUpgradeBase < ForemanMaintain::Scenario + def enabled_system_repos_id + feature(:system_repos).enabled_repos_ids + end + + def enable_repos(repo_ids = stored_enabled_repos_ids) + add_step(Procedures::Repositories::Enable.new(repos: repo_ids)) + end + + def disable_repos(repo_ids = stored_enabled_repos_ids) + add_step(Procedures::Repositories::Disable.new(repos: repo_ids)) + end + + def target_version + @target_version ||= context.get(:target_version) + end + + def current_version + feature(:instance).downstream.current_minor_version + end + + def maintenance_repo_id(version) + if (repo = ENV['maintenance_repo']) + return repo unless repo.empty? + end + + maintenance_repo(version) + end + + def maintenance_repo(version) + if el7? + "rhel-#{el_major_version}-server-satellite-maintenance-#{version}-rpms" + else + "satellite-maintenance-#{version}-for-rhel-#{el_major_version}-x86_64-rpms" + end + end + + def maintenance_repo_version + return '6' if current_version == '6.10' + + current_version + end + + def stored_enabled_repos_ids + @stored_enabled_repos_ids ||= begin + path = File.expand_path('enabled_repos.yml', ForemanMaintain.config.backup_dir) + @stored_enabled_repos_ids = File.file?(path) ? YAML.load(File.read(path)) : [] + end + end + + def all_maintenance_repos + repo_regex = if el7? + /rhel-\d-server-satellite-maintenance-\d.\d-rpms/ + else + /satellite-maintenance-\d.\d-for-rhel-\d-x86_64-rpms/ + end + stored_enabled_repos_ids.select { |id| !id.match(repo_regex).nil? } + end + + def repos_ids_to_reenable + repos_ids_to_reenable = stored_enabled_repos_ids - all_maintenance_repos + repos_ids_to_reenable << maintenance_repo(maintenance_repo_version) + end + end + + class SelfUpgrade < SelfUpgradeBase + metadata do + label :self_upgrade_foreman_maintain + description "Enables the specified version's maintenance repository and, "\ + 'updates the foreman-maintain packages' + manual_detection + end + + def compose + if check_min_version('foreman', '2.5') || check_min_version('foreman-proxy', '2.5') + pkgs_to_update = %w[satellite-maintain rubygem-foreman_maintain] + add_step(Procedures::Repositories::BackupEnabledRepos.new) + disable_repos + add_step(Procedures::Repositories::Enable.new(repos: [maintenance_repo_id(target_version)])) + add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true)) + enable_repos(repos_ids_to_reenable) + end + end + end + + class SelfUpgradeRescue < SelfUpgradeBase + metadata do + label :rescue_self_upgrade + description 'Disables all version specific maintenance repos and,'\ + ' enables the repositories which were configured prior to self upgrade' + manual_detection + run_strategy :fail_slow + end + + def compose + if check_min_version('foreman', '2.5') || check_min_version('foreman-proxy', '2.5') + enable_repos(repos_ids_to_reenable) + end + end + end +end diff --git a/lib/foreman_maintain/cli.rb b/lib/foreman_maintain/cli.rb index b034cc2af..3381b9414 100644 --- a/lib/foreman_maintain/cli.rb +++ b/lib/foreman_maintain/cli.rb @@ -12,6 +12,7 @@ require 'foreman_maintain/cli/packages_command' require 'foreman_maintain/cli/content_command' require 'foreman_maintain/cli/plugin_command' +require 'foreman_maintain/cli/self_upgrade_command' module ForemanMaintain module Cli @@ -27,6 +28,7 @@ class MainCommand < Base subcommand 'advanced', 'Advanced tools for server maintenance', AdvancedCommand subcommand 'content', 'Content related commands', ContentCommand subcommand 'plugin', 'Manage optional plugins on your server', PluginCommand + subcommand 'self-upgrade', 'Perform major version self upgrade', SelfUpgradeCommand subcommand 'maintenance-mode', 'Control maintenance-mode for application', MaintenanceModeCommand if ForemanMaintain.detector.feature(:satellite) && diff --git a/lib/foreman_maintain/cli/self_upgrade_command.rb b/lib/foreman_maintain/cli/self_upgrade_command.rb new file mode 100644 index 000000000..593d16f4d --- /dev/null +++ b/lib/foreman_maintain/cli/self_upgrade_command.rb @@ -0,0 +1,38 @@ +module ForemanMaintain + module Cli + class SelfUpgradeCommand < Base + option ['--target-version'], 'TARGET_VERSION',\ + 'Major version of the Satellite or Capsule'\ + ', e.g 7.0', :required => true + def execute + allow_major_version_upgrade_only + run_scenario(upgrade_scenario, upgrade_rescue_scenario) + end + + def upgrade_scenario + Scenarios::SelfUpgrade.new(target_version: target_version) + end + + def upgrade_rescue_scenario + Scenarios::SelfUpgradeRescue.new(target_version: target_version) + end + + def current_downstream_version + ForemanMaintain.detector.feature(:instance).downstream.current_version + end + + def allow_major_version_upgrade_only + begin + next_version = Gem::Version.new(target_version) + rescue ArgumentError => err + raise Error::UsageError, "Invalid version! #{err}" + end + if current_downstream_version >= next_version + message = "The target-version #{target_version} should be "\ + "greater than existing version #{current_downstream_version}!" + raise Error::UsageError, message + end + end + end + end +end diff --git a/test/lib/cli_test.rb b/test/lib/cli_test.rb index a54d11aea..92b6a0e2d 100644 --- a/test/lib/cli_test.rb +++ b/test/lib/cli_test.rb @@ -29,6 +29,7 @@ module ForemanMaintain advanced Advanced tools for server maintenance content Content related commands plugin Manage optional plugins on your server + self-upgrade Perform major version self upgrade maintenance-mode Control maintenance-mode for application Options: