foreman_maintain 1.6.14 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/foreman_maintain.yml.example +1 -1
- data/config/foreman_maintain.yml.packaging +1 -1
- data/definitions/checks/foreman_tasks/not_running.rb +18 -5
- data/definitions/checks/maintenance_mode/check_consistency.rb +1 -1
- data/definitions/checks/pulpcore/no_running_tasks.rb +34 -0
- data/definitions/features/cron.rb +1 -1
- data/definitions/features/dynflow_sidekiq.rb +4 -0
- data/definitions/features/instance.rb +4 -0
- data/definitions/features/pulpcore.rb +24 -0
- data/definitions/procedures/pulpcore/wait_for_tasks.rb +15 -0
- data/definitions/scenarios/backup.rb +19 -16
- data/definitions/scenarios/foreman_upgrade.rb +1 -0
- data/definitions/scenarios/restore.rb +3 -3
- data/definitions/scenarios/satellite_upgrade.rb +1 -0
- data/definitions/scenarios/update.rb +2 -1
- data/extras/foreman_protector/dnf/foreman-protector.py +1 -1
- data/lib/foreman_maintain/cli/backup_command.rb +15 -2
- data/lib/foreman_maintain/cli/upgrade_command.rb +33 -46
- data/lib/foreman_maintain/config.rb +2 -2
- data/lib/foreman_maintain/runner.rb +5 -2
- data/lib/foreman_maintain/upgrade_runner.rb +12 -13
- data/lib/foreman_maintain/version.rb +1 -1
- metadata +4 -3
- data/definitions/procedures/backup/online/safety_confirmation.rb +0 -27
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4c920bd300687cf40bdcfaa045a8e185d838c5c6a28a397456f033cb0fc7b920
         | 
| 4 | 
            +
              data.tar.gz: 5bdd2f964f86683efd0c462f383fc1e39ea4e4c28d1e30cb998a88bd6447b0b9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 845ce94787435fa1b731aba0e3ae5da8ccde750113e1cf967dd006a0f1d3483883a7625523fb0ad922bbfc28b1a67dcbf0f2d944dff6e952ff763eb1e32137e8
         | 
| 7 | 
            +
              data.tar.gz: 3551e01ecf107deb7608e2f5a250f0789c8681de3917b2bf04b7d1856385d939eb2cb61a9dd4f39ec5e42b7f2d6a5fffe6ae99ad2f8ec29e73098602483a2517
         | 
| @@ -6,17 +6,17 @@ module Checks::ForemanTasks | |
| 6 6 | 
             
                  tags :pre_upgrade
         | 
| 7 7 | 
             
                  after :foreman_tasks_not_paused
         | 
| 8 8 | 
             
                  before :check_old_foreman_tasks
         | 
| 9 | 
            +
                  param :wait_for_tasks,
         | 
| 10 | 
            +
                    'Wait for tasks to finish or fail directly',
         | 
| 11 | 
            +
                    :required => false,
         | 
| 12 | 
            +
                    :default => true
         | 
| 9 13 | 
             
                end
         | 
| 10 14 |  | 
| 11 15 | 
             
                def run
         | 
| 12 16 | 
             
                  task_count = feature(:foreman_tasks).running_tasks_count
         | 
| 13 17 | 
             
                  assert(task_count == 0,
         | 
| 14 18 | 
             
                    failure_message(task_count),
         | 
| 15 | 
            -
                    :next_steps =>
         | 
| 16 | 
            -
                      [Procedures::ForemanTasks::FetchTasksStatus.new(:state => 'running'),
         | 
| 17 | 
            -
                       Procedures::ForemanTasks::UiInvestigate.new(
         | 
| 18 | 
            -
                         'search_query' => search_query_for_running_tasks
         | 
| 19 | 
            -
                       )])
         | 
| 19 | 
            +
                    :next_steps => calculate_next_steps)
         | 
| 20 20 | 
             
                end
         | 
| 21 21 |  | 
| 22 22 | 
             
                private
         | 
| @@ -30,5 +30,18 @@ module Checks::ForemanTasks | |
| 30 30 | 
             
                  "There are #{task_count} active task(s) in the system." \
         | 
| 31 31 | 
             
                  "\nPlease wait for these to complete or cancel them from the Monitor tab."
         | 
| 32 32 | 
             
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def calculate_next_steps
         | 
| 35 | 
            +
                  steps = []
         | 
| 36 | 
            +
                  if @wait_for_tasks
         | 
| 37 | 
            +
                    steps << Procedures::ForemanTasks::FetchTasksStatus.new(:state => 'running')
         | 
| 38 | 
            +
                    unless assumeyes?
         | 
| 39 | 
            +
                      steps << Procedures::ForemanTasks::UiInvestigate.new(
         | 
| 40 | 
            +
                        'search_query' => search_query_for_running_tasks
         | 
| 41 | 
            +
                      )
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                  steps
         | 
| 45 | 
            +
                end
         | 
| 33 46 | 
             
              end
         | 
