foreman_maintain 0.4.1 → 0.4.2

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 (40) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +7 -1
  3. data/definitions/checks/disk/performance.rb +11 -1
  4. data/definitions/checks/version_locking_enabled.rb +14 -0
  5. data/definitions/features/candlepin_database.rb +1 -1
  6. data/definitions/features/downstream.rb +12 -2
  7. data/definitions/features/foreman_database.rb +1 -1
  8. data/definitions/features/package_manager.rb +34 -0
  9. data/definitions/features/sync_plans.rb +25 -24
  10. data/definitions/procedures/backup/config_files.rb +4 -1
  11. data/definitions/procedures/maintenance_mode/is_enabled.rb +2 -2
  12. data/definitions/procedures/packages/enable_version_locking.rb +17 -0
  13. data/definitions/procedures/packages/lock_versions.rb +17 -0
  14. data/definitions/procedures/packages/locking_status.rb +17 -0
  15. data/definitions/procedures/packages/unlock_versions.rb +13 -0
  16. data/definitions/procedures/packages/update.rb +1 -1
  17. data/definitions/procedures/sync_plans/disable.rb +1 -1
  18. data/definitions/scenarios/backup.rb +3 -3
  19. data/definitions/scenarios/upgrade_to_satellite_6_2.rb +1 -0
  20. data/definitions/scenarios/upgrade_to_satellite_6_2_z.rb +1 -0
  21. data/definitions/scenarios/upgrade_to_satellite_6_3.rb +1 -0
  22. data/definitions/scenarios/upgrade_to_satellite_6_3_z.rb +1 -0
  23. data/definitions/scenarios/upgrade_to_satellite_6_4.rb +1 -0
  24. data/definitions/scenarios/upgrade_to_satellite_6_4_z.rb +1 -0
  25. data/definitions/scenarios/upgrade_to_satellite_6_5.rb +1 -0
  26. data/definitions/scenarios/upgrade_to_satellite_6_5_z.rb +1 -0
  27. data/definitions/scenarios/upgrade_to_satellite_6_6.rb +80 -0
  28. data/definitions/scenarios/version_locking.rb +39 -0
  29. data/lib/foreman_maintain/cli/base.rb +5 -0
  30. data/lib/foreman_maintain/cli/packages_command.rb +36 -0
  31. data/lib/foreman_maintain/cli.rb +2 -0
  32. data/lib/foreman_maintain/concerns/system_helpers.rb +16 -16
  33. data/lib/foreman_maintain/package_manager/base.rb +71 -0
  34. data/lib/foreman_maintain/package_manager/dnf.rb +17 -0
  35. data/lib/foreman_maintain/package_manager/yum.rb +126 -0
  36. data/lib/foreman_maintain/package_manager.rb +3 -0
  37. data/lib/foreman_maintain/reporter/cli_reporter.rb +1 -1
  38. data/lib/foreman_maintain/version.rb +1 -1
  39. data/lib/foreman_maintain.rb +1 -0
  40. metadata +16 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8e56d0ebde52242c236f12a7a5b1f6a5bff833f3
4
- data.tar.gz: b1edcdce8bef56a30d93e8e87b353c0da2823d0f
2
+ SHA256:
3
+ metadata.gz: 41f6663257db0cfdff24426812ca56a64a53105c6192b5abf5a2dba70e934fb5
4
+ data.tar.gz: a745621e9499e97d3c39e7d4d86f833b31c96e762d34d7a2def668e59cb555a8
5
5
  SHA512:
6
- metadata.gz: d30075189e4c304a615af0f9184aec70e6a904e7918d02720a5fddb7241d8abaab5b02221aeeeedd0638a5f3f9b973c2def96e3612d42185d97b0fca9e8f18d8
7
- data.tar.gz: 9a4793c2de2b9ee693109bd6bb16b5f89f4365b17e972651973b4eb9844535788a1c1c665eef52790e487aa4da794ee1bc04f1ab160e867f666bccb7dd40019b
6
+ metadata.gz: c78e8bfc7d0ef67cbaf4d79c319b37175b4148d2050625894ac9a3e5186795b08ffe7f696472f110f3260ebac0381dd3407df55ce2cb92704751d00c4bed40c2
7
+ data.tar.gz: 0bfaef53cbc4ccf91f1f841365bdbe0beb6256104f3e6c704f6e0b8554c6921d2b7e3cd5c4ce0e5c7c94d6fe71e6e51525a4d47c38d14f1ff8428045a8fd15ae
data/README.md CHANGED
@@ -120,6 +120,12 @@ export EXTERNAL_SAT_ORG='Sat6-CI'
120
120
  export EXTERNAL_SAT_ACTIVATION_KEY='Satellite QA RHEL7'
