foreman_maintain 0.0.2 → 0.0.3

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +107 -25
  3. data/bin/foreman-maintain +1 -0
  4. data/definitions/checks/disk_speed_minimal.rb +31 -19
  5. data/definitions/checks/foreman_tasks/invalid/check_old.rb +20 -0
  6. data/definitions/checks/foreman_tasks/invalid/check_pending_state.rb +20 -0
  7. data/definitions/checks/foreman_tasks/invalid/check_planning_state.rb +20 -0
  8. data/definitions/checks/foreman_tasks/not_paused.rb +29 -0
  9. data/definitions/checks/foreman_tasks/not_running.rb +14 -0
  10. data/definitions/checks/sync_plans/with_disabled_status.rb +18 -0
  11. data/definitions/checks/sync_plans/with_enabled_status.rb +18 -0
  12. data/definitions/checks/system_registration.rb +31 -0
  13. data/definitions/features/downstream.rb +5 -3
  14. data/definitions/features/foreman_1_11_x.rb +4 -2
  15. data/definitions/features/foreman_1_7_x.rb +5 -3
  16. data/definitions/features/foreman_database.rb +11 -5
  17. data/definitions/features/foreman_tasks.rb +118 -9
  18. data/definitions/features/sync_plans.rb +75 -0
  19. data/definitions/features/upstream.rb +5 -3
  20. data/definitions/procedures/foreman_tasks/delete.rb +33 -0
  21. data/definitions/procedures/foreman_tasks/resume.rb +14 -0
  22. data/definitions/procedures/foreman_tasks/ui_investigate.rb +19 -0
  23. data/definitions/procedures/hammer_setup.rb +50 -0
  24. data/definitions/procedures/install_package.rb +17 -0
  25. data/definitions/procedures/sync_plans/disable.rb +22 -0
  26. data/definitions/procedures/sync_plans/enable.rb +21 -0
  27. data/definitions/scenarios/pre_upgrade_check_foreman_1_14.rb +7 -6
  28. data/definitions/scenarios/pre_upgrade_check_satellite_6_0_z.rb +8 -6
  29. data/definitions/scenarios/pre_upgrade_check_satellite_6_1.rb +8 -6
  30. data/definitions/scenarios/pre_upgrade_check_satellite_6_1_z.rb +8 -6
  31. data/definitions/scenarios/pre_upgrade_check_satellite_6_2.rb +8 -6
  32. data/definitions/scenarios/pre_upgrade_check_satellite_6_2_z.rb +8 -6
  33. data/definitions/scenarios/pre_upgrade_check_satellite_6_3.rb +8 -6
  34. data/lib/foreman_maintain.rb +52 -5
  35. data/lib/foreman_maintain/check.rb +18 -12
  36. data/lib/foreman_maintain/cli/base.rb +9 -2
  37. data/lib/foreman_maintain/cli/health_command.rb +2 -1
  38. data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
  39. data/lib/foreman_maintain/concerns/hammer.rb +20 -0
  40. data/lib/foreman_maintain/concerns/logger.rb +1 -5
  41. data/lib/foreman_maintain/concerns/metadata.rb +138 -31
  42. data/lib/foreman_maintain/concerns/system_helpers.rb +36 -32
  43. data/lib/foreman_maintain/config.rb +40 -5
  44. data/lib/foreman_maintain/core_ext.rb +24 -0
  45. data/lib/foreman_maintain/detector.rb +12 -13
  46. data/lib/foreman_maintain/error.rb +28 -0
  47. data/lib/foreman_maintain/executable.rb +86 -11
  48. data/lib/foreman_maintain/feature.rb +1 -0
  49. data/lib/foreman_maintain/param.rb +47 -0
  50. data/lib/foreman_maintain/reporter.rb +20 -3
  51. data/lib/foreman_maintain/reporter/cli_reporter.rb +166 -66
  52. data/lib/foreman_maintain/runner.rb +56 -13
  53. data/lib/foreman_maintain/runner/execution.rb +8 -0
  54. data/lib/foreman_maintain/scenario.rb +46 -2
  55. data/lib/foreman_maintain/top_level_modules.rb +3 -0
  56. data/lib/foreman_maintain/utils.rb +2 -0
  57. data/lib/foreman_maintain/utils/command_runner.rb +101 -0
  58. data/lib/foreman_maintain/utils/disk/device.rb +5 -9
  59. data/lib/foreman_maintain/utils/hammer.rb +78 -0
  60. data/lib/foreman_maintain/version.rb +1 -1
  61. data/lib/foreman_maintain/yaml_storage.rb +48 -0
  62. metadata +27 -9
  63. data/definitions/checks/foreman_tasks_not_paused.rb +0 -14
  64. data/definitions/checks/foreman_tasks_not_running.rb +0 -10
  65. data/definitions/procedures/foreman_tasks_resume.rb +0 -13
  66. data/lib/foreman_maintain/logger.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe40b2c9fdd4999acc0a0b764a916815e51c9c4a