| 34 47 | 
             
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Checks::Pulpcore
         | 
| 2 | 
            +
              class NoRunningTasks < ForemanMaintain::Check
         | 
| 3 | 
            +
                metadata do
         | 
| 4 | 
            +
                  for_feature :pulpcore
         | 
| 5 | 
            +
                  description 'Check for running pulpcore tasks'
         | 
| 6 | 
            +
                  tags :pre_upgrade
         | 
| 7 | 
            +
                  param :wait_for_tasks,
         | 
| 8 | 
            +
                    'Wait for tasks to finish or fail directly',
         | 
| 9 | 
            +
                    :required => false
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def run
         | 
| 13 | 
            +
                  tasks = feature(:pulpcore).running_tasks
         | 
| 14 | 
            +
                  assert(
         | 
| 15 | 
            +
                    tasks.empty?,
         | 
| 16 | 
            +
                    failure_message(tasks.length),
         | 
| 17 | 
            +
                    :next_steps => calculate_next_steps
         | 
| 18 | 
            +
                  )
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def failure_message(task_count)
         | 
| 24 | 
            +
                  <<~MSG
         | 
| 25 | 
            +
                    There are #{task_count} active task(s) in the system.
         | 
| 26 | 
            +
                    Please wait for these to complete.
         | 
| 27 | 
            +
                  MSG
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def calculate_next_steps
         | 
| 31 | 
            +
                  @wait_for_tasks ? [Procedures::Pulpcore::WaitForTasks.new] : []
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -101,6 +101,10 @@ class Features::Instance < ForemanMaintain::Feature | |
| 101 101 | 
             
                version.to_s[/^\d+\.\d+\.\d+/]
         | 
| 102 102 | 
             
              end
         | 
| 103 103 |  | 
| 104 | 
            +
              def current_major_version
         | 
| 105 | 
            +
                current_version.to_s[/^\d+\.\d+/]
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 104 108 | 
             
              def target_version
         | 
| 105 109 | 
             
                if feature(:instance).downstream
         | 
| 106 110 | 
             
                  Features::Satellite.new.target_version
         | 
| @@ -3,10 +3,34 @@ require 'foreman_maintain/utils/service/systemd' | |
| 3 3 | 
             
            class Features::Pulpcore < ForemanMaintain::Feature
         | 
| 4 4 | 
             
              include ForemanMaintain::Concerns::PulpCommon
         | 
| 5 5 |  | 
| 6 | 
            +
              TIMEOUT_FOR_TASKS_STATUS = 300
         | 
| 7 | 
            +
              RETRY_INTERVAL_FOR_TASKS_STATE = 10
         | 
| 8 | 
            +
             | 
| 6 9 | 
             
              metadata do
         | 
| 7 10 | 
             
                label :pulpcore
         | 
| 8 11 | 
             
              end
         | 
| 9 12 |  | 
| 13 | 
            +
              def cli(args)
         | 
| 14 | 
            +
                parse_json(execute("pulp --format json #{args}"))
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def running_tasks
         | 
| 18 | 
            +
                cli('task list --state-in running --state-in canceling')
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def wait_for_tasks(spinner, timeout_for_tasks_status = TIMEOUT_FOR_TASKS_STATUS)
         | 
| 22 | 
            +
                Timeout.timeout(timeout_for_tasks_status) do
         | 
| 23 | 
            +
                  while (task_count = running_tasks.length) != 0
         | 
| 24 | 
            +
                    puts "\nThere are #{task_count} tasks."
         | 
| 25 | 
            +
                    spinner.update "Waiting #{RETRY_INTERVAL_FOR_TASKS_STATE} seconds before retry."
         | 
| 26 | 
            +
                    sleep RETRY_INTERVAL_FOR_TASKS_STATE
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              rescue Timeout::Error => e
         | 
| 30 | 
            +
                logger.error(e.message)
         | 
| 31 | 
            +
                puts "\nTimeout: #{e.message}. Try again."
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 10 34 | 
             
              def services
         | 
| 11 35 | 
             
                redis_services = feature(:redis) ? feature(:redis).services : []
         | 
| 12 36 |  | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            module Procedures::Pulpcore
         | 
| 2 | 
            +
              class WaitForTasks < ForemanMaintain::Procedure
         | 
| 3 | 
            +
                metadata do
         | 
| 4 | 
            +
                  for_feature :pulpcore
         | 
| 5 | 
            +
                  description 'Fetch tasks status and wait till they finish'
         | 
| 6 | 
            +
                  advanced_run false
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def run
         | 
| 10 | 
            +
                  with_spinner("waiting for tasks to finish") do |spinner|
         | 
| 11 | 
            +
                    feature(:pulpcore).wait_for_tasks(spinner)
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -13,13 +13,15 @@ module ForemanMaintain::Scenarios | |
| 13 13 | 
             
                  param :proxy_features, 'List of proxy features to backup (default: all)', :array => true
         | 
| 14 14 | 
             
                  param :skip_pulp_content, 'Skip Pulp content during backup'
         | 