121
121
  ```
122
122
 
123
+ To use beta repositories during upgrade, set the following environment variable
124
+
125
+ ```
126
+ export FOREMAN_MAINTAIN_USE_BETA='1'
127
+ ```
128
+
123
129
  ## Implementation
124
130
 
125
131
  `foreman_maintain` maps the CLI commands into definitions. This allows to keep the set
@@ -437,7 +443,7 @@ Possible options for the `:completion` attribute are:
437
443
  * `maintenance-mode status` gives a brief output with On/Off message. This includes status of each step.
438
444
 
439
445
  * `maintenance-mode is-enabled` returns `0 or 1` output depending upon the maintenance-mode status.
440
- Here, 1=ON & 0=OFF.
446
+ Here, 0=ON & 1=OFF.
441
447
 
442
448
  If User would like to check whether maintenance-mode is ON/OFF on system in their external script then
443
449
  they can use subcommand `foreman-maintain maintenance-mode is-enabled`.
@@ -26,7 +26,11 @@ module Checks
26
26
  puts "\n"
27
27
  puts stats.stdout
28
28
 
29
- assert(success, io_obj.slow_disk_error_msg)
29
+ if feature(:downstream) && feature(:downstream).at_least_version?('6.3')
30
+ assert(success, io_obj.slow_disk_error_msg + warning_message, :warn => true)
31
+ else
32
+ assert(success, io_obj.slow_disk_error_msg)
33
+ end
30
34
  end
31
35
  end
32
36
 
@@ -38,11 +42,17 @@ module Checks
38
42
 
39
43
  def dirs_to_check
40
44
  return DEFAULT_DIRS.first(1) if check_only_single_device?
45
+
41
46
  DEFAULT_DIRS
42
47
  end
43
48
 
44
49
  private
45
50
 
51
+ def warning_message
52
+ "\nWARNING: Low disk speed might have a negative impact on the system."\
53
+ "\nSee https://access.redhat.com/solutions/3397771 before proceeding"
54
+ end
55
+
46
56
  def compute_disk_speed(spinner)
47
57
  success = true
48
58
  io_obj = ForemanMaintain::Utils::Disk::NilDevice.new
@@ -0,0 +1,14 @@
1
+ module Checks
2
+ class VersionLockingEnabled < ForemanMaintain::Check
3
+ metadata do
4
+ description 'Check if tooling for package version locking is installed'
5
+ end
6
+
7
+ def run
8
+ enabled = feature(:package_manager).version_locking_enabled?
9
+ enable_locking = Procedures::Packages::EnableVersionLocking.new(:assumeyes => assumeyes?)
10
+ assert(enabled, 'Tools for package version locking are not available on this system',
11
+ :next_steps => enable_locking)
12
+ end
13
+ end
14
+ end
@@ -7,7 +7,7 @@ class Features::CandlepinDatabase < ForemanMaintain::Feature
7
7
  label :candlepin_database
8
8
 
9
9
  confine do
10
- file_exists?(CANDLEPIN_DB_CONFIG)
10
+ file_nonzero?(CANDLEPIN_DB_CONFIG)
11
11
  end
12
12
  end
13
13
 
@@ -64,7 +64,9 @@ class Features::Downstream < ForemanMaintain::Feature
64
64
 
65
65
  rh_repos.concat(sat_and_tools_repos(rh_version_major, sat_version))
66
66
 
67
- rh_repos << 'rhel-7-server-ansible-2.6-rpms' if sat_version.to_s == '6.4'
67
+ if sat_version > version('6.3')
68
+ rh_repos << ansible_repo(sat_version, rh_version_major)
69
+ end
68
70
 
69
71
  if current_minor_version == '6.3' && sat_version.to_s != '6.4' && (
70
72
  feature(:puppet_server) && feature(:puppet_server).puppet_version.major == 4)
@@ -74,6 +76,14 @@ class Features::Downstream < ForemanMaintain::Feature
74
76
  rh_repos
75
77
  end
76
78
 
79
+ def ansible_repo(sat_version, rh_version_major)
80
+ if sat_version >= version('6.6')
81
+ "rhel-#{rh_version_major}-server-ansible-2.8-rpms"
82
+ elsif sat_version >= version('6.4')
83
+ "rhel-#{rh_version_major}-server-ansible-2.6-rpms"
84
+ end
85
+ end
86
+
77
87
  def sat_and_tools_repos(rh_version_major, sat_version)
78
88
  sat_version_full = "#{sat_version.major}.#{sat_version.minor}"
79
89
  sat_repo_id = "rhel-#{rh_version_major}-server-satellite-#{sat_version_full}-rpms"
@@ -81,7 +91,7 @@ class Features::Downstream < ForemanMaintain::Feature
81
91
  sat_maintenance_repo_id = "rhel-#{rh_version_major}-server-satellite-maintenance-6-rpms"
82
92
 
83
93
  # Override to use Beta repositories for sat version until GA
84
- if sat_version.to_s == '6.5'
94
+ if ENV['FOREMAN_MAINTAIN_USE_BETA'] == '1'
85
95
  sat_repo_id = "rhel-server-#{rh_version_major}-satellite-6-beta-rpms"
86
96
  sat_tools_repo_id = "rhel-#{rh_version_major}-server-satellite-tools-6-beta-rpms"
87
97
  sat_maintenance_repo_id = "rhel-#{rh_version_major}-server-satellite-maintenance-6-beta-rpms"
@@ -7,7 +7,7 @@ class Features::ForemanDatabase < ForemanMaintain::Feature
7
7
  label :foreman_database
8
8
 
9
9
  confine do
10
- file_exists?(FOREMAN_DB_CONFIG)
10
+ file_nonzero?(FOREMAN_DB_CONFIG)
11
11
  end
12
12
  end
13
13
 
@@ -0,0 +1,34 @@
1
+ class Features::PackageManager < ForemanMaintain::Feature
2
+ metadata do
3
+ label :package_manager
4
+ end
5
+
6
+ extend Forwardable
7
+ def_delegators :manager, :lock_versions, :unlock_versions,
8
+ :installed?, :find_installed_package, :install, :update,
9
+ :version_locking_enabled?, :configure_version_locking,
10
+ :foreman_related_packages, :version_locking_packages,
11
+ :versions_locked?, :clean_cache
12
+
13
+ def self.type
14
+ @type ||= %w[dnf yum apt].find { |manager| command_present?(manager) }
15
+ end
16
+
17
+ def type
18
+ self.class.type
19
+ end
20
+
21
+ def manager
22
+ @manager ||= case type
23
+ when 'dnf'
24
+ ForemanMaintain::PackageManager::Dnf.new
25
+ when 'yum'
26
+ ForemanMaintain::PackageManager::Yum.new
27
+ else
28
+ raise 'No supported package manager was found'
29
+ end
30
+ end
31
+
32
+ # TODO: DEB grep ^Package: /var/lib/apt/lists/deb.theforeman.org_dists_*
33
+ # TODO DEB apt-mark hold/unhold <package>
34
+ end
@@ -3,33 +3,34 @@ class Features::SyncPlans < ForemanMaintain::Feature
3
3
  label :sync_plans
4
4
  end
5
5
 
6
- def active_sync_plans_count
7
- feature(:foreman_database).query(
8
- <<-SQL
9
- SELECT count(*) AS count FROM katello_sync_plans WHERE enabled ='t'
10
- SQL
11
- ).first['count'].to_i
6
+ def required_new_implementation
7
+ @required_new_implementation ||=
8
+ feature(:foreman_database).query(
9
+ <<-SQL
10
+ SELECT COUNT(1) FROM information_schema.table_constraints
11
+ WHERE constraint_name='katello_sync_plan_foreman_tasks_recurring_logic_fk' AND table_name='katello_sync_plans'
12
+ SQL
13
+ ).first['count'].to_i > 0
12
14
  end
13
15
 
14
- def ids_by_status(enabled = true)
15
- enabled = enabled ? 't' : 'f'
16
- feature(:foreman_database).query(
17
- <<-SQL
18
- SELECT id FROM katello_sync_plans WHERE enabled ='#{enabled}'
19
- SQL
20
- ).map { |r| r['id'].to_i }
21
- end
16
+ def sync_plan_ids_by_status(enabled = true, filter_ids = nil)
17
+ if filter_ids
18
+ return [] if filter_ids.empty?
22
19
 
23
- def verify_existing_ids_by_status(ids, enabled = true)
24
- return [] if ids.empty?
20
+ ids_condition = filter_ids.map { |id| "'#{id}'" }.join(',')
21
+ end
25
22
 
26
- enabled = enabled ? 't' : 'f'
27
- ids_condition = ids.map { |id| "'#{id}'" }.join(',')
28
- feature(:foreman_database).query(
29
- <<-SQL
30
- SELECT id FROM katello_sync_plans WHERE enabled ='#{enabled}' AND id IN (#{ids_condition})
23
+ if required_new_implementation
24
+ query = <<-SQL
25
+ select sp.id as id from katello_sync_plans sp inner join foreman_tasks_recurring_logics rl on sp.foreman_tasks_recurring_logic_id = rl.id
26
+ where rl.state='#{enabled ? 'active' : 'disabled'}' #{ids_condition ? " AND sp.id IN (#{ids_condition})" : ''}
31
27
  SQL
32
- ).map { |r| r['id'].to_i }
28
+ else
29
+ query = <<-SQL
30
+ SELECT id FROM katello_sync_plans WHERE enabled ='#{enabled ? 't' : 'f'}' #{ids_condition ? " AND id IN (#{ids_condition})" : ''}
31
+ SQL
32
+ end
33
+ feature(:foreman_database).query(query).map { |r| r['id'].to_i }
33
34
  end
34
35
 
35
36
  def make_disable(ids)
@@ -69,7 +70,7 @@ class Features::SyncPlans < ForemanMaintain::Feature
69
70
  private
70
71
 
71
72
  def update_records(ids, enabled)
72
- ids_not_required_update = verify_existing_ids_by_status(ids, enabled)
73
+ ids_not_required_update = sync_plan_ids_by_status(enabled, ids)
73
74
  ids_required_update = ids - ids_not_required_update
74
75
  make_data_key_empty(enabled) if !ids_not_required_update.empty? && ids_required_update.empty?
75
76
  updated_record_ids = []
@@ -104,7 +105,7 @@ class Features::SyncPlans < ForemanMaintain::Feature
104
105
  else
105
106
  @data[:disabled] = [] unless @data[:disabled]
106
107
  @data[:enabled] = [] if @data[:disabled].empty?
107
- @data[:disabled].concat(new_ids)
108
+ @data[:disabled].concat(new_ids).uniq!
108
109
  end
109
110
  end
110
111
 
@@ -11,6 +11,8 @@ module Procedures::Backup
11
11
  param :backup_dir, 'Directory where to backup to', :required => true
12
12
  param :proxy_features, 'List of proxy features to backup (default: all)',
13
13
  :array => true, :default => ['all']
14
+ param :ignore_changed_files, 'Should packing tar ignore changed files',
15
+ :flag => true, :default => false
14
16
  end
15
17
 
16
18
  def run
@@ -18,9 +20,10 @@ module Procedures::Backup
18
20
  increments = File.join(@backup_dir, '.config.snar')
19
21
  with_spinner('Collecting config files to backup') do
20
22
  configs = config_files.join(' ')
23
+ statuses = @ignore_changed_files ? [0, 1] : [0]
21
24
  execute!("tar --selinux --create --gzip --file=#{tarball} " \
22
25
  "--listed-incremental=#{increments} --ignore-failed-read " \
23
- "#{configs}")
26
+ "#{configs}", :valid_exit_statuses => statuses)
24
27
  end
25
28
  end
26
29
 
@@ -9,8 +9,8 @@ module Procedures::MaintenanceMode
9
9
  attr_reader :status_code
10
10
 
11
11
  def run
12
- @status_code = feature(:iptables).maintenance_mode_chain_exist? ? 1 : 0
13
- puts "Maintenance mode is #{@status_code == 0 ? 'Off' : 'On'}"
12
+ @status_code = feature(:iptables).maintenance_mode_chain_exist? ? 0 : 1
13
+ puts "Maintenance mode is #{@status_code == 1 ? 'Off' : 'On'}"
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,17 @@
1
+ module Procedures::Packages
2
+ class EnableVersionLocking < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Install and configure tools for version locking'
5
+ param :assumeyes, 'Do not ask for confirmation'
6
+ end
7
+
8
+ def run
9
+ packages = feature(:package_manager).version_locking_packages
10
+ feature(:package_manager).install(packages, :assumeyes => @assumeyes)
11
+ unless feature(:package_manager).installed?(packages)
12
+ raise "Unable to install some of the required dependences: #{packages.join(' ')}"
13
+ end
14
+ feature(:package_manager).configure_version_locking
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Procedures::Packages
2
+ class LockVersions < ForemanMaintain::Procedure
3
+ metadata do
4
+ for_feature :package_manager
5
+ description 'Lock versions of Foreman-related packages'
6
+ preparation_steps { [Checks::VersionLockingEnabled.new] }
7
+ end
8
+
9
+ def run
10
+ with_spinner('Collecting list of packages to lock') do |spinner|
11
+ package_list = feature(:package_manager).foreman_related_packages
12
+ spinner.update('Locking packages')
13
+ feature(:package_manager).lock_versions(package_list)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Procedures::Packages
2
+ class LockingStatus < ForemanMaintain::Procedure
3
+ metadata do
4
+ for_feature :package_manager
5
+ description 'Check status of version locking of Foreman-related packages'
6
+ preparation_steps { [Checks::VersionLockingEnabled.new] }
7
+ end
8
+
9
+ def run
10
+ if feature(:package_manager).versions_locked?
11
+ puts 'Packages are locked.'
12
+ else
13
+ puts 'Packages are not locked.'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Procedures::Packages
2
+ class UnlockVersions < ForemanMaintain::Procedure
3
+ metadata do
4
+ for_feature :package_manager
5
+ description 'Unlock versions of Foreman-related packages'
6
+ preparation_steps { [Checks::VersionLockingEnabled.new] }
7
+ end
8
+
9
+ def run
10
+ feature(:package_manager).unlock_versions
11
+ end
12
+ end
13
+ end
@@ -7,7 +7,7 @@ module Procedures::Packages
7
7
 
8
8
  def run
9
9
  assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
10
- clean_all_packages
10
+ feature(:package_manager).clean_cache
11
11
  packages_action(:update, @packages, :assumeyes => assumeyes_val)
12
12
  end
13
13
 
@@ -21,7 +21,7 @@ module Procedures::SyncPlans
21
21
  default_storage = ForemanMaintain.storage(:default)
22
22
  feature(:sync_plans).load_from_storage(default_storage)
23
23
  with_spinner('disabling sync plans') do |spinner|
24
- ids = feature(:sync_plans).ids_by_status(true)
24
+ ids = feature(:sync_plans).sync_plan_ids_by_status(true)
25
25
  feature(:sync_plans).make_disable(ids)
26
26
  spinner.update "Total #{ids.length} sync plans are now disabled."
27
27
  end
@@ -19,7 +19,6 @@ module ForemanMaintain::Scenarios
19
19
  param :tar_volume_size, 'Size of tar volume (indicates splitting)'
20
20
  end
21
21
 
22
- # rubocop:disable Metrics/MethodLength
23
22
  def compose
24
23
  check_valid_startegy
25
24
  safety_confirmation
@@ -27,7 +26,6 @@ module ForemanMaintain::Scenarios
27
26
  prepare_directory
28
27
  logical_volume_confirmation
29
28
  add_step_with_context(Procedures::Backup::Metadata)
30
- add_step_with_context(Procedures::Backup::ConfigFiles)
31
29
 
32
30
  case strategy
33
31
  when :online
@@ -39,7 +37,6 @@ module ForemanMaintain::Scenarios
39
37
  end
40
38
  add_step_with_context(Procedures::Backup::CompressData)
41
39
  end
42
- # rubocop:enable Metrics/MethodLength
43
40
 
44
41
  # rubocop:disable Metrics/MethodLength
45
42
  def set_context_mapping
@@ -132,6 +129,7 @@ module ForemanMaintain::Scenarios
132
129
  add_steps_with_context(
133
130
  find_procedures(:maintenance_mode_on),
134
131
  Procedures::Service::Stop,
132
+ Procedures::Backup::ConfigFiles,
135
133
  Procedures::Backup::Pulp,
136
134
  Procedures::Backup::Offline::Mongo,
137
135
  Procedures::Backup::Offline::CandlepinDB,
@@ -162,6 +160,7 @@ module ForemanMaintain::Scenarios
162
160
  Procedures::Backup::Snapshot::PrepareMount,
163
161
  find_procedures(:maintenance_mode_on),
164
162
  Procedures::Service::Stop,
163
+ Procedures::Backup::ConfigFiles,
165
164
  Procedures::Backup::Snapshot::MountMongo,
166
165
  Procedures::Backup::Snapshot::MountPulp,
167
166
  Procedures::Backup::Snapshot::MountCandlepinDB,
@@ -184,6 +183,7 @@ module ForemanMaintain::Scenarios
184
183
  # rubocop:enable Metrics/MethodLength
185
184
 
186
185
  def add_online_backup_steps
186
+ add_step_with_context(Procedures::Backup::ConfigFiles, :ignore_changed_files => true)
187
187
  add_step_with_context(Procedures::Backup::Pulp, :ensure_unchanged => true)
188
188
  add_steps_with_context(
189
189
  Procedures::Backup::Online::Mongo,
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_2
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.2'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_2_z
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.2'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -46,6 +46,7 @@ module Scenarios::Satellite_6_3
46
46
 
47
47
  def compose
48
48
  add_step(Procedures::Repositories::Setup.new(:version => '6.3'))
49
+ add_step(Procedures::Packages::UnlockVersions.new)
49
50
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
50
51
  add_step(Procedures::Installer::Upgrade.new)
51
52
  end
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_3_z
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.3'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -46,6 +46,7 @@ module Scenarios::Satellite_6_4
46
46
 
47
47
  def compose
48
48
  add_step(Procedures::Repositories::Setup.new(:version => '6.4'))
49
+ add_step(Procedures::Packages::UnlockVersions.new)
49
50
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
50
51
  add_step(Procedures::Installer::Upgrade.new)
51
52
  end
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_4_z
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.4'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_5
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.5'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -45,6 +45,7 @@ module Scenarios::Satellite_6_5_z
45
45
 
46
46
  def compose
47
47
  add_step(Procedures::Repositories::Setup.new(:version => '6.5'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
48
49
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
49
50
  add_step(Procedures::Installer::Upgrade.new)
50
51
  end
@@ -0,0 +1,80 @@
1
+ module Scenarios::Satellite_6_6
2
+ class Abstract < ForemanMaintain::Scenario
3
+ def self.upgrade_metadata(&block)
4
+ metadata do
5
+ tags :upgrade_to_satellite_6_6
6
+ confine do
7
+ feature(:downstream) && feature(:downstream).current_minor_version == '6.5'
8
+ end
9
+ instance_eval(&block)
10
+ end
11
+ end
12
+ end
13
+
14
+ class PreUpgradeCheck < Abstract
15
+ upgrade_metadata do
16
+ description 'Checks before upgrading to Satellite 6.6'
17
+ tags :pre_upgrade_checks
18
+ run_strategy :fail_slow
19
+ end
20
+
21
+ def compose
22
+ add_steps(find_checks(:default))
23
+ add_steps(find_checks(:pre_upgrade))
24
+ add_step(Checks::Repositories::Validate.new(:version => '6.6'))
25
+ end
26
+ end
27
+
28
+ class PreMigrations < Abstract
29
+ upgrade_metadata do
30
+ description 'Procedures before migrating to Satellite 6.6'
31
+ tags :pre_migrations
32
+ end
33
+
34
+ def compose
35
+ add_steps(find_procedures(:pre_migrations))
36
+ add_step(Procedures::Service::Stop.new)
37
+ end
38
+ end
39
+
40
+ class Migrations < Abstract
41
+ upgrade_metadata do
42
+ description 'Migration scripts to Satellite 6.6'
43
+ tags :migrations
44
+ end
45
+
46
+ def compose
47
+ add_step(Procedures::Repositories::Setup.new(:version => '6.6'))
48
+ add_step(Procedures::Packages::UnlockVersions.new)
49
+ add_step(Procedures::Packages::Update.new(:assumeyes => true))
50
+ add_step(Procedures::Installer::Upgrade.new)
51
+ end
52
+ end
53
+
54
+ class PostMigrations < Abstract
55
+ upgrade_metadata do
56
+ description 'Procedures after migrating to Satellite 6.6'
57
+ tags :post_migrations
58
+ end
59
+
60
+ def compose
61
+ add_step(Procedures::Service::Start.new)
62
+ add_steps(find_procedures(:post_migrations))
63
+ end
64
+ end
65
+
66
+ class PostUpgradeChecks < Abstract
67
+ upgrade_metadata do
68
+ description 'Checks after upgrading to Satellite 6.6'
69
+ tags :post_upgrade_checks
70
+ run_strategy :fail_slow
71
+ end
72
+
73
+ def compose
74
+ add_steps(find_checks(:default))
75
+ add_steps(find_checks(:post_upgrade))
76
+ end
77
+ end
78
+ end
79
+
80
+ ForemanMaintain::UpgradeRunner.register_version('6.6', :upgrade_to_satellite_6_6)
@@ -0,0 +1,39 @@
1
+ module ForemanMaintain::Scenarios
2
+ module VersionLocking
3
+ class Status < ForemanMaintain::Scenario
4
+ metadata do
5
+ label :version_locking_status
6
+ description 'detection of status of package version locking'
7
+ manual_detection
8
+ end
9
+
10
+ def compose
11
+ add_step(Procedures::Packages::LockingStatus)
12
+ end
13
+ end
14
+
15
+ class Unlock < ForemanMaintain::Scenario
16
+ metadata do
17
+ label :version_locking_unlock
18
+ description 'unlocking of package versions'
19
+ manual_detection
20
+ end
21
+
22
+ def compose
23
+ add_step(Procedures::Packages::UnlockVersions)
24
+ end
25
+ end
26
+
27
+ class Lock < ForemanMaintain::Scenario
28
+ metadata do
29
+ label :version_locking_lock
30
+ description 'locking of package versions'
31
+ manual_detection
32
+ end
33
+
34
+ def compose
35
+ add_step(Procedures::Packages::LockVersions)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -64,6 +64,11 @@ module ForemanMaintain
64
64
  runner.run
65
65
  end
66
66
 
67
+ def run_scenarios_and_exit(scenarios, rescue_scenario: nil)
68
+ run_scenario(scenarios, rescue_scenario)
69
+ exit runner.exit_code
70
+ end
71
+
67
72
  def available_checks
68
73
  filter = {}
69
74
  filter[:tags] = tags if respond_to?(:tags)
@@ -0,0 +1,36 @@
1
+ module ForemanMaintain
2
+ module Cli
3
+ class PackagesCommand < Base
4
+ subcommand 'lock', 'Prevent Foreman-related packages from automatic update' do
5
+ interactive_option
6
+ def execute
7
+ run_scenarios_and_exit(Scenarios::VersionLocking::Lock.new)
8
+ end
9
+ end
10
+
11
+ subcommand 'unlock', 'Enable Foreman-related packages for automatic update' do
12
+ interactive_option
13
+ def execute
14
+ run_scenarios_and_exit(Scenarios::VersionLocking::Unlock.new)
15
+ end
16
+ end
17
+
18
+ subcommand 'status', 'Check if Foreman-related packages are protected against update' do
19
+ interactive_option
20
+ def execute
21
+ run_scenarios_and_exit(Scenarios::VersionLocking::Status.new)
22
+ end
23
+ end
24
+
25
+ subcommand 'is-locked', 'Check if update of Foreman-related packages is allowed' do
26
+ interactive_option
27
+ def execute
28
+ locked = feature(:package_manager).versions_locked?
29
+ puts "Foreman related packages are#{locked ? '' : ' not'} locked"
30
+ exit_code = locked ? 0 : 1
31
+ exit exit_code
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -9,6 +9,7 @@ require 'foreman_maintain/cli/advanced_command'
9
9
  require 'foreman_maintain/cli/service_command'
10
10
  require 'foreman_maintain/cli/restore_command'
11
11
  require 'foreman_maintain/cli/maintenance_mode_command'
12
+ require 'foreman_maintain/cli/packages_command'
12
13
 
13
14
  module ForemanMaintain
14
15
  module Cli
@@ -20,6 +21,7 @@ module ForemanMaintain
20
21
  subcommand 'service', 'Control applicable services', ServiceCommand
21
22
  subcommand 'backup', 'Backup server', BackupCommand
22
23
  subcommand 'restore', 'Restore a backup', RestoreCommand
24
+ subcommand 'packages', 'Lock/Unlock installed packages', PackagesCommand
23
25
  subcommand 'advanced', 'Advanced tools for server maintenance', AdvancedCommand
24
26
  subcommand 'maintenance-mode', 'Control maintenance-mode for application',
25
27
  MaintenanceModeCommand
@@ -54,6 +54,10 @@ module ForemanMaintain
54
54
  $CHILD_STATUS.success?
55
55
  end
56
56
 
57
+ def command_present?(command_name)
58
+ execute?("command -v #{command_name}")
59
+ end
60
+
57
61
  def execute!(command, options = {})
58
62
  command_runner = Utils::CommandRunner.new(logger, command, options)
59
63
  execution.puts '' if command_runner.interactive? && respond_to?(:execution)
@@ -81,11 +85,12 @@ module ForemanMaintain
81
85
  File.exist?(filename)
82
86
  end
83
87
 
88
+ def file_nonzero?(filename)
89
+ File.exist?(filename) && !File.zero?(filename)
90
+ end
91
+
84
92
  def find_package(name)
85
- result = execute(%(rpm -q '#{name}'))
86
- if $CHILD_STATUS.success?
87
- result
88
- end
93
+ feature(:package_manager).find_installed_package(name)
89
94
  end
90
95
 
91
96
  def hostname
@@ -101,20 +106,15 @@ module ForemanMaintain
101
106
  end
102
107
 
103
108
  def packages_action(action, packages, options = {})
104
- expected_actions = [:install, :update]
105
- unless expected_actions.include?(action)
109
+ options.validate_options!(:assumeyes)
110
+ case action
111
+ when :install
112
+ feature(:package_manager).install(packages, :assumeyes => options[:assumeyes])
113
+ when :update
114
+ feature(:package_manager).update(packages, :assumeyes => options[:assumeyes])
115
+ else
106
116
  raise ArgumentError, "Unexpected action #{action} expected #{expected_actions.inspect}"
107
117
  end
108
- options.validate_options!(:assumeyes)
109
- yum_options = []
110
- yum_options << '-y' if options[:assumeyes]
111
- execute!("yum #{yum_options.join(' ')} #{action} #{packages.join(' ')}",
112
- :interactive => true)
113
- end
114
-
115
- def clean_all_packages
116
- execute!('dnf clean all') if find_package('dnf')
117
- execute!('yum clean all') if find_package('yum')
118
118
  end
119
119
 
120
120
  def package_version(name)
@@ -0,0 +1,71 @@
1
+ module ForemanMaintain::PackageManager
2
+ # rubocop:disable Lint/UnusedMethodArgument
3
+ class Base
4
+ def foreman_related_packages
5
+ raise NotImplementedError
6
+ end
7
+
8
+ # list of packages providing the version locking
9
+ def version_locking_packages
10
+ raise NotImplementedError
11
+ end
12
+
13
+ # check tools are installed and enabled
14
+ def version_locking_enabled?
15
+ raise NotImplementedError
16
+ end
17
+
18
+ # make sure the version locking tools are configured
19
+ # we can assume it is already installed
20
+ def configure_version_locking
21
+ raise NotImplementedError
22
+ end
23
+
24
+ # are the packages installed on the system?
25
+ def installed?(packages)
26
+ raise NotImplementedError
27
+ end
28
+
29
+ # find installed package and return full nvra or nil
30
+ def find_installed_package(name)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ # install package
35
+ def install(packages, assumeyes: false)
36
+ raise NotImplementedError
37
+ end
38
+
39
+ # update package
40
+ def update(packages = [], assumeyes: false)
41
+ raise NotImplementedError
42
+ end
43
+
44
+ # prevent listed packages from update
45
+ def lock_versions(package_list)
46
+ raise NotImplementedError
47
+ end
48
+
49
+ # allow all packages we previously locked to update
50
+ def unlock_versions
51
+ raise NotImplementedError
52
+ end
53
+
54
+ # check if packages are locked
55
+ def versions_locked?
56
+ raise NotImplementedError
57
+ end
58
+
59
+ # clean the package manager cache
60
+ def clean_cache
61
+ raise NotImplementedError
62
+ end
63
+
64
+ private
65
+
66
+ def sys
67
+ ForemanMaintain::Utils::SystemHelpers
68
+ end
69
+ end
70
+ # rubocop:enable Lint/UnusedMethodArgument
71
+ end
@@ -0,0 +1,17 @@
1
+ module ForemanMaintain::PackageManager
2
+ class Dnf < Yum
3
+ def clean_cache
4
+ dnf_action('clean', 'all')
5
+ super
6
+ end
7
+
8
+ private
9
+
10
+ def dnf_action(action, packages, assumeyes: false)
11
+ yum_options = []
12
+ yum_options << '-y' if assumeyes
13
+ sys.execute!("dnf #{yum_options.join(' ')} #{action} #{packages.join(' ')}",
14
+ :interactive => true)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,126 @@
1
+ module ForemanMaintain::PackageManager
2
+ class Yum < Base
3
+ VERSIONLOCK_START_CLAUSE = '## foreman-maintain - start'.freeze
4
+ VERSIONLOCK_END_CLAUSE = '## foreman-maintain - end'.freeze
5
+ VERSIONLOCK_CONFIG_FILE = '/etc/yum/pluginconf.d/versionlock.conf'.freeze
6
+ VERSIONLOCK_DEFAULT_LIST_FILE = '/etc/yum/pluginconf.d/versionlock.list'.freeze
7
+
8
+ def self.parse_envra(envra)
9
+ # envra format: 0:foreman-1.20.1.10-1.el7sat.noarch
10
+ parsed = envra.match(/\d*:?(?<name>.*)-[^-]+-[^-]+\.[^.]+/)
11
+ parsed ? Hash[parsed.names.zip(parsed.captures)].merge(:envra => envra) : nil
12
+ end
13
+
14
+ def foreman_related_packages
15
+ query = "repoquery -a --qf='%{envra} %{repo.id}' --search foreman-installer |head -n1"
16
+ foreman_repo = sys.execute(query).split[1]
17
+ query_installed = "repoquery -a --qf='%{envra}' --repoid='#{foreman_repo}'"
18
+ sys.execute(query_installed). split("\n").map do |pkg|
19
+ self.class.parse_envra(pkg)
20
+ end
21
+ end
22
+
23
+ def version_locking_packages
24
+ %w[yum-utils yum-plugin-versionlock]
25
+ end
26
+
27
+ def lock_versions(package_list)
28
+ unlock_versions
29
+ File.open(versionlock_file, 'a') do |f|
30
+ f.puts VERSIONLOCK_START_CLAUSE
31
+ f.puts '# The following packages are locked by foreman-maintain. Do not modify!'
32
+ package_list.each { |package| f.puts "#{package[:envra]}.*" }
33
+ f.puts '# End of list of packages locked by foreman-maintain'
34
+ f.puts VERSIONLOCK_END_CLAUSE
35
+ end
36
+ end
37
+
38
+ def unlock_versions
39
+ lock_file = versionlock_file
40
+ content = File.read(lock_file)
41
+ content = content.gsub(/#{VERSIONLOCK_START_CLAUSE}.*#{VERSIONLOCK_END_CLAUSE}\n/m, '')
42
+ File.open(lock_file, 'w') { |f| f.write content }
43
+ end
44
+
45
+ def versions_locked?
46
+ lock_file = versionlock_file
47
+ return false if lock_file.nil?
48
+ content = File.read(lock_file)
49
+ !!content.match(/#{VERSIONLOCK_START_CLAUSE}.*#{VERSIONLOCK_END_CLAUSE}\n/m)
50
+ end
51
+
52
+ def version_locking_enabled?
53
+ installed?(version_locking_packages) && versionlock_config =~ /^\s*enabled\s+=\s+1/ \
54
+ && File.exist?(versionlock_file)
55
+ end
56
+
57
+ # make sure the version locking tools are configured
58
+ # enabled = 1
59
+ # locklist = <list file>
60
+ # we can assume it is already installed
61
+ def configure_version_locking
62
+ config = versionlock_config
63
+ config += "\n" unless config[-1] == "\n"
64
+ enabled_re = /^\s*enabled\s*=.*$/
65
+ if enabled_re.match(config)
66
+ config = config.gsub(enabled_re, 'enabled = 1')
67
+ else
68
+ config += "enabled = 1\n"
69
+ end
70
+ unless config =~ /^\s*locklist\s*=.*$/
71
+ config += "locklist = #{VERSIONLOCK_DEFAULT_LIST_FILE}\n"
72
+ end
73
+ File.open(versionlock_config_file, 'w') { |file| file.puts config }
74
+ FileUtils.touch(versionlock_file)
75
+ end
76
+
77
+ def installed?(packages)
78
+ packages_list = [packages].flatten(1).map { |pkg| "'#{pkg}'" }.join(' ')
79
+ sys.execute?(%(rpm -q #{packages_list}))
80
+ end
81
+
82
+ def find_installed_package(name)
83
+ status, result = sys.execute_with_status(%(rpm -q '#{name}'))
84
+ if status == 0
85
+ result
86
+ end
87
+ end
88
+
89
+ def install(packages, assumeyes: false)
90
+ yum_action('install', packages, :assumeyes => assumeyes)
91
+ end
92
+
93
+ def update(packages = [], assumeyes: false)
94
+ yum_action('update', packages, :assumeyes => assumeyes)
95
+ end
96
+
97
+ def clean_cache
98
+ yum_action('clean', 'all')
99
+ end
100
+
101
+ private
102
+
103
+ def versionlock_config
104
+ File.exist?(versionlock_config_file) ? File.read(versionlock_config_file) : ''
105
+ end
106
+
107
+ def versionlock_config_file
108
+ VERSIONLOCK_CONFIG_FILE
109
+ end
110
+
111
+ def versionlock_file
112
+ result = versionlock_config.match(/^\s*locklist\s*=\s*(\S+)/)
113
+ result.nil? ? nil : File.expand_path(result.captures[0])
114
+ end
115
+
116
+ def yum_action(action, packages, assumeyes: false)
117
+ yum_options = []
118
+ packages = [packages].flatten(1)
119
+ yum_options << '-y' if assumeyes
120
+ yum_options_s = yum_options.empty? ? '' : ' ' + yum_options.join(' ')
121
+ packages_s = packages.empty? ? '' : ' ' + packages.join(' ')
122
+ sys.execute!("yum#{yum_options_s} #{action}#{packages_s}",
123
+ :interactive => true)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,3 @@
1
+ require 'foreman_maintain/package_manager/base'
2
+ require 'foreman_maintain/package_manager/yum'
3
+ require 'foreman_maintain/package_manager/dnf'
@@ -317,7 +317,7 @@ module ForemanMaintain
317
317
 
318
318
  recommend << <<-MESSAGE.strip_heredoc
319
319
  The steps in warning state itself might not mean there is an error,
320
- but it should be reviews to ensure the behavior is expected
320
+ but it should be reviewed to ensure the behavior is expected
321
321
  MESSAGE
322
322
  end
323
323
  puts((message + recommend).join("\n"))
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '0.4.1'.freeze
2
+ VERSION = '0.4.2'.freeze
3
3
  end
@@ -37,6 +37,7 @@ module ForemanMaintain
37
37
  require 'foreman_maintain/reporter'
38
38
  require 'foreman_maintain/utils'
39
39
  require 'foreman_maintain/error'
40
+ require 'foreman_maintain/package_manager'
40
41
 
41
42
  class << self
42
43
  attr_accessor :config, :logger
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: 0.4.1
4
+ version: 0.4.2
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: 2019-02-28 00:00:00.000000000 Z
11
+ date: 2019-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -151,6 +151,7 @@ files:
151
151
  - definitions/checks/root_user.rb
152
152
  - definitions/checks/services_up.rb
153
153
  - definitions/checks/system_registration.rb
154
+ - definitions/checks/version_locking_enabled.rb
154
155
  - definitions/features/candlepin.rb
155
156
  - definitions/features/candlepin_database.rb
156
157
  - definitions/features/cron.rb
@@ -169,6 +170,7 @@ files:
169
170
  - definitions/features/iptables.rb
170
171
  - definitions/features/katello.rb
171
172
  - definitions/features/mongo.rb
173
+ - definitions/features/package_manager.rb
172
174
  - definitions/features/pulp.rb
173
175
  - definitions/features/puppet_server.rb
174
176
  - definitions/features/service.rb
@@ -214,7 +216,11 @@ files:
214
216
  - definitions/procedures/iptables/remove_maintenance_mode_chain.rb
215
217
  - definitions/procedures/knowledge_base_article.rb
216
218
  - definitions/procedures/maintenance_mode/is_enabled.rb
219
+ - definitions/procedures/packages/enable_version_locking.rb
217
220
  - definitions/procedures/packages/install.rb
221
+ - definitions/procedures/packages/lock_versions.rb
222
+ - definitions/procedures/packages/locking_status.rb
223
+ - definitions/procedures/packages/unlock_versions.rb
218
224
  - definitions/procedures/packages/update.rb
219
225
  - definitions/procedures/passenger_recycler.rb
220
226
  - definitions/procedures/pulp/migrate.rb
@@ -257,6 +263,8 @@ files:
257
263
  - definitions/scenarios/upgrade_to_satellite_6_4_z.rb
258
264
  - definitions/scenarios/upgrade_to_satellite_6_5.rb
259
265
  - definitions/scenarios/upgrade_to_satellite_6_5_z.rb
266
+ - definitions/scenarios/upgrade_to_satellite_6_6.rb
267
+ - definitions/scenarios/version_locking.rb
260
268
  - lib/foreman_maintain.rb
261
269
  - lib/foreman_maintain/check.rb
262
270
  - lib/foreman_maintain/cli.rb
@@ -271,6 +279,7 @@ files:
271
279
  - lib/foreman_maintain/cli/base.rb
272
280
  - lib/foreman_maintain/cli/health_command.rb
273
281
  - lib/foreman_maintain/cli/maintenance_mode_command.rb
282
+ - lib/foreman_maintain/cli/packages_command.rb
274
283
  - lib/foreman_maintain/cli/restore_command.rb
275
284
  - lib/foreman_maintain/cli/service_command.rb
276
285
  - lib/foreman_maintain/cli/transform_clamp_options.rb
@@ -294,6 +303,10 @@ files:
294
303
  - lib/foreman_maintain/error.rb
295
304
  - lib/foreman_maintain/executable.rb
296
305
  - lib/foreman_maintain/feature.rb
306
+ - lib/foreman_maintain/package_manager.rb
307
+ - lib/foreman_maintain/package_manager/base.rb
308
+ - lib/foreman_maintain/package_manager/dnf.rb
309
+ - lib/foreman_maintain/package_manager/yum.rb
297
310
  - lib/foreman_maintain/param.rb
298
311
  - lib/foreman_maintain/procedure.rb
299
312
  - lib/foreman_maintain/reporter.rb
@@ -344,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
344
357
  version: '0'
345
358
  requirements: []
346
359
  rubyforge_project:
347
- rubygems_version: 2.6.14.1
360
+ rubygems_version: 2.7.9
348
361
  signing_key:
349
362
  specification_version: 4
350
363
  summary: Foreman maintenance tool belt