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.
- checksums.yaml +4 -4
- data/README.md +107 -25
- data/bin/foreman-maintain +1 -0
- data/definitions/checks/disk_speed_minimal.rb +31 -19
- data/definitions/checks/foreman_tasks/invalid/check_old.rb +20 -0
- data/definitions/checks/foreman_tasks/invalid/check_pending_state.rb +20 -0
- data/definitions/checks/foreman_tasks/invalid/check_planning_state.rb +20 -0
- data/definitions/checks/foreman_tasks/not_paused.rb +29 -0
- data/definitions/checks/foreman_tasks/not_running.rb +14 -0
- data/definitions/checks/sync_plans/with_disabled_status.rb +18 -0
- data/definitions/checks/sync_plans/with_enabled_status.rb +18 -0
- data/definitions/checks/system_registration.rb +31 -0
- data/definitions/features/downstream.rb +5 -3
- data/definitions/features/foreman_1_11_x.rb +4 -2
- data/definitions/features/foreman_1_7_x.rb +5 -3
- data/definitions/features/foreman_database.rb +11 -5
- data/definitions/features/foreman_tasks.rb +118 -9
- data/definitions/features/sync_plans.rb +75 -0
- data/definitions/features/upstream.rb +5 -3
- data/definitions/procedures/foreman_tasks/delete.rb +33 -0
- data/definitions/procedures/foreman_tasks/resume.rb +14 -0
- data/definitions/procedures/foreman_tasks/ui_investigate.rb +19 -0
- data/definitions/procedures/hammer_setup.rb +50 -0
- data/definitions/procedures/install_package.rb +17 -0
- data/definitions/procedures/sync_plans/disable.rb +22 -0
- data/definitions/procedures/sync_plans/enable.rb +21 -0
- data/definitions/scenarios/pre_upgrade_check_foreman_1_14.rb +7 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_0_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_1.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_1_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_2.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_2_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_3.rb +8 -6
- data/lib/foreman_maintain.rb +52 -5
- data/lib/foreman_maintain/check.rb +18 -12
- data/lib/foreman_maintain/cli/base.rb +9 -2
- data/lib/foreman_maintain/cli/health_command.rb +2 -1
- data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
- data/lib/foreman_maintain/concerns/hammer.rb +20 -0
- data/lib/foreman_maintain/concerns/logger.rb +1 -5
- data/lib/foreman_maintain/concerns/metadata.rb +138 -31
- data/lib/foreman_maintain/concerns/system_helpers.rb +36 -32
- data/lib/foreman_maintain/config.rb +40 -5
- data/lib/foreman_maintain/core_ext.rb +24 -0
- data/lib/foreman_maintain/detector.rb +12 -13
- data/lib/foreman_maintain/error.rb +28 -0
- data/lib/foreman_maintain/executable.rb +86 -11
- data/lib/foreman_maintain/feature.rb +1 -0
- data/lib/foreman_maintain/param.rb +47 -0
- data/lib/foreman_maintain/reporter.rb +20 -3
- data/lib/foreman_maintain/reporter/cli_reporter.rb +166 -66
- data/lib/foreman_maintain/runner.rb +56 -13
- data/lib/foreman_maintain/runner/execution.rb +8 -0
- data/lib/foreman_maintain/scenario.rb +46 -2
- data/lib/foreman_maintain/top_level_modules.rb +3 -0
- data/lib/foreman_maintain/utils.rb +2 -0
- data/lib/foreman_maintain/utils/command_runner.rb +101 -0
- data/lib/foreman_maintain/utils/disk/device.rb +5 -9
- data/lib/foreman_maintain/utils/hammer.rb +78 -0
- data/lib/foreman_maintain/version.rb +1 -1
- data/lib/foreman_maintain/yaml_storage.rb +48 -0
- metadata +27 -9
- data/definitions/checks/foreman_tasks_not_paused.rb +0 -14
- data/definitions/checks/foreman_tasks_not_running.rb +0 -10
- data/definitions/procedures/foreman_tasks_resume.rb +0 -13
- data/lib/foreman_maintain/logger.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3685c87a51938c933602dc6c14326eff9dcd0f17
|
4
|
+
data.tar.gz: aecc1a267b26067df5a4ecda9ffda31ddd278983
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
58
|
+
metadata do
|
59
|
+
label :foreman
|
59
60
|
|
60
|
-
|
61
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
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
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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(:
|
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.
|
data/bin/foreman-maintain
CHANGED
@@ -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
|
-
|
7
|
-
|
8
|
-
|
13
|
+
def run
|
14
|
+
with_spinner(description) do |spinner|
|
15
|
+
io_obj, success = compute_disk_speed(spinner)
|
16
|
+
spinner.update('Finished')
|
9
17
|
|
10
|
-
|
11
|
-
|
18
|
+
assert(success, io_obj.slow_disk_error_msg)
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
|
-
def
|
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 "
|
47
|
+
logger.info "Slow disk detected #{dir}: #{io_obj.read_speed} #{io_obj.unit}."
|
25
48
|
break
|
26
49
|
end
|
27
50
|
|
28
|
-
|
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
|