| 15 15 | 
             
                  param :tar_volume_size, 'Size of tar volume (indicates splitting)'
         | 
| 16 | 
            +
                  param :wait_for_tasks, 'Wait for running tasks to complete instead of aborting'
         | 
| 16 17 | 
             
                end
         | 
| 17 18 |  | 
| 18 19 | 
             
                def compose
         | 
| 19 20 | 
             
                  check_valid_strategy
         | 
| 20 21 | 
             
                  add_step_with_context(Checks::Backup::IncrementalParentType,
         | 
| 21 22 | 
             
                    :online_backup => strategy == :online)
         | 
| 22 | 
            -
                   | 
| 23 | 
            +
                  add_step(Checks::ForemanTasks::NotRunning.new(:wait_for_tasks => wait_for_tasks?))
         | 
| 24 | 
            +
                  add_step(Checks::Pulpcore::NoRunningTasks.new(:wait_for_tasks => wait_for_tasks?))
         | 
| 23 25 | 
             
                  add_step_with_context(Procedures::Backup::AccessibilityConfirmation) if strategy == :offline
         | 
| 24 26 | 
             
                  add_step_with_context(Procedures::Backup::PrepareDirectory)
         | 
| 25 27 | 
             
                  add_step_with_context(Procedures::Backup::Metadata, :online_backup => strategy == :online)
         | 
| @@ -62,12 +64,6 @@ module ForemanMaintain::Scenarios | |
| 62 64 |  | 
| 63 65 | 
             
                private
         | 
| 64 66 |  | 
| 65 | 
            -
                def safety_confirmation
         | 
| 66 | 
            -
                  if strategy == :online
         | 
| 67 | 
            -
                    add_step_with_context(Procedures::Backup::Online::SafetyConfirmation)
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
             | 
| 71 67 | 
             
                def check_valid_strategy
         | 
| 72 68 | 
             
                  unless [:online, :offline].include? strategy
         | 
| 73 69 | 
             
                    raise ArgumentError, "Unsupported strategy '#{strategy}'"
         | 
| @@ -92,6 +88,8 @@ module ForemanMaintain::Scenarios | |
| 92 88 | 
             
                end
         | 
| 93 89 |  | 
| 94 90 | 
             
                def add_online_backup_steps
         | 
| 91 | 
            +
                  add_step(Procedures::Service::Stop.new(:only => online_workers)) unless online_workers.empty?
         | 
| 92 | 
            +
             | 
| 95 93 | 
             
                  add_step_with_context(Procedures::Backup::ConfigFiles, :ignore_changed_files => true,
         | 
| 96 94 | 
             
                    :online_backup => true)
         | 
| 97 95 | 
             
                  add_step_with_context(Procedures::Backup::Pulp, :ensure_unchanged => true)
         | 
| @@ -104,11 +102,24 @@ module ForemanMaintain::Scenarios | |
| 104 102 | 
             
                    Procedures::Backup::Online::ForemanDB,
         | 
| 105 103 | 
             
                    Procedures::Backup::Online::PulpcoreDB
         | 
| 106 104 | 
             
                  )
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  add_step(Procedures::Service::Start.new(:only => online_workers)) unless online_workers.empty?
         | 
| 107 107 | 
             
                end
         | 
| 108 108 |  | 
| 109 109 | 
             
                def strategy
         | 
| 110 110 | 
             
                  context.get(:strategy)
         | 
| 111 111 | 
             
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                def wait_for_tasks?
         | 
| 114 | 
            +
                  !!context.get(:wait_for_tasks)
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                def online_workers
         | 
| 118 | 
            +
                  services = []
         | 
| 119 | 
            +
                  services += feature(:dynflow_sidekiq).workers if feature(:dynflow_sidekiq)
         | 
| 120 | 
            +
                  services += feature(:pulpcore).configured_workers if feature(:pulpcore)
         | 
| 121 | 
            +
                  services
         | 
| 122 | 
            +
                end
         | 
| 112 123 | 
             
              end
         | 
| 113 124 |  | 
| 114 125 | 
             
              class BackupRescueCleanup < ForemanMaintain::Scenario
         | 
| @@ -122,9 +133,7 @@ module ForemanMaintain::Scenarios | |
| 122 133 | 
             
                end
         | 
| 123 134 |  | 
| 124 135 | 
             
                def compose
         | 
| 125 | 
            -
                   | 
| 126 | 
            -
                    add_step_with_context(Procedures::Service::Start)
         | 
| 127 | 
            -
                  end
         | 
| 136 | 
            +
                  add_step_with_context(Procedures::Service::Start)
         | 
| 128 137 | 
             
                  add_step_with_context(Procedures::Backup::Clean)
         | 
| 129 138 | 
             
                end
         | 
| 130 139 |  | 
| @@ -134,11 +143,5 @@ module ForemanMaintain::Scenarios | |
| 134 143 | 
             
                  context.map(:preserve_dir,
         | 
| 135 144 | 
             
                    Procedures::Backup::Clean => :preserve_dir)
         | 
