foreman_maintain 0.6.13 → 0.7.4

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/definitions/checks/disk/available_space_candlepin.rb +27 -0
  4. data/definitions/checks/foreman/check_checkpoint_segments.rb +30 -22
  5. data/definitions/checks/foreman_tasks/not_paused.rb +10 -13
  6. data/definitions/checks/package_manager/yum/validate_yum_config.rb +51 -0
  7. data/definitions/features/candlepin.rb +4 -0
  8. data/definitions/features/dynflow_sidekiq.rb +7 -4
  9. data/definitions/features/foreman_cockpit.rb +15 -0
  10. data/definitions/features/foreman_tasks.rb +12 -2
  11. data/definitions/features/pulpcore.rb +20 -5
  12. data/definitions/procedures/backup/accessibility_confirmation.rb +1 -1
  13. data/definitions/procedures/backup/online/safety_confirmation.rb +11 -6
  14. data/definitions/procedures/backup/snapshot/logical_volume_confirmation.rb +1 -1
  15. data/definitions/procedures/content/migration_stats.rb +12 -0
  16. data/definitions/procedures/content/prepare.rb +2 -6
  17. data/definitions/procedures/content/prepare_abort.rb +12 -0
  18. data/definitions/procedures/content/switchover.rb +1 -1
  19. data/definitions/procedures/foreman_tasks/delete.rb +3 -4
  20. data/definitions/procedures/foreman_tasks/resume.rb +5 -0
  21. data/definitions/procedures/packages/installer_confirmation.rb +1 -1
  22. data/definitions/procedures/packages/update_all_confirmation.rb +1 -1
  23. data/definitions/procedures/prep_6_10_upgrade.rb +29 -0
  24. data/definitions/procedures/restore/confirmation.rb +1 -1
  25. data/definitions/procedures/restore/installer_reset.rb +10 -1
  26. data/definitions/procedures/service/list.rb +12 -2
  27. data/definitions/scenarios/backup.rb +2 -0
  28. data/definitions/scenarios/content.rb +50 -3
  29. data/definitions/scenarios/prep_6_10_upgrade.rb +13 -0
  30. data/definitions/scenarios/upgrade_to_capsule_6_9.rb +88 -0
  31. data/definitions/scenarios/upgrade_to_capsule_6_9_z.rb +88 -0
  32. data/definitions/scenarios/upgrade_to_satellite_6_9.rb +90 -0
  33. data/definitions/scenarios/upgrade_to_satellite_6_9_z.rb +89 -0
  34. data/lib/foreman_maintain.rb +3 -1
  35. data/lib/foreman_maintain/cli.rb +8 -0
  36. data/lib/foreman_maintain/cli/content_command.rb +17 -2
  37. data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
  38. data/lib/foreman_maintain/concerns/downstream.rb +4 -0
  39. data/lib/foreman_maintain/concerns/primary_checks.rb +23 -0
  40. data/lib/foreman_maintain/package_manager/dnf.rb +1 -0
  41. data/lib/foreman_maintain/reporter.rb +18 -13
  42. data/lib/foreman_maintain/reporter/cli_reporter.rb +24 -11
  43. data/lib/foreman_maintain/runner.rb +13 -8
  44. data/lib/foreman_maintain/scenario.rb +4 -0
  45. data/lib/foreman_maintain/utils/backup.rb +1 -1
  46. data/lib/foreman_maintain/utils/disk/io_device.rb +4 -0
  47. data/lib/foreman_maintain/utils/service/systemd.rb +13 -2
  48. data/lib/foreman_maintain/version.rb +1 -1
  49. metadata +14 -3
  50. data/definitions/checks/yum_exclude.rb +0 -21