4
- data.tar.gz: cf9939ee27a333b61665f3eee0277005bfdd0167
3
+ metadata.gz: 3685c87a51938c933602dc6c14326eff9dcd0f17
4
+ data.tar.gz: aecc1a267b26067df5a4ecda9ffda31ddd278983
5
5
  SHA512:
6
- metadata.gz: c3297df9601ce8f75dae19f2539b9563434d523d2f3eec602f4562bb6ce98ff29a3622f5c07c859a4da29c6f2cd38f2d90cd8d9d3531dee6b6f08bc49fdecefc
7
- data.tar.gz: 67e607579907ad237d497692781c7e226352f87b9494f3cbe51aa167e67298ef500884b2099b386a002a9604432a4afa41da8c74a0b51bcf64721a5fa9a421e8
6
+ metadata.gz: e972a4b2e2375bc8af5190c66b897fb9604ebada63804fc57a73547b93169b4a919ff54439e4efb2c4438b19b0b10b35f6d4cfd7805043479c4954d2f31b4acd
7
+ data.tar.gz: 521e0c73a330a750cfeee298ca9b7d2ed9341b4e863f56cb1a791df3b774a97c1fc27352d8bec14a453549fc9bb30fd3b87da059418b6266f0aca3a5e6d6269e
data/README.md CHANGED
@@ -55,10 +55,12 @@ definitions.
55
55
 
56
56
  ```ruby
57
57
  class Features::Foreman < ForemanMaintain::Feature
58
- label :foreman
58
+ metadata do
59
+ label :foreman
59
60
 
60
- confine do
61
- check_min_version('foreman', '1.7')
61
+ confine do
62
+ check_min_version('foreman', '1.7')
63
+ end
62
64
  end
63
65
 
64
66
  # helper method that can be used in other definitions like this:
@@ -81,22 +83,19 @@ Checks define assertions to determine status of the system.
81
83
 
82
84
  ```ruby
83
85
  class Checks::ForemanIsRuning < ForemanMaintain::Check
84
- for_feature :foreman
85
-
86
- description 'check foreman service is running'
87
-
88
- tags :basic
86
+ metadata do
87
+ for_feature :foreman
88
+ description 'check foreman service is running'
89
+ tags :default
90
+ end
89
91
 
90
92
  def run
91
93
  # we are using methods of a feature.
94
+ # we can define additional steps to be executed as a follow-up
95
+ # of assertion failure
92
96
  assert(feature(:foreman).running?
93
- 'There are currently paused tasks in the system')
94
- end
95
-
96
- # we can define additional steps to be executed after this check is finished
97
- # based on the result
98
- def next_steps
99
- [procedure(Procedures::ForemanStart)] if fail?
97
+ 'There are currently paused tasks in the system'),
98
+ :next_steps => Procedures::ForemanStart.new)
100
99
  end
101
100
  end
102
101
  ```
@@ -107,6 +106,23 @@ Similarly as features, also checks (and in fact all definitions) can used
107
106
  Every definition has a `label` (if not stated explicitly, it's
108
107
  determined from the class name).
109
108
 
109
+ In case some operation take more time, it's possible to enable a spinner
110
+ and update the spinner continuously with `with_spinner` method.
111
+
112
+ ```ruby
113
+ def run
114
+ with_spinner do |spinner|
115
+ spinner.update 'checking foreman is running'
116
+ if feature(:foreman).running?
117
+ spinner.update 'foreman is not started, starting'
118
+ feature(:foreman).start
119
+ else
120
+ spinner.update 'foreman is started, restarting'
121
+ end
122
+ end
123
+ end
124
+ ```
125
+
110
126
  ### Procedures
111
127
 
112
128
  Procedure defines some operation that can be performed against the system.
@@ -114,9 +130,10 @@ It can be part of a scenario or be linked from a check as a remediation step.
114
130
 
115
131
  ```ruby