| 136 145 | 
             
                end
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                private
         | 
| 139 | 
            -
             | 
| 140 | 
            -
                def strategy
         | 
| 141 | 
            -
                  context.get(:strategy)
         | 
| 142 | 
            -
                end
         | 
| 143 146 | 
             
              end
         | 
| 144 147 | 
             
            end
         | 
| @@ -48,6 +48,7 @@ module Scenarios::Foreman | |
| 48 48 | 
             
                    Checks::ForemanTasks::Invalid::CheckPendingState, # if foreman-tasks
         | 
| 49 49 | 
             
                    Checks::ForemanTasks::Invalid::CheckPlanningState, # if foreman-tasks
         | 
| 50 50 | 
             
                    Checks::ForemanTasks::NotRunning, # if foreman-tasks
         | 
| 51 | 
            +
                    Checks::Pulpcore::NoRunningTasks, # if pulpcore
         | 
| 51 52 | 
             
                    Checks::NonRhPackages,
         | 
| 52 53 | 
             
                    Checks::PackageManager::Dnf::ValidateDnfConfig,
         | 
| 53 54 | 
             
                    Checks::Repositories::CheckNonRhRepository,
         | 
| @@ -28,7 +28,7 @@ module ForemanMaintain::Scenarios | |
| 28 28 | 
             
                  add_steps_with_context(Procedures::Restore::Confirmation,
         | 
| 29 29 | 
             
                    Procedures::Restore::RequiredPackages,
         | 
| 30 30 | 
             
                    Procedures::Restore::Configs)
         | 
| 31 | 
            -
                  add_step_with_context(Procedures::Crond::Stop) | 
| 31 | 
            +
                  add_step_with_context(Procedures::Crond::Stop)
         | 
| 32 32 | 
             
                  unless backup.incremental?
         | 
| 33 33 | 
             
                    add_steps_with_context(Procedures::Restore::InstallerReset)
         | 
| 34 34 | 
             
                  end
         | 
| @@ -48,7 +48,7 @@ module ForemanMaintain::Scenarios | |
| 48 48 |  | 
| 49 49 | 
             
                  add_step(Procedures::Installer::Run.new(:assumeyes => true))
         | 
| 50 50 | 
             
                  add_step_with_context(Procedures::Installer::UpgradeRakeTask)
         | 
| 51 | 
            -
                  add_step_with_context(Procedures::Crond::Start) | 
| 51 | 
            +
                  add_step_with_context(Procedures::Crond::Start)
         | 
| 52 52 | 
             
                end
         | 
| 53 53 | 
             
                # rubocop:enable Metrics/MethodLength,Metrics/AbcSize
         | 
| 54 54 |  | 
| @@ -93,7 +93,7 @@ module ForemanMaintain::Scenarios | |
| 93 93 | 
             
                end
         | 
| 94 94 |  | 
| 95 95 | 
             
                def compose
         | 
| 96 | 
            -
                  add_step_with_context(Procedures::Crond::Stop) | 
| 96 | 
            +
                  add_step_with_context(Procedures::Crond::Stop)
         | 
| 97 97 | 
             
                end
         | 
| 98 98 | 
             
              end
         | 
| 99 99 | 
             
            end
         | 
| @@ -48,6 +48,7 @@ module Scenarios::Satellite | |
| 48 48 | 
             
                    Checks::ForemanTasks::Invalid::CheckPendingState, # if foreman-tasks
         | 
| 49 49 | 
             
                    Checks::ForemanTasks::Invalid::CheckPlanningState, # if foreman-tasks
         | 
| 50 50 | 
             
                    Checks::ForemanTasks::NotRunning, # if foreman-tasks
         | 
| 51 | 
            +
                    Checks::Pulpcore::NoRunningTasks, # if pulpcore
         | 
| 51 52 | 
             
                    Checks::NonRhPackages,
         | 
| 52 53 | 
             
                    Checks::PackageManager::Dnf::ValidateDnfConfig,
         | 
| 53 54 | 
             
                    Checks::Repositories::CheckNonRhRepository,
         | 
| @@ -5,7 +5,7 @@ module Scenarios::Update | |
| 5 5 | 
             
                    tags :update_scenario
         | 
| 6 6 |  | 
| 7 7 | 
             
                    confine do
         | 
| 8 | 
            -
                      feature(:instance).target_version == feature(:instance). | 
| 8 | 
            +
                      feature(:instance).target_version == feature(:instance).current_major_version
         | 
| 9 9 | 
             
                    end
         | 
| 10 10 |  | 
| 11 11 | 
             
                    instance_eval(&block)
         | 
| @@ -46,6 +46,7 @@ module Scenarios::Update | |
| 46 46 | 
             
                    Checks::ForemanTasks::Invalid::CheckPendingState, # if foreman-tasks
         | 
| 47 47 | 
             
                    Checks::ForemanTasks::Invalid::CheckPlanningState, # if foreman-tasks
         | 
| 48 48 | 
             
                    Checks::ForemanTasks::NotRunning, # if foreman-tasks
         | 