@@ -0,0 +1,89 @@
1
+ module Scenarios::Satellite_6_9_z
2
+ class Abstract < ForemanMaintain::Scenario
3
+ def self.upgrade_metadata(&block)
4
+ metadata do
5
+ tags :upgrade_scenario
6
+ confine do
7
+ feature(:satellite) &&
8
+ (feature(:satellite).current_minor_version == '6.9' || \
9
+ ForemanMaintain.upgrade_in_progress == '6.9.z')
10
+ end
11
+ instance_eval(&block)
12
+ end
13
+ end
14
+
15
+ def target_version
16
+ '6.9.z'
17
+ end
18
+ end
19
+
20
+ class PreUpgradeCheck < Abstract
21
+ upgrade_metadata do
22
+ description 'Checks before upgrading to Satellite 6.9.z'
23
+ tags :pre_upgrade_checks
24
+ run_strategy :fail_slow
25
+ end
26
+
27
+ def compose
28
+ add_steps(find_checks(:default))
29
+ add_steps(find_checks(:pre_upgrade))
30
+ add_step(Checks::Repositories::Validate.new(:version => '6.9'))
31
+ end
32
+ end
33
+
34
+ class PreMigrations < Abstract
35
+ upgrade_metadata do
36
+ description 'Procedures before migrating to Satellite 6.9.z'
37
+ tags :pre_migrations
38
+ end
39
+
40
+ def compose
41
+ add_steps(find_procedures(:pre_migrations))
42
+ add_step(Procedures::Service::Stop.new)
43
+ end
44
+ end
45
+
46
+ class Migrations < Abstract
47
+ upgrade_metadata do
48
+ description 'Migration scripts to Satellite 6.9.z'
49
+ tags :migrations
50
+ end
51
+
52
+ def set_context_mapping
53
+ context.map(:assumeyes, Procedures::Installer::Upgrade => :assumeyes)
54
+ end
55
+
56
+ def compose
57
+ add_step(Procedures::Repositories::Setup.new(:version => '6.9'))
58
+ add_step(Procedures::Packages::UnlockVersions.new)
59
+ add_step(Procedures::Packages::Update.new(:assumeyes => true))
60
+ add_step_with_context(Procedures::Installer::Upgrade)
61
+ add_step(Procedures::Installer::UpgradeRakeTask)
62
+ end
63
+ end
64
+
65
+ class PostMigrations < Abstract
66
+ upgrade_metadata do
67
+ description 'Procedures after migrating to Satellite 6.9.z'
68
+ tags :post_migrations
69
+ end
70
+
71
+ def compose
72
+ add_step(Procedures::Service::Start.new)
73
+ add_steps(find_procedures(:post_migrations))
74
+ end
75
+ end
76
+
77
+ class PostUpgradeChecks < Abstract
78
+ upgrade_metadata do
79
+ description 'Checks after upgrading to Satellite 6.9.z'
80
+ tags :post_upgrade_checks
81
+ run_strategy :fail_slow
82
+ end
83
+
84
+ def compose
85
+ add_steps(find_checks(:default))
86
+ add_steps(find_checks(:post_upgrade))
87
+ end
88
+ end
89
+ end
@@ -21,6 +21,7 @@ module ForemanMaintain
21
21
  require 'foreman_maintain/concerns/base_database'
22
22
  require 'foreman_maintain/concerns/directory_marker'
23
23
  require 'foreman_maintain/concerns/downstream'
24
+ require 'foreman_maintain/concerns/primary_checks'
24
25
  require 'foreman_maintain/top_level_modules'
25
26
  require 'foreman_maintain/yaml_storage'
26
27
  require 'foreman_maintain/config'
@@ -41,6 +42,7 @@ module ForemanMaintain
41
42
  require 'foreman_maintain/error'
42
43
 
43
44
  class << self
45
+ include ForemanMaintain::Concerns::PrimaryChecks
44
46
  attr_accessor :config, :logger
45
47
 