116
132
  class Procedures::ForemanStart < ForemanMaintain::Procedure
117
- for_feature :foreman
118
-
119
- description 'start foreman service'
133
+ metadata do
134
+ for_feature :foreman
135
+ description 'start foreman service'
136
+ end
120
137
 
121
138
  def run
122
139
  feature(:foreman).start
@@ -124,6 +141,49 @@ class Procedures::ForemanStart < ForemanMaintain::Procedure
124
141
  end
125
142
  ```
126
143
 
144
+ ### Preparation steps
145
+
146
+ Some steps can require some additional steps to be performed before we
147
+ can proceed. A typical example is installing additional dependencies.
148
+ A preparation step is usually a procedure.
149
+
150
+ ```ruby
151
+ class Procedures::InstallPackage < ForemanMaintain::Procedure
152
+ metadata do
153
+ # definitions of parameters of the procedure
154
+ param :packages, 'List of packages to install', :array => true
155
+ end
156
+
157
+ def run
158
+ install_packages(@packages)
159
+ end
160
+
161
+ # if false, the step will be considered as done: it will not be executed
162
+ def necessary?
163
+ @packages.any? { |package| package_version(package).nil? }
164
+ end
165
+
166
+ def description
167
+ "Install package(s) #{@packages.join(', ')}"
168
+ end
169
+ end
170
+
171
+ class Checks::DiskIO < ForemanMaintain::Check
172
+ metadata do
173
+ description 'check foreman service is running'
174
+ preparation_steps { Procedures::InstallPackage.new(:packages => %w[hdparm]) }
175
+ end
176
+
177
+ def run
178
+ execute!('hdparam ...')
179
+ end
180
+ end
181
+ ```
182
+
183
+ When running a scenario, all the preparation steps in that scenario
184
+ will be collected, and run if necessary (the `necessary?` method
185
+ returning `true`). The preparation steps will be run as separate scenario.
186
+
127
187
  ### Scenarios
128
188
 
129
189
  Scenarios represent a composition of various steps (checks and procedures) to
@@ -132,22 +192,44 @@ achieve some complex maintenance operation in the system (such as upgrade).
132
192
 
133
193
  ```ruby
134
194
  class Scenarios::PreUpgradeCheckForeman_1_14 < ForemanMaintain::Scenario
135
- description 'checks before upgrading to Foreman 1.14'
136
-
137
- confine do
138
- feature(:upstream)
195
+ metadata do
196
+ description 'checks before upgrading to Foreman 1.14'
197
+ confine do
198
+ feature(:upstream)
199
+ end
200
+ tags :pre_upgrade_check
139
201
  end
140
202
 
141
- tags :pre_upgrade_check
142
-
143
203
  # Method to be called when composing the steps of the scenario
144
204
  def compose
145
205
  # we can search for the checks by metadata
146
- steps.concat(find_checks(:basic))
206
+ steps.concat(find_checks(:default))
147
207
  end
148
208
  end