| 49 | 
            +
                    Checks::Pulpcore::NoRunningTasks, # if pulpcore
         | 
| 49 50 | 
             
                    Checks::NonRhPackages,
         | 
| 50 51 | 
             
                    Checks::PackageManager::Dnf::ValidateDnfConfig,
         | 
| 51 52 | 
             
                    Checks::Repositories::CheckNonRhRepository,
         | 
| @@ -53,7 +53,7 @@ class ForemanProtector(dnf.Plugin): | |
| 53 53 | 
             
                    return final_query
         | 
| 54 54 |  | 
| 55 55 | 
             
                def sack(self):
         | 
| 56 | 
            -
                    if self.cli is not None and self.cli.command._basecmd not in PROTECT_COMMANDS:
         | 
| 56 | 
            +
                    if self.cli is not None and self.cli.command is not None and self.cli.command._basecmd not in PROTECT_COMMANDS:
         | 
| 57 57 | 
             
                        return
         | 
| 58 58 | 
             
                    if os.environ.get('LEAPP_IPU_IN_PROGRESS') is not None:
         | 
| 59 59 | 
             
                        return
         | 
| @@ -57,6 +57,7 @@ module ForemanMaintain | |
| 57 57 | 
             
                      option '--features', 'FEATURES',
         | 
| 58 58 | 
             
                        "#{proxy_name} features to include in the backup. " \
         | 
| 59 59 | 
             
                            'Valid features are tftp, dns, dhcp, openscap, and all.', :multivalued => true
         | 
| 60 | 
            +
                      option '--wait-for-tasks', :flag, 'Wait for running tasks to complete instead of aborting'
         | 
| 60 61 | 
             
                    end
         | 
| 61 62 | 
             
                    # rubocop:enable  Metrics/MethodLength
         | 
| 62 63 |  | 
| @@ -89,6 +90,7 @@ module ForemanMaintain | |
| 89 90 | 
             
                      :tar_volume_size => split_pulp_tar,
         | 
| 90 91 | 
             
                      :skip_pulp_content => skip_pulp_content?,
         | 
| 91 92 | 
             
                      :incremental_dir => incremental,
         | 
| 93 | 
            +
                      :wait_for_tasks => wait_for_tasks?,
         | 
| 92 94 | 
             
                    }.merge(options))
         | 
| 93 95 | 
             
                  end
         | 
| 94 96 |  | 
| @@ -110,6 +112,13 @@ module ForemanMaintain | |
| 110 112 | 
             
                  interactive_option
         | 
| 111 113 | 
             
                  common_backup_options
         | 
| 112 114 |  | 
| 115 | 
            +
                  banner <<-BANNER
         | 
| 116 | 
            +
                  Create a backup with most services still running.
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  The only services that are shut down are workers that can influence
         | 
| 119 | 
            +
                  the consistency of the backup.
         | 
| 120 | 
            +
                  BANNER
         | 
| 121 | 
            +
             | 
| 113 122 | 
             
                  def execute
         | 
| 114 123 | 
             
                    perform_backup(:online)
         | 
| 115 124 | 
             
                  end
         | 
| @@ -120,14 +129,18 @@ module ForemanMaintain | |
| 120 129 | 
             
                  interactive_option
         | 
| 121 130 | 
             
                  common_backup_options
         | 
| 122 131 |  | 
| 132 | 
            +
                  banner <<-BANNER
         | 
| 133 | 
            +
                  Create a backup with all services shut down.
         | 
| 134 | 
            +
                  BANNER
         | 
| 135 | 
            +
             | 
| 123 136 | 
             
                  def execute
         | 
| 124 137 | 
             
                    perform_backup(:offline)
         | 
| 125 138 | 
             
                  end
         | 
| 126 139 | 
             
                end
         | 
| 127 140 |  | 
| 128 141 | 
             
                class BackupCommand < Base
         | 
| 129 | 
            -
                  subcommand 'online', ' | 
| 130 | 
            -
                  subcommand 'offline', ' | 
| 142 | 
            +
                  subcommand 'online', 'Create backup with most services still running', OnlineBackupCommand
         | 
| 143 | 
            +
                  subcommand 'offline', 'Create backup with all services shut down', OfflineBackupCommand
         | 
| 131 144 | 
             
                end
         | 
| 132 145 | 
             
              end
         | 
| 133 146 | 
             
            end
         | 
| @@ -1,85 +1,72 @@ | |
| 1 1 | 
             
            module ForemanMaintain
         | 
| 2 2 | 
             
              module Cli
         | 
| 3 3 | 
             
                class UpgradeCommand < Base
         | 
| 4 | 
            -
                  def self.target_version_option
         | 
| 5 | 
            -
                    option '--target-version', 'TARGET_VERSION', 'Target version of the upgrade',
         | 
| 6 | 
            -
                      :required => false
         | 
| 7 | 
            -
                  end
         | 
| 8 | 
            -
             | 
| 9 4 | 
             
                  def self.disable_self_upgrade_option
         | 