46
48
  LOGGER_LEVEL_MAPPING = {
@@ -153,7 +155,7 @@ module ForemanMaintain
153
155
  def pkg_and_cmd_name
154
156
  instance_feature = ForemanMaintain.available_features(:label => :instance).first
155
157
  if instance_feature.downstream
156
- return %w[satellite-maintain satellite-maintain]
158
+ return instance_feature.downstream.fm_pkg_and_cmd_name
157
159
  end
158
160
 
159
161
  [main_package_name, 'foreman-maintain']
@@ -27,6 +27,14 @@ module ForemanMaintain
27
27
  subcommand 'content', 'Content related commands', ContentCommand
28
28
  subcommand 'maintenance-mode', 'Control maintenance-mode for application',
29
29
  MaintenanceModeCommand
30
+ if ForemanMaintain.detector.feature(:satellite) &&
31
+ ForemanMaintain.detector.feature(:satellite).current_minor_version == '6.9'
32
+ subcommand 'prep-6.10-upgrade', 'Preparations for the Satellite 6.10 upgrade' do
33
+ def execute
34
+ run_scenarios_and_exit(Scenarios::Prep610Upgrade.new)
35
+ end
36
+ end
37
+ end
30
38
 
31
39
  def run(*arguments)
32
40
  logger.info("Running foreman-maintain command with arguments #{arguments.inspect}")
@@ -7,9 +7,24 @@ module ForemanMaintain
7
7
  end
8
8
  end
9
9
 
10
- subcommand 'switchover', 'Switch support for certain content from Pulp 2 to Pulp 3' do
10
+ unless ForemanMaintain.detector.feature(:satellite) ||
11
+ ForemanMaintain.detector.feature(:capsule)
12
+ subcommand 'switchover', 'Switch support for certain content from Pulp 2 to Pulp 3' do
13
+ def execute
14
+ run_scenarios_and_exit(Scenarios::Content::Switchover.new)
15
+ end
16
+ end
17
+ end
18
+
19
+ subcommand 'prepare-abort', 'Abort all running Pulp 2 to Pulp 3 migration tasks' do
20
+ def execute
21
+ run_scenarios_and_exit(Scenarios::Content::PrepareAbort.new)
22
+ end
23
+ end
24
+
25
+ subcommand 'migration-stats', 'Retrieve Pulp 2 to Pulp 3 migration statistics' do
11
26
  def execute
12
- run_scenarios_and_exit(Scenarios::Content::Switchover.new)
27
+ run_scenarios_and_exit(Scenarios::Content::MigrationStats.new)
13
28
  end
14
29
  end
15
30
  end
@@ -67,6 +67,7 @@ module ForemanMaintain
67
67
  disable_self_upgrade_option
68
68
 
69
69
  def execute
70
+ ForemanMaintain.validate_downstream_packages
70
71
  ForemanMaintain.perform_self_upgrade unless disable_self_upgrade?
71
72
  upgrade_runner.run_phase(:pre_upgrade_checks)
72
73
  exit upgrade_runner.exit_code
@@ -86,6 +87,7 @@ module ForemanMaintain
86
87
  end
87
88
 
88
89
  def execute
90
+ ForemanMaintain.validate_downstream_packages
89
91
  ForemanMaintain.perform_self_upgrade unless disable_self_upgrade?
90
92
  if phase
91
93
  upgrade_runner.run_phase(phase.to_sym)
@@ -54,6 +54,10 @@ module ForemanMaintain
54
54
  raise NotImplementedError
55
55
  end
56
56
 
57
+ def fm_pkg_and_cmd_name
58
+ %w[satellite-maintain satellite-maintain]
59
+ end
60
+
57
61
  private
58
62
 
59
63
  def rh_repos(server_version)
@@ -0,0 +1,23 @@
1
+ module ForemanMaintain
2
+ module Concerns
3
+ module PrimaryChecks
4
+ def validate_downstream_packages
5
+ return unless detector.feature(:installer) && detector.feature(:installer).with_scenarios?
6
+ if (package = package_name) && !package_manager.installed?(package)
7
+ raise ForemanMaintain::Error::Fail,
8
+ "Error: Important rpm package #{package} is not installed!"\
9
+ "\nInstall #{package} rpm to ensure system consistency."
10
+ end
11
+ end
12
+
13
+ def package_name
14
+ installed_scenario = detector.feature(:installer).last_scenario
15
+ if installed_scenario == 'satellite'
16
+ 'satellite'
17
+ elsif installed_scenario == 'capsule'
18
+ 'satellite-capsule'
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -8,6 +8,7 @@ module ForemanMaintain::PackageManager
8
8
  private
9
9
 
10
10
  def dnf_action(action, packages, with_status: false, assumeyes: false)
11
+ packages = [packages].flatten(1)
11
12
  yum_options = []
12
13
  yum_options << '-y' if assumeyes
13
14
  if with_status
@@ -22,12 +22,13 @@ module ForemanMaintain
22
22
 
23
23
  def after_scenario_finishes(_scenario); end
24
24
 
25
- def on_next_steps(steps)
25
+ def on_next_steps(steps, run_strategy = :fail_fast)
26
26
  return if steps.empty?
27
+
27
28
  if steps.size > 1
28
- multiple_steps_decision(steps)
29
+ multiple_steps_decision(steps, run_strategy)
29
30
  else
30
- single_step_decision(steps.first)
31
+ single_step_decision(steps.first, run_strategy)
31
32
  end
32
33
  end
33
34
 
@@ -46,17 +47,19 @@ module ForemanMaintain
46
47
  end
47
48
 
48
49
  # simple yes/no question, returns :yes, :no or :quit
49
- def ask_decision(message, options = {})
50
- options.validate_options!(:assumeyes)
51
- assumeyes = options.fetch(:assumeyes, assumeyes?)
50
+ # rubocop:disable Metrics/LineLength
51
+ def ask_decision(message, actions_msg: 'y(yes), n(no), q(quit)', assumeyes: assumeyes?, run_strategy: :fail_fast)
52
+ actions_msg = 'y(yes), n(no)' if run_strategy == :fail_slow
52
53
  if assumeyes
53
54
  print("#{message} (assuming yes)")
54
55
  return :yes
55
56
  end
57
+
56
58
  until_valid_decision do
57
- filter_decision(ask("#{message}, [y(yes), n(no), q(quit)]"))
59
+ filter_decision(ask("#{message}, [#{actions_msg}]"))
58
60
  end
59
61
  end
62
+ # rubocop:enable Metrics/LineLength
60
63
 
61
64
  def assumeyes=(assume)
62
65
  @assumeyes = !!assume
@@ -64,8 +67,8 @@ module ForemanMaintain
64
67
 
65
68
  private
66
69
 
67
- def single_step_decision(step)
68
- answer = ask_decision("Continue with step [#{step.description}]?")
70
+ def single_step_decision(step, run_strategy)
71
+ answer = ask_decision("Continue with step [#{step.description}]?", run_strategy: run_strategy)
69
72
  if answer == :yes
70
73
  step
71
74
  else
@@ -73,12 +76,12 @@ module ForemanMaintain
73
76
  end
74
77
  end
75
78
 
76
- def multiple_steps_decision(steps)
79
+ def multiple_steps_decision(steps, run_strategy)
77
80
  puts 'There are multiple steps to proceed:'
78
81
  steps.each_with_index do |step, index|
79
82
  puts "#{index + 1}) #{step.description}"
80
83
  end
81
- ask_to_select('Select step to continue', steps, &:description)
84
+ ask_to_select('Select step to continue', steps, run_strategy)
82
85
  end
83
86
 
84
87
  def filter_decision(answer)
@@ -90,13 +93,15 @@ module ForemanMaintain
90
93
  end
91
94
 
92
95
  # rubocop:disable Metrics/MethodLength
93
- def ask_to_select(message, steps)
96
+ def ask_to_select(message, steps, run_strategy)
94
97
  if assumeyes?
95
98
  puts('(assuming first option)')
96
99
  return steps.first
97
100
  end
98
101
  until_valid_decision do
99
- answer = ask("#{message}, [n(next), q(quit)]")
102
+ actions = run_strategy == :fail_slow ? 'n(next)' : 'n(next), q(quit)'
103
+
104
+ answer = ask("#{message}, [#{actions}]")
100
105
  if answer =~ /^\d+$/ && (answer.to_i - 1) < steps.size
101
106
  steps[answer.to_i - 1]
102
107
  else
@@ -67,6 +67,7 @@ module ForemanMaintain
67
67
  end
68
68
  end
69
69
 
70
+ attr_accessor :select_option_counter
70
71
  attr_reader :last_line, :max_length
71
72
 
72
73
  def initialize(stdout = STDOUT, stdin = STDIN, options = {})
@@ -81,6 +82,7 @@ module ForemanMaintain
81
82
  @spinner = Spinner.new(self)
82
83
  @spinner.start_spinner if @stdout.tty?
83
84
  @last_line = ''
85
+ @select_option_counter = 0
84
86
  end
85
87
 
86
88
  def before_scenario_starts(scenario)
@@ -167,8 +169,9 @@ module ForemanMaintain
167
169
  @assumeyes
168
170
  end
169
171
 
170
- def single_step_decision(step)
171
- answer = ask_decision("Continue with step [#{step.runtime_message}]?")
172
+ def single_step_decision(step, run_strategy)
173
+ answer = ask_decision("Continue with step [#{step.runtime_message}]?",
174
+ run_strategy: run_strategy)
172
175
  if answer == :yes
173
176
  step
174
177
  else
@@ -176,25 +179,28 @@ module ForemanMaintain
176
179
  end
177
180
  end
178
181
 
179
- def multiple_steps_decision(steps)
182
+ def multiple_steps_decision(steps, run_strategy)
180
183
  puts 'There are multiple steps to proceed:'
181
184
  steps.each_with_index do |step, index|
182
185
  puts "#{index + 1}) #{step.runtime_message}"
183
186
  end
184
- ask_to_select('Select step to continue', steps, &:runtime_message)
187
+ ask_to_select('Select step to continue', steps, run_strategy)
185
188
  end
186
189
 
187
- def ask_decision(message, options = 'y(yes), n(no), q(quit)', ignore_assumeyes: false)
190
+ # rubocop:disable Metrics/LineLength
191
+ def ask_decision(message, actions_msg: 'y(yes), n(no), q(quit)', ignore_assumeyes: false, run_strategy: :fail_fast)
192
+ actions_msg = 'y(yes), n(no)' if run_strategy == :fail_slow
188
193
  if !ignore_assumeyes && assumeyes?
189
194
  print("#{message} (assuming yes)\n")
190
195
  return :yes
191
196
  end
192
197
  until_valid_decision do
193
- filter_decision(ask("#{message}, [#{options}]"))
198
+ filter_decision(ask("#{message}, [#{actions_msg}]"))
194
199
  end
195
200
  ensure
196
201
  clear_line
197
202
  end
203
+ # rubocop:enable Metrics/LineLength
198
204
 
199
205
  def filter_decision(answer)
200
206
  decision = nil
@@ -206,13 +212,17 @@ module ForemanMaintain
206
212
  end
207
213
 
208
214
  # rubocop:disable Metrics/MethodLength
209
- def ask_to_select(message, steps)
215
+ def ask_to_select(message, steps, run_strategy)
210
216
  if assumeyes?
211
- puts('(assuming first option)')
212
- return steps.first
217
+ step = steps[@select_option_counter]
218
+ @select_option_counter += 1
219
+ puts("(assuming option #{@select_option_counter})")
220
+ return step
213
221
  end
222
+
214
223
  until_valid_decision do
215
- answer = ask("#{message}, [n(next), q(quit)]")
224
+ actions = run_strategy == :fail_slow ? 'n(next)' : 'n(next), q(quit)'
225
+ answer = ask("#{message}, [#{actions}]")
216
226
  if answer =~ /^\d+$/ && (answer.to_i - 1) < steps.size
217
227
  steps[answer.to_i - 1]
218
228
  else
@@ -277,6 +287,7 @@ module ForemanMaintain
277
287
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
278
288
  def scenario_failure_message(scenario)
279
289
  return if scenario.passed? && !scenario.warning?
290
+
280
291
  message = []
281
292
  message << <<-MESSAGE.strip_heredoc
282
293
  Scenario [#{scenario.description}] failed.
@@ -293,13 +304,15 @@ module ForemanMaintain
293
304
  end
294
305
 
295
306
  steps_with_error = scenario.steps_with_error(:whitelisted => false)
307
+ steps_with_skipped = scenario.steps_with_skipped(:whitelisted => true)
308
+ steps_to_whitelist = steps_with_error + steps_with_skipped
296
309
  unless steps_with_error.empty?
297
310
  message << format(<<-MESSAGE.strip_heredoc, format_steps(steps_with_error, "\n", 2))
298
311
  The following steps ended up in failing state:
299
312
 
300
313
  %s
301
314
  MESSAGE
302
- whitelist_labels = steps_with_error.map(&:label_dashed).join(',')
315
+ whitelist_labels = steps_to_whitelist.map(&:label_dashed).join(',')
303
316
  recommend << format(<<-MESSAGE.strip_heredoc, whitelist_labels)
304
317
  Resolve the failed steps and rerun
305
318
  the command. In case the failures are false positives,
@@ -18,6 +18,7 @@ module ForemanMaintain
18
18
  @last_scenario = nil
19
19
  @last_scenario_continuation_confirmed = false
20
20
  @exit_code = 0
21
+ @procedure_step_counter = 0
21
22
  end
22
23
 
23
24
  def quit?
@@ -70,7 +71,8 @@ module ForemanMaintain
70
71
  :quit
71
72
  elsif @last_scenario.steps_with_warning(:whitelisted => false).any?
72
73
  @last_scenario_continuation_confirmed = true
73
- reporter.ask_decision("Continue with [#{scenario.description}]")
74
+ reporter.ask_decision("Continue with [#{scenario.description}]",
75
+ run_strategy: scenario.run_strategy)
74
76
  end
75
77
 
76
78
  ask_to_quit if [:quit, :no].include?(decision)
@@ -131,7 +133,7 @@ module ForemanMaintain
131
133
  if execution.aborted?
132
134
  ask_to_quit
133
135
  else
134
- next_steps_decision = ask_about_offered_steps(step)
136
+ next_steps_decision = ask_about_offered_steps(step, scenario)
135
137
  if next_steps_decision != :yes &&
136
138
  execution.fail? && !execution.whitelisted? &&
137
139
  scenario.run_strategy == :fail_fast
@@ -141,15 +143,18 @@ module ForemanMaintain
141
143
  end
142
144
 
143
145
  # rubocop:disable Metrics/MethodLength
144
- def ask_about_offered_steps(step)
145
- if assumeyes? && rerun_check?(step)
146
- @reporter.puts 'Check still failing after attempt to fix. Skipping'
147
- return :no
148
- end
146
+ def ask_about_offered_steps(step, scenario)
149
147
  if step.next_steps && !step.next_steps.empty?
150
148
  @last_decision_step = step
149
+ @procedure_step_counter += 1
151
150
  steps = step.next_steps.map(&:ensure_instance)
152
- decision = @reporter.on_next_steps(steps)
151
+ if assumeyes? && @procedure_step_counter > steps.length
152
+ @procedure_step_counter = 0
153
+ @reporter.select_option_counter = 0
154
+ @reporter.puts 'Check still failing after attempt to fix. Skipping'
155
+ return :no
156
+ end
157
+ decision = @reporter.on_next_steps(steps, scenario.run_strategy)
153
158
  case decision
154
159
  when :quit
155
160
  ask_to_quit