149
209
  ```
150
210
 
211
+ ### Hammer
212
+
213
+ In some cases, it's useful to be able to use the hammer as part of check/fix procedures.
214
+ The easiest way to achieve this is to include `ForemanMaintain::Concerns::Hammer` module:
215
+
216
+ ```ruby
217
+ include ForemanMaintain::Concerns::Hammer
218
+
219
+ def run
220
+ hammer('task resume')
221
+ end
222
+ ```
223
+
224
+ We expect the credentials for the hammer commands to to be stored inside the hammer settings:
225
+
226
+ ```
227
+ # ~/.hammer/cli.modules.d/foreman.yml
228
+ :foreman:
229
+ :username: 'admin'
230
+ :password: 'changeme'
231
+ ```
232
+
151
233
  ## Implementation components
152
234
 
153
235
  In order to process the definitions, there are other components present in the `lib` directory.
@@ -3,6 +3,7 @@
3
3
  $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
4
 
5
5
  require 'foreman_maintain'
6
+
6
7
  ForemanMaintain.setup
7
8
 
8
9
  require 'foreman_maintain/cli'
@@ -1,41 +1,53 @@
1
1
  class Checks::DiskSpeedMinimal < ForemanMaintain::Check
2
+ metadata do
3
+ label :disk_io
4
+ description 'Check for recommended disk speed of pulp, mongodb, pgsql dir.'
5
+ tags :pre_upgrade
6
+ preparation_steps { Procedures::InstallPackage.new(:packages => %w[hdparm fio]) }
7
+ end
8
+
2
9
  EXPECTED_IO = 80
3
10
  DEFAULT_UNIT = 'MB/sec'.freeze
4
11
  DEFAULT_DIRS = ['/var/lib/pulp', '/var/lib/mongodb', '/var/lib/pgsql'].freeze
5
12
 
6
- label :disk_io
7
- description 'Check for recommended disk speed of pulp, mongodb, pgsql dir.'
8
- tags :basic
13
+ def run
14
+ with_spinner(description) do |spinner|
15
+ io_obj, success = compute_disk_speed(spinner)
16
+ spinner.update('Finished')
9
17
 
10
- confine do
11
- execute?('which hdparm') && execute?('which fio')
18
+ assert(success, io_obj.slow_disk_error_msg)
19
+ end
12
20
  end
13
21
 
14
- def run
22
+ def check_only_single_device?
23
+ DEFAULT_DIRS.map do |dir|
24
+ ForemanMaintain::Utils::Disk::Device.new(dir).name
25
+ end.uniq.length <= 1
26
+ end
27
+
28
+ def dirs_to_check
29
+ return DEFAULT_DIRS.first(1) if check_only_single_device?
30
+ DEFAULT_DIRS
31
+ end
32
+
33
+ private
34
+
35
+ def compute_disk_speed(spinner)
15
36
  success = true
16
37
  io_obj = ForemanMaintain::Utils::Disk::NilDevice.new
17
38
 
18
39
  dirs_to_check.each do |dir|
19
40
  io_obj = ForemanMaintain::Utils::Disk::Device.new(dir)
20
41
 
42
+ spinner.update("[Speed check In-Progress] device: #{io_obj.name}")
43
+
21
44
  next if io_obj.read_speed >= EXPECTED_IO
22
45
 
23
46
  success = false
24
- logger.info "\n Slow disk detected for #{dir} - #{io_obj.read_speed} #{io_obj.unit}."
47
+ logger.info "Slow disk detected #{dir}: #{io_obj.read_speed} #{io_obj.unit}."
25
48
  break
26
49
  end
27
50
 
28
- assert(success, io_obj.slow_disk_error_msg)
29
- end
30
-
31
- def check_only_single_device?
32
- DEFAULT_DIRS.map do |dir|
33
- ForemanMaintain::Utils::Disk::Device.new(dir).name
34
- end.uniq.length <= 1
35
- end
36
-
37
- def dirs_to_check
38
- return DEFAULT_DIRS.first(1) if check_only_single_device?
39
- DEFAULT_DIRS
51
+ [io_obj, success]
40
52
  end
41
53
  end
@@ -0,0 +1,20 @@
1
+ module Checks::ForemanTasks
2
+ module Invalid
3
+ class CheckOld < ForemanMaintain::Check
4
+ metadata do
5
+ label :check_old_foreman_tasks
6
+ for_feature :foreman_tasks
7
+ tags :pre_upgrade
8
+ description 'Check for old tasks in paused/stopped state'
9
+ end
10
+
11
+ def run
12
+ # Check and delete 'all tasks beyond 30 days(paused and stopped)'
13
+ count_old_tasks = feature(:foreman_tasks).count(:old)
14
+ assert(count_old_tasks <= 0,
15
+ "Found #{count_old_tasks} paused or stopped task(s) older than 30 days",
16
+ :next_steps => Procedures::ForemanTasks::Delete.new(:state => :old))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Checks::ForemanTasks
2
+ module Invalid
3
+ class CheckPendingState < ForemanMaintain::Check
4
+ metadata do
5
+ label :check_foreman_tasks_in_pending_state
6
+ for_feature :foreman_tasks
7
+ tags :pre_upgrade
8
+ description 'Check for pending tasks which are safe to delete'
9
+ end
10
+
11
+ def run
12
+ # Check and delete 'all tasks in pending state'
13
+ count_tasks_in_pending_state = feature(:foreman_tasks).count(:pending)
14
+ assert(count_tasks_in_pending_state <= 0,
15
+ "Found #{count_tasks_in_pending_state} pending task(s) which are safe to delete",
16
+ :next_steps => Procedures::ForemanTasks::Delete.new(:state => :pending))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Checks::ForemanTasks
2
+ module Invalid
3
+ class CheckPlanningState < ForemanMaintain::Check
4
+ metadata do
5
+ label :check_foreman_tasks_in_planning_state
6
+ for_feature :foreman_tasks
7
+ tags :pre_upgrade
8
+ description 'Check for tasks in planning state'
9
+ end
10
+
11
+ def run
12
+ # Check and delete 'all tasks in planning state'
13
+ tasks_in_planning_count = feature(:foreman_tasks).count(:planning)
14
+ assert(tasks_in_planning_count <= 0,
15
+ "Found #{tasks_in_planning_count} task(s) in planning state",
16
+ :next_steps => Procedures::ForemanTasks::Delete.new(:state => :planning))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ module Checks::ForemanTasks
2
+ class NotPaused < ForemanMaintain::Check
3
+ metadata do
4
+ for_feature :foreman_tasks
5
+ description 'check for paused tasks'
6
+ tags :default
7
+ end
8
+
9
+ def run
10
+ paused_tasks_count = feature(:foreman_tasks).paused_tasks_count(ignored_tasks)
11
+ assert(paused_tasks_count == 0,
12
+ "There are currently #{paused_tasks_count} paused tasks in the system",
13
+ :next_steps =>
14
+ [Procedures::ForemanTasks::Resume.new,
15
+ Procedures::ForemanTasks::UiInvestigate.new('search_query' => scoped_search_query)])
16
+ end
17
+
18
+ # Note: this is for UI link generation only: we are not using scoped search for querying
19
+ # the tasks itself as we use direct SQL instead
20
+ def scoped_search_query
21
+ "state = paused AND label !^(#{ignored_tasks.join(' ')})"
22
+ end
23
+
24
+ def ignored_tasks
25
+ %w[Actions::Candlepin::ListenOnCandlepinEvents
26
+ Actions::Katello::EventQueue::Monitor]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ module Checks::ForemanTasks
2
+ class NotRunning < ForemanMaintain::Check
3
+ metadata do
4
+ for_feature :foreman_tasks
5
+ description 'check for running tasks'
6
+ tags :pre_upgrade
7
+ end
8
+
9
+ def run
10
+ assert(feature(:foreman_tasks).running_tasks_count == 0,
11
+ 'There are actively running tasks in the system')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Checks::SyncPlans
2
+ class WithDisabledStatus < ForemanMaintain::Check
3
+ include ForemanMaintain::Concerns::Hammer
4
+
5
+ metadata do
6
+ for_feature :sync_plans
7
+ description 'check for disabled sync plans'
8
+ tags :post_upgrade
9
+ end
10
+
11
+ def run
12
+ disabled_plans_count = feature(:sync_plans).disabled_plans_count
13
+ assert(disabled_plans_count == 0,
14
+ "There are #{disabled_plans_count} disabled sync plans which needs to be enabled",
15
+ :next_steps => Procedures::SyncPlans::Enable.new)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Checks::SyncPlans
2
+ class WithEnabledStatus < ForemanMaintain::Check
3
+ include ForemanMaintain::Concerns::Hammer
4
+
5
+ metadata do
6
+ for_feature :sync_plans
7
+ description 'check for enabled sync plans'
8
+ tags :pre_upgrade
9
+ end
10
+
11
+ def run
12
+ active_sync_plans_count = feature(:sync_plans).active_sync_plans_count
13
+ assert(active_sync_plans_count == 0,
14
+ "There are total #{active_sync_plans_count} active sync plans in the system",
15
+ :next_steps => Procedures::SyncPlans::Disable.new)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ class Checks::SystemRegistration < ForemanMaintain::Check
2
+ metadata do
3
+ label :verify_self_registration
4
+ description 'Check whether system is self-registered or not'
5
+ tags :default
6
+
7
+ confine do
8
+ file_exists?('/etc/rhsm/rhsm.conf')
9
+ end
10
+ end
11
+
12
+ def run
13
+ if system_is_self_registerd?
14
+ raise ForemanMaintain::Error::Warn, 'System is self registered'
15
+ else
16
+ puts 'System is not self registered'
17
+ end
18
+ end
19
+
20
+ def system_is_self_registerd?
21
+ rhsm_hostname.casecmp(hostname).zero?
22
+ end
23
+
24
+ def rhsm_hostname
25
+ execute("grep '\\bhostname\\b' < #{rhsm_conf_file} | grep -v '^#'").sub(/.*?=/, '').strip
26
+ end
27
+
28
+ def rhsm_conf_file
29
+ '/etc/rhsm/rhsm.conf'
30
+ end
31
+ end