| 10 5 | 
             
                    option '--disable-self-upgrade', :flag, 'Disable automatic self upgrade',
         | 
| 11 6 | 
             
                      :default => false
         | 
| 12 7 | 
             
                  end
         | 
| 13 8 |  | 
| 14 | 
            -
                  def current_target_version
         | 
| 15 | 
            -
                    current_target_version = ForemanMaintain::UpgradeRunner.current_target_version
         | 
| 16 | 
            -
                    if current_target_version && target_version && target_version != current_target_version
         | 
| 17 | 
            -
                      raise Error::UsageError,
         | 
| 18 | 
            -
                        "Can't set target version #{target_version}, "\
         | 
| 19 | 
            -
                        "#{current_target_version} already in progress"
         | 
| 20 | 
            -
                    end
         | 
| 21 | 
            -
                    @target_version = current_target_version if current_target_version
         | 
| 22 | 
            -
                    return true if current_target_version
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  def validate_target_version!
         | 
| 26 | 
            -
                    return if current_target_version
         | 
| 27 | 
            -
                    unless UpgradeRunner.available_targets.include?(target_version)
         | 
| 28 | 
            -
                      message_start = if target_version
         | 
| 29 | 
            -
                                        "Can't upgrade to #{target_version}"
         | 
| 30 | 
            -
                                      else
         | 
| 31 | 
            -
                                        '--target-version not specified'
         | 
| 32 | 
            -
                                      end
         | 
| 33 | 
            -
                      message = <<~MESSAGE
         | 
| 34 | 
            -
                        #{message_start}
         | 
| 35 | 
            -
                        Possible target versions are:
         | 
| 36 | 
            -
                      MESSAGE
         | 
| 37 | 
            -
                      versions = UpgradeRunner.available_targets.join("\n")
         | 
| 38 | 
            -
                      raise Error::UsageError, message + versions
         | 
| 39 | 
            -
                    end
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
             | 
| 42 9 | 
             
                  def upgrade_runner
         | 
| 43 10 | 
             
                    return @upgrade_runner if defined? @upgrade_runner
         | 
| 44 | 
            -
                     | 
