foreman_maintain 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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