| 45 | 
            -
                    @upgrade_runner = ForemanMaintain::UpgradeRunner.new(target_version, reporter,
         | 
| 11 | 
            +
                    @upgrade_runner = ForemanMaintain::UpgradeRunner.new(reporter,
         | 
| 46 12 | 
             
                      :assumeyes => assumeyes?,
         | 
| 47 13 | 
             
                      :whitelist => whitelist || [],
         | 
| 48 14 | 
             
                      :force => force?).tap(&:load)
         | 
| 49 15 | 
             
                  end
         | 
| 50 16 |  | 
| 51 | 
            -
                  def print_versions(target_versions)
         | 
| 52 | 
            -
                    target_versions.sort.each { |version| puts version }
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
             | 
| 55 17 | 
             
                  def allow_self_upgrade?
         | 
| 56 18 | 
             
                    !disable_self_upgrade?
         | 
| 57 19 | 
             
                  end
         | 
| 58 20 |  | 
| 21 | 
            +
                  def try_upgrade
         | 
| 22 | 
            +
                    if upgrade_runner.available?
         | 
| 23 | 
            +
                      yield
         | 
| 24 | 
            +
                    else
         | 
| 25 | 
            +
                      instance = ForemanMaintain.detector.feature(:instance)
         | 
| 26 | 
            +
                      msg = <<~BANNER
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                        There are no upgrades available.
         | 
| 29 | 
            +
                        The current version of #{instance.product_name} is #{instance.current_major_version}.
         | 
| 30 | 
            +
                        Consider using the update command.
         | 
| 31 | 
            +
                      BANNER
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                      puts msg
         | 
| 34 | 
            +
                      ForemanMaintain::UpgradeRunner::WARNING_EXIT_CODE
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 59 38 | 
             
                  subcommand 'check', 'Run pre-upgrade checks before upgrading to specified version' do
         | 
| 60 | 
            -
                    target_version_option
         | 
| 61 39 | 
             
                    interactive_option
         | 
| 62 40 | 
             
                    disable_self_upgrade_option
         | 
| 63 41 |  | 
| 64 42 | 
             
                    def execute
         | 
| 65 43 | 
             
                      ForemanMaintain.validate_downstream_packages
         | 
| 66 44 | 
             
                      ForemanMaintain.perform_self_upgrade if allow_self_upgrade?
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                       | 
| 45 | 
            +
             | 
| 46 | 
            +
                      exit_code = try_upgrade do
         | 
| 47 | 
            +
                        upgrade_runner.run_phase(:pre_upgrade_checks)
         | 
| 48 | 
            +
                        upgrade_runner.exit_code
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      exit exit_code
         | 
| 69 52 | 
             
                    end
         | 
| 70 53 | 
             
                  end
         | 
| 71 54 |  | 
| 72 55 | 
             
                  subcommand 'run', 'Run full upgrade to a specified version' do
         | 
| 73 | 
            -
                    target_version_option
         | 
| 74 56 | 
             
                    interactive_option
         | 
| 75 57 | 
             
                    disable_self_upgrade_option
         | 
| 76 58 |  | 
| 77 59 | 
             
                    def execute
         | 
| 78 60 | 
             
                      ForemanMaintain.validate_downstream_packages
         | 
| 79 61 | 
             
                      ForemanMaintain.perform_self_upgrade if allow_self_upgrade?
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                       | 
| 82 | 
            -
             | 
| 62 | 
            +
             | 
| 63 | 
            +
                      exit_code = try_upgrade do
         | 
| 64 | 
            +
                        upgrade_runner.run
         | 
| 65 | 
            +
                        upgrade_runner.save
         | 
| 66 | 
            +
                        upgrade_runner.exit_code
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                      exit exit_code
         | 
| 83 70 | 
             
                    end
         | 
| 84 71 | 
             
                  end
         | 
| 85 72 | 
             
                end
         | 
| @@ -52,8 +52,8 @@ module ForemanMaintain | |
| 52 52 | 
             
                end
         | 
| 53 53 |  | 
| 54 54 | 
             
                def load_cron_option
         | 
| 55 | 
            -
                  opt_val = @options.fetch(:manage_crond,  | 
| 56 | 
            -
                  @manage_crond = boolean?(opt_val) ? opt_val :  | 
| 55 | 
            +
                  opt_val = @options.fetch(:manage_crond, true)
         | 
| 56 | 
            +
                  @manage_crond = boolean?(opt_val) ? opt_val : true
         | 
| 57 57 | 
             
                end
         | 
| 58 58 |  | 
| 59 59 | 
             
                def load_config
         | 
| @@ -4,6 +4,9 @@ module ForemanMaintain | |
| 4 4 | 
             
                include Concerns::Logger
         | 
| 5 5 | 
             
                attr_reader :reporter, :exit_code
         | 
| 6 6 |  | 
| 7 | 
            +
                WARNING_EXIT_CODE = 78
         | 
| 8 | 
            +
                FAILURE_EXIT_CODE = 1
         | 
| 9 | 
            +
             | 
| 7 10 | 
             
                require 'foreman_maintain/runner/execution'
         | 
| 8 11 | 
             
                require 'foreman_maintain/runner/stored_execution'
         | 
| 9 12 | 
             
                def initialize(reporter, scenarios, options = {})
         | 
| @@ -61,8 +64,8 @@ module ForemanMaintain | |
| 61 64 | 
             
                    @last_scenario = scenario
         | 
| 62 65 | 
             
                    @last_scenario_continuation_confirmed = false
         | 
| 63 66 | 
             
                  end
         | 
| 64 | 
            -
                  @exit_code =  | 
| 65 | 
            -
                  @exit_code =  | 
| 67 | 
            +
                  @exit_code = WARNING_EXIT_CODE if scenario.warning?
         | 
| 68 | 
            +
                  @exit_code = FAILURE_EXIT_CODE if scenario.failed?
         | 
| 66 69 | 
             
                end
         | 
| 67 70 |  | 
| 68 71 | 
             
                def whitelisted_step?(step)
         | 
| @@ -34,32 +34,31 @@ module ForemanMaintain | |
| 34 34 |  | 
| 35 35 | 
             
                attr_reader :version, :tag, :phase
         | 
| 36 36 |  | 
| 37 | 
            -
                def initialize( | 
| 37 | 
            +
                def initialize(reporter, options = {})
         | 
| 38 38 | 
             
                  super(reporter, [], options)
         | 
| 39 | 
            -
                  @version = version
         | 
| 40 | 
            -
                  scenarios_present = find_scenarios(:tags => :upgrade_scenario).any?(&matching_version_test)
         | 
| 41 | 
            -
                  raise "Unknown version #{version}" unless scenarios_present
         | 
| 42 | 
            -
             | 
| 43 39 | 
             
                  @scenario_cache = {}
         | 
| 44 | 
            -
                   | 
| 40 | 
            +
                  @phase = :pre_upgrade_checks
         | 
| 41 | 
            +
                  condition = { :tags => [:upgrade_scenario, phase] }
         | 
| 42 | 
            +
                  matching_scenarios = find_scenarios(condition)
         | 
| 43 | 
            +
                  @version = matching_scenarios.first&.target_version
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def available?
         | 
| 47 | 
            +
                  condition = { :tags => [:upgrade_scenario, :pre_upgrade_check] }
         | 
| 48 | 
            +
                  matching_scenarios = find_scenarios(condition)
         | 
| 49 | 
            +
                  !matching_scenarios.empty?
         | 
| 45 50 | 
             
                end
         | 
| 46 51 |  | 
| 47 52 | 
             
                def scenario(phase)
         | 
| 48 53 | 
             
                  return @scenario_cache[phase] if @scenario_cache.key?(phase)
         | 
| 49 54 |  | 
| 50 55 | 
             
                  condition = { :tags => [:upgrade_scenario, phase] }
         | 
| 51 | 
            -
                  matching_scenarios = find_scenarios(condition) | 
| 56 | 
            +
                  matching_scenarios = find_scenarios(condition)
         | 
| 52 57 | 
             
                  raise "Too many scenarios match #{condition.inspect}" if matching_scenarios.size > 1
         | 
| 53 58 |  | 
| 54 59 | 
             
                  @scenario_cache[phase] = matching_scenarios.first
         | 
| 55 60 | 
             
                end
         | 
| 56 61 |  | 
| 57 | 
            -
                def matching_version_test
         | 
| 58 | 
            -
                  proc do |scenario|
         | 
| 59 | 
            -
                    scenario.respond_to?(:target_version) && scenario.target_version == @version
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
                end
         | 
| 62 | 
            -
             | 
| 63 62 | 
             
                def run
         | 
| 64 63 | 
             
                  self.class.current_target_version = @version
         | 
| 65 64 | 
             
                  PHASES.each do |phase|
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: foreman_maintain
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ivan Nečas
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2024-08- | 
| 11 | 
            +
            date: 2024-08-20 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: clamp
         | 
| @@ -187,6 +187,7 @@ files: | |
| 187 187 | 
             
            - definitions/checks/non_rh_packages.rb
         | 
| 188 188 | 
             
            - definitions/checks/package_manager/dnf/validate_dnf_config.rb
         | 
| 189 189 | 
             
            - definitions/checks/pulpcore/db_up.rb
         | 
| 190 | 
            +
            - definitions/checks/pulpcore/no_running_tasks.rb
         | 
| 190 191 | 
             
            - definitions/checks/puppet/verify_no_empty_cacert_requests.rb
         | 
| 191 192 | 
             
            - definitions/checks/repositories/check_non_rh_repository.rb
         | 
| 192 193 | 
             
            - definitions/checks/repositories/check_upstream_repository.rb
         | 
| @@ -238,7 +239,6 @@ files: | |
| 238 239 | 
             
            - definitions/procedures/backup/online/candlepin_db.rb
         | 
| 239 240 | 
             
            - definitions/procedures/backup/online/foreman_db.rb
         | 
| 240 241 | 
             
            - definitions/procedures/backup/online/pulpcore_db.rb
         | 
| 241 | 
            -
            - definitions/procedures/backup/online/safety_confirmation.rb
         | 
| 242 242 | 
             
            - definitions/procedures/backup/prepare_directory.rb
         | 
| 243 243 | 
             
            - definitions/procedures/backup/pulp.rb
         | 
| 244 244 | 
             
            - definitions/procedures/crond/start.rb
         | 
| @@ -273,6 +273,7 @@ files: | |
| 273 273 | 
             
            - definitions/procedures/packages/update.rb
         | 
| 274 274 | 
             
            - definitions/procedures/packages/update_all_confirmation.rb
         | 
| 275 275 | 
             
            - definitions/procedures/pulpcore/container_handle_image_metadata.rb
         | 
| 276 | 
            +
            - definitions/procedures/pulpcore/wait_for_tasks.rb
         | 
| 276 277 | 
             
            - definitions/procedures/puppet/delete_empty_ca_cert_request_files.rb
         | 
| 277 278 | 
             
            - definitions/procedures/puppet/remove_puppet.rb
         | 
| 278 279 | 
             
            - definitions/procedures/puppet/remove_puppet_data.rb
         | 
| @@ -1,27 +0,0 @@ | |
| 1 | 
            -
            module Procedures::Backup
         | 
| 2 | 
            -
              module Online
         | 
| 3 | 
            -
                class SafetyConfirmation < ForemanMaintain::Procedure
         | 
| 4 | 
            -
                  metadata do
         | 
| 5 | 
            -
                    description 'Data consistency warning'
         | 
| 6 | 
            -
                    tags :backup
         | 
| 7 | 
            -
                  end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                  def run
         | 
| 10 | 
            -
                    answer = ask_decision(warning_message, actions_msg: 'y(yes), q(quit)')
         | 
| 11 | 
            -
                    abort! unless answer == :yes
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def warning_message
         | 
| 15 | 
            -
                    "*** WARNING: The online backup is intended for making a copy of the data\n" \
         | 
| 16 | 
            -
                      '*** for debugging purposes only.' \
         | 
| 17 | 
            -
                      " The backup routine can not ensure 100% consistency while the\n" \
         | 
| 18 | 
            -
                      "*** backup is taking place as there is a chance there may be data mismatch between\n" \
         | 
| 19 | 
            -
                      '*** the databases while the services are live.' \
         | 
| 20 | 
            -
                      " If you wish to utilize the online backup\n" \
         | 
| 21 | 
            -
                      '*** for production use you need to ensure that there are' \
         | 
| 22 | 
            -
                      " no modifications occurring during\n" \
         | 
| 23 | 
            -
                      "*** your backup run.\n\nDo you want to proceed?"
         | 
| 24 | 
            -
                  end
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
              end
         | 
| 27 | 
            -
            end
         |