foreman_maintain 1.4.0 → 1.4.1

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/definitions/checks/check_hotfix_installed.rb +2 -3
  4. data/definitions/checks/disk/performance.rb +1 -2
  5. data/definitions/checks/package_manager/{yum/validate_yum_config.rb → dnf/validate_dnf_config.rb} +13 -11
  6. data/definitions/checks/repositories/check_upstream_repository.rb +1 -2
  7. data/definitions/features/installer.rb +8 -66
  8. data/definitions/features/instance.rb +0 -6
  9. data/definitions/procedures/backup/metadata.rb +5 -3
  10. data/definitions/procedures/packages/installer_confirmation.rb +1 -1
  11. data/definitions/procedures/packages/update.rb +3 -3
  12. data/definitions/scenarios/backup.rb +1 -6
  13. data/definitions/scenarios/self_upgrade.rb +4 -6
  14. data/definitions/scenarios/upgrade_to_capsule_6_15.rb +1 -2
  15. data/definitions/scenarios/upgrade_to_capsule_6_15_z.rb +1 -2
  16. data/definitions/scenarios/upgrade_to_katello_nightly.rb +1 -1
  17. data/definitions/scenarios/upgrade_to_satellite_6_15.rb +1 -2
  18. data/definitions/scenarios/upgrade_to_satellite_6_15_z.rb +1 -2
  19. data/extras/foreman_protector/foreman-protector.conf +1 -1
  20. data/lib/foreman_maintain/concerns/base_database.rb +0 -41
  21. data/lib/foreman_maintain/concerns/system_helpers.rb +2 -2
  22. data/lib/foreman_maintain/config.rb +5 -1
  23. data/lib/foreman_maintain/package_manager/dnf.rb +138 -11
  24. data/lib/foreman_maintain/package_manager.rb +0 -1
  25. data/lib/foreman_maintain/repository_manager/el.rb +2 -2
  26. data/lib/foreman_maintain/version.rb +1 -1
  27. metadata +3 -12
  28. data/definitions/checks/backup/directory_ready.rb +0 -23
  29. data/definitions/checks/foreman/check_checkpoint_segments.rb +0 -59
  30. data/definitions/checks/foreman/check_duplicate_roles.rb +0 -42
  31. data/definitions/checks/foreman/puppet_class_duplicates.rb +0 -48
  32. data/definitions/checks/original_assets.rb +0 -23
  33. data/definitions/procedures/foreman/apipie_cache.rb +0 -12
  34. data/definitions/procedures/foreman_docker/remove_foreman_docker.rb +0 -16
  35. data/extras/foreman_protector/yum/foreman-protector.py +0 -86
  36. data/lib/foreman_maintain/package_manager/yum.rb +0 -142
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8e76b84acb5103032daf0a4207f4c53a7d425fffe2fbfce49273200e3f5a732
4
- data.tar.gz: a91160e10024846b1b931515e55c6461aba0c2c3b5209a966fb9c43685b3eea5
3
+ metadata.gz: a742f6c45bf5c57c814ba78f83ff3fb72863de35005f0e8f34a6f823de766ba5
4
+ data.tar.gz: be8eb54fe3eb4d9a05d59f64ad34fc314ae97fc4be47c1aeaf4cde3b0d46b979
5
5
  SHA512:
6
- metadata.gz: 005d201ea441c1e1ecdd51838f76f9157357a332cb025ba6ea9fe835bff604d601b259ca374d8cf32118ab12203bea2dfc490d959127dee1f92768a684fb0e0f
7
- data.tar.gz: f51b31aa841554becdf0e3904c1a9d5259bd0d7691a83240b99f731320335ad20ee5428fc5c02267bf41ec50bd4f0e87bce2e7fcb9cec0f068ea4c03b04e1cac
6
+ metadata.gz: 4cb48844ead00af99f66d37ee2a215fe9c397f14b544774580ad5df3dc09598231f5a8a7978fbc2111bb104daa951f1d3c6a1dc2426c2f635e319ded93117e6f
7
+ data.tar.gz: 7c0cea08c66ea928e2fa6659dd051d55c4ab0e9afabba61c18ad9934b1a21fd1b177d7f765e58a2885927103daf92ba8d05513d2fc0f386ec2900e546afa3cbc
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Foreman Maintain [![Build Status](https://github.com/theforeman/foreman_maintain/workflows/Ruby%20Tests/badge.svg?event=pull_request)](https://github.com/theforeman/foreman_maintain/workflows/Ruby%20Tests/badge.svg?event=pull_request) <a href="https://codeclimate.com/github/theforeman/foreman_maintain"><img src="https://codeclimate.com/github/theforeman/foreman_maintain/badges/gpa.svg" /></a>
1
+ # Foreman Maintain [![Ruby Tests](https://github.com/theforeman/foreman_maintain/actions/workflows/ruby_tests.yml/badge.svg)](https://github.com/theforeman/foreman_maintain/actions/workflows/ruby_tests.yml) <a href="https://codeclimate.com/github/theforeman/foreman_maintain"><img src="https://codeclimate.com/github/theforeman/foreman_maintain/badges/gpa.svg" /></a>
2
2
 
3
3
  The `foreman_maintain` aims to provide various features that helps keep the
4
4
  Foreman/Satellite up and running. It supports multiple versions and subparts
@@ -4,8 +4,7 @@ class Checks::CheckHotfixInstalled < ForemanMaintain::Check
4
4
  description 'Check to verify if any hotfix installed on system'
5
5
  tags :pre_upgrade
6
6
  preparation_steps do
7
- [Checks::Repositories::CheckNonRhRepository.new,
8
- Procedures::Packages::Install.new(:packages => %w[yum-utils])]
7
+ [Checks::Repositories::CheckNonRhRepository.new]
9
8
  end
10
9
 
11
10
  confine do
@@ -45,7 +44,7 @@ class Checks::CheckHotfixInstalled < ForemanMaintain::Check
45
44
 
46
45
  def installed_packages
47
46
  packages = []
48
- IO.popen(['repoquery', '-a', '--installed', '--qf', query_format]) do |io|
47
+ IO.popen(['dnf', 'repoquery', '-a', '--installed', '--qf', query_format]) do |io|
49
48
  io.each do |line|
50
49
  repo, pkg = line.chomp.split
51
50
  next if repo.nil? || pkg.nil?
@@ -30,8 +30,7 @@ module Checks
30
30
  puts "\n"
31
31
  puts stats.stdout
32
32
 
33
- current_downstream_feature = feature(:instance).downstream
34
- if current_downstream_feature&.at_least_version?('6.3')
33
+ if feature(:instance).downstream
35
34
  assert(success, io_obj.slow_disk_error_msg + warning_message, :warn => true)
36
35
  else
37
36
  assert(success, io_obj.slow_disk_error_msg)
@@ -1,9 +1,9 @@
1
1
  module Checks::PackageManager
2
- module Yum
3
- class ValidateYumConfig < ForemanMaintain::Check
2
+ module Dnf
3
+ class ValidateDnfConfig < ForemanMaintain::Check
4
4
  metadata do
5
- label :validate_yum_config
6
- description 'Check to validate yum configuration before upgrade'
5
+ label :validate_dnf_config
6
+ description 'Check to validate dnf configuration before upgrade'
7
7
  tags :pre_upgrade
8
8
  end
9
9
 
@@ -17,30 +17,32 @@ module Checks::PackageManager
17
17
 
18
18
  private
19
19
 
20
+ # rubocop:disable Metrics/LineLength
20
21
  def failure_message(final_result)
21
22
  verb_string = final_result[:matched_keys].length > 1 ? 'are' : 'is'
22
23
 
23
- "#{final_result[:matched_keys].join(',')} #{verb_string} set in /etc/yum.conf as below:"\
24
+ "#{final_result[:matched_keys].join(',')} #{verb_string} set in /etc/dnf/dnf.conf as below:"\
24
25
  "\n#{final_result[:grep_output]}"\
25
- "\nUnset this configuration as it is risky while yum update or upgrade!"
26
+ "\nUnset this configuration as it is risky while dnf update or upgrade!"
26
27
  end
28
+ # rubocop:enable Metrics/LineLength
27
29
 
28
30
  def verify_config_options
29
31
  result = {}
30
- combined_regex = yum_config_options.values.join('|')
32
+ combined_regex = dnf_config_options.values.join('|')
31
33
  result[:grep_output] = execute_grep_cmd(combined_regex)
32
- result[:matched_keys] = yum_config_options.keys.select do |key|
34
+ result[:matched_keys] = dnf_config_options.keys.select do |key|
33
35
  result[:grep_output].include?(key)
34
36
  end
35
37
  result
36
38
  end
37
39
 
38
40
  def execute_grep_cmd(regex_string)
39
- execute_with_status("grep -iE '#{regex_string}' /etc/yum.conf")[1]
41
+ execute_with_status("grep -iE '#{regex_string}' /etc/dnf/dnf.conf")[1]
40
42
  end
41
43
 
42
- def yum_config_options
43
- @yum_config_options ||= {
44
+ def dnf_config_options
45
+ @dnf_config_options ||= {
44
46
  'exclude' => '^exclude\s*=\s*\S+.*$',
45
47
  }
46
48
  end
@@ -6,8 +6,7 @@ class Checks::CheckUpstreamRepository < ForemanMaintain::Check
6
6
  description 'Check if any upstream repositories are enabled on system'
7
7
  tags :pre_upgrade
8
8
  preparation_steps do
9
- [Checks::Repositories::CheckNonRhRepository.new,
10
- Procedures::Packages::Install.new(:packages => %w[yum-utils])]
9
+ [Checks::Repositories::CheckNonRhRepository.new]
11
10
  end
12
11
  confine do
13
12
  feature(:instance).downstream
@@ -3,22 +3,10 @@ class Features::Installer < ForemanMaintain::Feature
3
3
  label :installer
4
4
 
5
5
  confine do
6
- find_package('foreman-installer') ||
7
- find_package('katello-installer') ||
8
- find_package('capsule-installer')
6
+ find_package('foreman-installer')
9
7
  end
10
8
  end
11
9
 
12
- def initialize
13
- @installer_type = if find_package('foreman-installer')
14
- :scenarios
15
- elsif find_package('katello-installer')
16
- :legacy_katello
17
- elsif find_package('capsule-installer')
18
- :legacy_capsule
19
- end
20
- end
21
-
22
10
  def answers
23
11
  load_answers(configuration)
24
12
  end
@@ -28,39 +16,17 @@ class Features::Installer < ForemanMaintain::Feature
28
16
  end
29
17
 
30
18
  def config_file
31
- case @installer_type
32
- when :scenarios
33
- last_scenario_config
34
- when :legacy_katello
35
- File.join(config_directory, 'katello-installer.yaml')
36
- when :legacy_capsule
37
- File.join(config_directory, 'capsule-installer.yaml')
38
- end
39
- end
40
-
41
- def with_scenarios?
42
- @installer_type == :scenarios
19
+ last_scenario_config
43
20
  end
44
21
 
45
22
  def config_directory
46
- case @installer_type
47
- when :scenarios
48
- '/etc/foreman-installer'
49
- when :legacy_katello
50
- '/etc/katello-installer'
51
- when :legacy_capsule
52
- '/etc/capsule-installer'
53
- end
23
+ '/etc/foreman-installer'
54
24
  end
55
25
 
56
26
  def custom_hiera_file
57
27
  @custom_hiera_file ||= File.join(config_directory, 'custom-hiera.yaml')
58
28
  end
59
29
 
60
- def can_upgrade?
61
- @installer_type == :scenarios || @installer_type == :legacy_katello
62
- end
63
-
64
30
  def config_files
65
31
  Dir.glob(File.join(config_directory, '**/*')) +
66
32
  [
@@ -71,23 +37,14 @@ class Features::Installer < ForemanMaintain::Feature
71
37
  end
72
38
 
73
39
  def last_scenario
74
- return nil unless with_scenarios?
75
-
76
40
  File.basename(last_scenario_config).split('.')[0]
77
41
  end
78
42
 
79
43
  def installer_command
80
- case @installer_type
81
- when :scenarios
82
- if feature(:satellite)
83
- 'satellite-installer'
84
- else
85
- 'foreman-installer'
86
- end
87
- when :legacy_katello
88
- 'katello-installer'
89
- when :legacy_capsule
90
- 'capsule-installer'
44
+ if feature(:satellite)
45
+ 'satellite-installer'
46
+ else
47
+ 'foreman-installer'
91
48
  end
92
49
  end
93
50
 
@@ -105,22 +62,7 @@ class Features::Installer < ForemanMaintain::Feature
105
62
  end
106
63
 
107
64
  def upgrade(exec_options = {})
108
- run(installer_arguments, exec_options)
109
- end
110
-
111
- def installer_arguments
112
- installer_args = ''
113
-
114
- if feature(:foreman_proxy)&.with_content? &&
115
- check_max_version('foreman-installer', '3.4')
116
- installer_args += ' --disable-system-checks'
117
- end
118
-
119
- if !check_min_version('foreman-installer', '2.1') && can_upgrade?
120
- installer_args += ' --upgrade'
121
- end
122
-
123
- installer_args
65
+ run('', exec_options)
124
66
  end
125
67
 
126
68
  def initial_admin_username
@@ -139,12 +139,6 @@ class Features::Instance < ForemanMaintain::Feature
139
139
  end
140
140
 
141
141
  def pick_failing_components(components)
142
- if feature(:katello).current_version < Gem::Version.new('3.2.0')
143
- # Note that katello_ping returns an empty result against foreman_auth.
144
- # https://github.com/Katello/katello/commit/95d7b9067d38f269a5ec121fb73b5c19d4422baf
145
- components.reject! { |n| n.eql?('foreman_auth') }
146
- end
147
-
148
142
  components.each_with_object([]) do |(name, data), failing|
149
143
  failing << name unless data['status'] == 'ok'
150
144
  end
@@ -64,9 +64,11 @@ module Procedures::Backup
64
64
  end
65
65
 
66
66
  def proxy_config(spinner)
67
- spinner.update('Collecting proxy configuration')
68
- feature(:installer).answers['foreman_proxy'].select do |key, _|
69
- PROXY_CONFIG_ENTRIES.include?(key)
67
+ if feature(:installer)
68
+ spinner.update('Collecting proxy configuration')
69
+ feature(:installer).answers['foreman_proxy'].select do |key, _|
70
+ PROXY_CONFIG_ENTRIES.include?(key)
71
+ end
70
72
  end
71
73
  end
72
74
  end
@@ -6,7 +6,7 @@ module Procedures::Packages
6
6
 
7
7
  def run
8
8
  question = "\nWARNING: This script runs #{feature(:installer).installer_command} " \
9
- "after the yum execution \n" \
9
+ "after the dnf execution \n" \
10
10
  "to ensure the #{feature(:instance).product_name} " \
11
11
  "is in a consistent state.\n" \
12
12
  "As a result some of your services may be restarted. \n\n" \
@@ -6,13 +6,13 @@ module Procedures::Packages
6
6
  param :force, 'Do not skip if package is installed', :flag => true, :default => false
7
7
  param :warn_on_errors, 'Do not interrupt scenario on failure',
8
8
  :flag => true, :default => false
9
- param :yum_options, 'Extra yum options if any', :array => true, :default => []
9
+ param :dnf_options, 'Extra dnf options if any', :array => true, :default => []
10
10
  end
11
11
 
12
12
  def run
13
13
  assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
14
14
  package_manager.clean_cache(:assumeyes => assumeyes_val)
15
- opts = { :assumeyes => assumeyes_val, :yum_options => @yum_options }
15
+ opts = { :assumeyes => assumeyes_val, :dnf_options => @dnf_options }
16
16
  packages_action(:update, @packages, opts)
17
17
  rescue ForemanMaintain::Error::ExecutionError => e
18
18
  if @warn_on_errors
@@ -27,7 +27,7 @@ module Procedures::Packages
27
27
  end
28
28
 
29
29
  def description
30
- if @yum_options.include?('--downloadonly')
30
+ if @dnf_options.include?('--downloadonly')
31
31
  "Download package(s) #{@packages.join(', ')}"
32
32
  else
33
33
  "Update package(s) #{@packages.join(', ')}"
@@ -25,7 +25,7 @@ module ForemanMaintain::Scenarios
25
25
  accessibility_confirmation
26
26
  prepare_directory
27
27
  logical_volume_confirmation
28
- add_step_with_context(Procedures::Backup::Metadata)
28
+ add_step_with_context(Procedures::Backup::Metadata, :online_backup => online_backup?)
29
29
 
30
30
  case strategy
31
31
  when :online
@@ -49,7 +49,6 @@ module ForemanMaintain::Scenarios
49
49
  # rubocop:disable Metrics/MethodLength
50
50
  def set_context_mapping
51
51
  context.map(:backup_dir,
52
- Checks::Backup::DirectoryReady => :backup_dir,
53
52
  Procedures::Backup::PrepareDirectory => :backup_dir,
54
53
  Procedures::Backup::Metadata => :backup_dir,
55
54
  Procedures::Backup::ConfigFiles => :backup_dir,
@@ -66,7 +65,6 @@ module ForemanMaintain::Scenarios
66
65
  Procedures::Backup::Snapshot::MountForemanDB => :backup_dir,
67
66
  Procedures::Backup::Snapshot::MountPulpcoreDB => :backup_dir)
68
67
  context.map(:preserve_dir,
69
- Checks::Backup::DirectoryReady => :preserve_dir,
70
68
  Procedures::Backup::PrepareDirectory => :preserve_dir)
71
69
  context.map(:incremental_dir,
72
70
  Procedures::Backup::PrepareDirectory => :incremental_dir,
@@ -104,8 +102,6 @@ module ForemanMaintain::Scenarios
104
102
 
105
103
  def prepare_directory
106
104
  add_step_with_context(Procedures::Backup::PrepareDirectory)
107
- add_step_with_context(Checks::Backup::DirectoryReady,
108
- :postgres_access => online_backup? || include_db_dumps?)
109
105
  end
110
106
 
111
107
  def logical_volume_confirmation
@@ -199,7 +195,6 @@ module ForemanMaintain::Scenarios
199
195
  Procedures::Backup::Online::ForemanDB,
200
196
  Procedures::Backup::Online::PulpcoreDB
201
197
  )
202
- add_step_with_context(Procedures::Backup::Metadata, :online_backup => true)
203
198
  end
204
199
 
205
200
  def strategy
@@ -67,13 +67,11 @@ module ForemanMaintain::Scenarios
67
67
  def downstream_self_upgrade(pkgs_to_update)
68
68
  ForemanMaintain.enable_maintenance_module
69
69
 
70
- if check_min_version('foreman', '2.5') || check_min_version('foreman-proxy', '2.5')
71
- yum_options = req_repos_to_update_pkgs.map do |id|
72
- "--enablerepo=#{id}"
73
- end
74
- add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true,
75
- yum_options: yum_options))
70
+ dnf_options = req_repos_to_update_pkgs.map do |id|
71
+ "--enablerepo=#{id}"
76
72
  end
73
+ add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true,
74
+ dnf_options: dnf_options))
77
75
  end
78
76
 
79
77
  def upstream_self_upgrade(pkgs_to_update)
@@ -27,7 +27,6 @@ module Scenarios::Capsule_6_15
27
27
  def compose
28
28
  add_steps(find_checks(:default))
29
29
  add_steps(find_checks(:pre_upgrade))
30
- add_step(Checks::Foreman::CheckpointSegments)
31
30
  add_step(Checks::Repositories::Validate.new(:version => '6.15'))
32
31
  end
33
32
  end
@@ -58,7 +57,7 @@ module Scenarios::Capsule_6_15
58
57
  modules_to_enable = ["satellite-capsule:#{el_short_name}"]
59
58
  add_step(Procedures::Packages::EnableModules.new(:module_names => modules_to_enable))
60
59
  add_step(Procedures::Packages::Update.new(:assumeyes => true,
61
- :yum_options => ['--downloadonly']))
60
+ :dnf_options => ['--downloadonly']))
62
61
  add_step(Procedures::Service::Stop.new)
63
62
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
64
63
  add_step_with_context(Procedures::Installer::Upgrade)
@@ -27,7 +27,6 @@ module Scenarios::Capsule_6_15_z
27
27
  def compose
28
28
  add_steps(find_checks(:default))
29
29
  add_steps(find_checks(:pre_upgrade))
30
- add_step(Checks::Foreman::CheckpointSegments)
31
30
  add_step(Checks::Repositories::Validate.new(:version => '6.15'))
32
31
  end
33
32
  end
@@ -58,7 +57,7 @@ module Scenarios::Capsule_6_15_z
58
57
  modules_to_enable = ["satellite-capsule:#{el_short_name}"]
59
58
  add_step(Procedures::Packages::EnableModules.new(:module_names => modules_to_enable))
60
59
  add_step(Procedures::Packages::Update.new(:assumeyes => true,
61
- :yum_options => ['--downloadonly']))
60
+ :dnf_options => ['--downloadonly']))
62
61
  add_step(Procedures::Service::Stop.new)
63
62
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
64
63
  add_step_with_context(Procedures::Installer::Upgrade)
@@ -55,7 +55,7 @@ module Scenarios::Katello_Nightly
55
55
  modules_to_enable = ["katello:#{el_short_name}", "pulpcore:#{el_short_name}"]
56
56
  add_step(Procedures::Packages::EnableModules.new(:module_names => modules_to_enable))
57
57
  add_step(Procedures::Packages::Update.new(:assumeyes => true,
58
- :yum_options => ['--downloadonly']))
58
+ :dnf_options => ['--downloadonly']))
59
59
  add_step(Procedures::Service::Stop.new)
60
60
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
61
61
  add_step_with_context(Procedures::Installer::Upgrade)
@@ -27,7 +27,6 @@ module Scenarios::Satellite_6_15
27
27
  def compose
28
28
  add_steps(find_checks(:default))
29
29
  add_steps(find_checks(:pre_upgrade))
30
- add_step(Checks::Foreman::CheckpointSegments)
31
30
  add_step(Checks::Repositories::Validate.new(:version => '6.15'))
32
31
  end
33
32
  end
@@ -59,7 +58,7 @@ module Scenarios::Satellite_6_15
59
58
  modules_to_enable = ["satellite:#{el_short_name}"]
60
59
  add_step(Procedures::Packages::EnableModules.new(:module_names => modules_to_enable))
61
60
  add_step(Procedures::Packages::Update.new(:assumeyes => true,
62
- :yum_options => ['--downloadonly']))
61
+ :dnf_options => ['--downloadonly']))
63
62
  add_step(Procedures::Service::Stop.new)
64
63
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
65
64
  add_step_with_context(Procedures::Installer::Upgrade)
@@ -27,7 +27,6 @@ module Scenarios::Satellite_6_15_z
27
27
  def compose
28
28
  add_steps(find_checks(:default))
29
29
  add_steps(find_checks(:pre_upgrade))
30
- add_step(Checks::Foreman::CheckpointSegments)
31
30
  add_step(Checks::Repositories::Validate.new(:version => '6.15'))
32
31
  end
33
32
  end
@@ -58,7 +57,7 @@ module Scenarios::Satellite_6_15_z
58
57
  modules_to_enable = ["satellite:#{el_short_name}"]
59
58
  add_step(Procedures::Packages::EnableModules.new(:module_names => modules_to_enable))
60
59
  add_step(Procedures::Packages::Update.new(:assumeyes => true,
61
- :yum_options => ['--downloadonly']))
60
+ :dnf_options => ['--downloadonly']))
62
61
  add_step(Procedures::Service::Stop.new)
63
62
  add_step(Procedures::Packages::Update.new(:assumeyes => true))
64
63
  add_step_with_context(Procedures::Installer::Upgrade)
@@ -1,3 +1,3 @@
1
1
  [main]
2
2
  enabled = 0
3
- whitelist = /etc/yum/pluginconf.d/foreman-protector.whitelist
3
+ whitelist = /etc/dnf/plugins/foreman-protector.whitelist
@@ -75,11 +75,6 @@ module ForemanMaintain
75
75
  :hidden_patterns => [config['password']])
76
76
  end
77
77
 
78
- def backup_file_path(config = configuration)
79
- dump_file_name = "#{config['database']}_#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}.dump"
80
- "#{backup_dir}/#{dump_file_name}.bz2"
81
- end
82
-
83
78
  def dump_db(file, config = configuration)
84
79
  execute!(dump_command(config) + " > #{file}", :hidden_patterns => [config['password']])
85
80
  end
@@ -115,47 +110,11 @@ module ForemanMaintain
115
110
  end
116
111
  end
117
112
 
118
- # TODO: refactor to use dump_db
119
- def backup_db_command(file_path, config = configuration)
120
- pg_dump_cmd = "pg_dump -Fc #{config['database']}"
121
- "runuser - postgres -c '#{pg_dump_cmd}' | bzip2 -9 > #{file_path}"
122
- end
123
-
124
113
  # TODO: remove the backup file path tools from here. Lib Utils::Backup?
125
114
  def backup_dir
126
115
  @backup_dir ||= File.expand_path(ForemanMaintain.config.db_backup_dir)
127
116
  end
128
117
 
129
- def perform_backup(config = configuration)
130
- file_path = backup_file_path(config)
131
- backup_cmd = backup_db_command(file_path, config)
132
- execute!(backup_cmd, :hidden_patterns => [config['password']])
133
- puts "\n Note: Database backup file path - #{file_path}"
134
- puts "\n In case of any exception, use above dump file to restore DB."
135
- end
136
-
137
- def table_exist?(table_name)
138
- sql = <<-SQL
139
- SELECT EXISTS ( SELECT *
140
- FROM information_schema.tables WHERE table_name = '#{table_name}' )
141
- SQL
142
- result = query(sql)
143
- return false if result.nil? || (result && result.empty?)
144
-
145
- result.first['exists'].eql?('t')
146
- end
147
-
148
- def delete_records_by_ids(tbl_name, rec_ids)
149
- quotize_rec_ids = rec_ids.map { |el| "'#{el}'" }.join(',')
150
- unless quotize_rec_ids.empty?
151
- psql(<<-SQL)
152
- BEGIN;
153
- DELETE FROM #{tbl_name} WHERE id IN (#{quotize_rec_ids});
154
- COMMIT;
155
- SQL
156
- end
157
- end
158
-
159
118
  def find_base_directory(directory)
160
119
  find_dir_containing_file(directory, 'postgresql.conf')
161
120
  end
@@ -100,13 +100,13 @@ module ForemanMaintain
100
100
  end
101
101
 
102
102
  def packages_action(action, packages, options = {})
103
- options.validate_options!(:assumeyes, :yum_options)
103
+ options.validate_options!(:assumeyes, :dnf_options)
104
104
  case action
105
105
  when :install
106
106
  package_manager.install(packages, :assumeyes => options[:assumeyes])
107
107
  when :update
108
108
  package_manager.update(packages, :assumeyes => options[:assumeyes],
109
- :yum_options => options[:yum_options])
109
+ :dnf_options => options[:dnf_options])
110
110
  when :remove
111
111
  package_manager.remove(packages, :assumeyes => options[:assumeyes])
112
112
  else
@@ -64,7 +64,11 @@ module ForemanMaintain
64
64
  end
65
65
 
66
66
  def config_file_path
67
- File.exist?(CONFIG_FILE) ? CONFIG_FILE : File.join(source_path, 'config/foreman_maintain.yml')
67
+ if defined?(CONFIG_FILE) && File.exist?(CONFIG_FILE)
68
+ CONFIG_FILE
69
+ else
70
+ File.join(source_path, 'config/foreman_maintain.yml')
71
+ end
68
72
  end
69
73
 
70
74
  def source_path
@@ -1,14 +1,100 @@
1
1
  module ForemanMaintain::PackageManager
2
- class Dnf < Yum
3
- def clean_cache(assumeyes: false)
4
- dnf_action('clean', 'all', :assumeyes => assumeyes)
5
- super
2
+ class Dnf < Base
3
+ PROTECTOR_CONFIG_FILE = '/etc/dnf/plugins/foreman-protector.conf'.freeze
4
+ PROTECTOR_WHITELIST_FILE = '/etc/dnf/plugins/foreman-protector.whitelist'.freeze
5
+
6
+ def self.parse_envra(envra)
7
+ # envra format: 0:foreman-1.20.1.10-1.el7sat.noarch
8
+ parsed = envra.match(/\d*:?(?<name>.*)-[^-]+-[^-]+\.[^.]+/)
9
+ parsed ? Hash[parsed.names.map(&:to_sym).zip(parsed.captures)].merge(:envra => envra) : nil
10
+ end
11
+
12
+ def lock_versions
13
+ enable_protector
14
+ end
15
+
16
+ def unlock_versions
17
+ disable_protector
18
+ end
19
+
20
+ def versions_locked?
21
+ !!(protector_config =~ /^\s*enabled\s*=\s*1/) &&
22
+ protector_whitelist_file_nonzero?
23
+ end
24
+
25
+ def protector_whitelist_file_nonzero?
26
+ File.exist?(PROTECTOR_WHITELIST_FILE) &&
27
+ !File.zero?(PROTECTOR_WHITELIST_FILE)
6
28
  end
7
29
 
8
30
  def version_locking_supported?
9
31
  true
10
32
  end
11
33
 
34
+ def installed?(packages)
35
+ packages_list = [packages].flatten(1).map { |pkg| "'#{pkg}'" }.join(' ')
36
+ sys.execute?(%(rpm -q #{packages_list}))
37
+ end
38
+
39
+ def find_installed_package(name, queryformat = '')
40
+ rpm_cmd = "rpm -q '#{name}'"
41
+ unless queryformat.empty?
42
+ rpm_cmd += " --qf '#{queryformat}'"
43
+ end
44
+ status, result = sys.execute_with_status(rpm_cmd, interactive: false)
45
+ if status == 0
46
+ result
47
+ end
48
+ end
49
+
50
+ def install(packages, assumeyes: false)
51
+ dnf_action('install', packages, assumeyes: assumeyes)
52
+ end
53
+
54
+ def reinstall(packages, assumeyes: false)
55
+ dnf_action('reinstall', packages, assumeyes: assumeyes)
56
+ end
57
+
58
+ def remove(packages, assumeyes: false)
59
+ dnf_action('remove', packages, assumeyes: assumeyes)
60
+ end
61
+
62
+ def update(packages = [], assumeyes: false, dnf_options: [])
63
+ dnf_action('update', packages, assumeyes: assumeyes, dnf_options: dnf_options)
64
+ end
65
+
66
+ def check_update(packages: nil, with_status: false)
67
+ dnf_action(
68
+ 'check-update',
69
+ packages,
70
+ assumeyes: true,
71
+ valid_exit_statuses: [0, 100],
72
+ with_status: with_status
73
+ )
74
+ end
75
+
76
+ def update_available?(package)
77
+ cmd_output = dnf_action('check-update -q', package, with_status: true, assumeyes: false)
78
+ cmd_output[0] == 100
79
+ end
80
+
81
+ def files_not_owned_by_package(directory)
82
+ find_cmd = "find #{directory} -exec /bin/sh -c 'rpm -qf {} &> /dev/null || echo {}' \\;"
83
+ sys.execute(find_cmd).split("\n")
84
+ end
85
+
86
+ def list_installed_packages(queryformat = '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n')
87
+ # The queryformat should only include valid tag(s) as per `rpm --querytags` list.
88
+ # If any special formatting is required with querytag then it should be provided with tag i.e,
89
+ # "--%{VENDOR}"
90
+ # The queryformat string must end with '\n'
91
+ sys.execute!("rpm -qa --qf '#{queryformat}'").split("\n")
92
+ end
93
+
94
+ def clean_cache(assumeyes: false)
95
+ dnf_action('clean', 'all', :assumeyes => assumeyes)
96
+ end
97
+
12
98
  def module_enabled?(name)
13
99
  _status, result = info(name)
14
100
  result.match?(/Stream.+\[e\].+/)
@@ -29,18 +115,59 @@ module ForemanMaintain::PackageManager
29
115
 
30
116
  private
31
117
 
32
- def dnf_action(action, packages, with_status: false, assumeyes: false)
118
+ # rubocop:disable Metrics/LineLength, Metrics/ParameterLists
119
+ def dnf_action(action, packages, with_status: false, assumeyes: false, dnf_options: [], valid_exit_statuses: [0])
33
120
  packages = [packages].flatten(1)
34
- yum_options = []
35
- yum_options << '-y' if assumeyes
121
+
122
+ dnf_options << '-y' if assumeyes
123
+ dnf_options << '--disableplugin=foreman-protector'
124
+
125
+ command = ['dnf', dnf_options.join(' '), action]
126
+
127
+ command.push(packages.join(' ')) unless packages.empty?
128
+ command = command.join(' ')
129
+
36
130
  if with_status
37
- sys.execute_with_status("dnf #{yum_options.join(' ')} #{action} #{packages.join(' ')}",
38
- :interactive => !assumeyes)
131
+ sys.execute_with_status(
132
+ command,
133
+ :interactive => !assumeyes
134
+ )
39
135
  else
40
- sys.execute!("dnf #{yum_options.join(' ')} #{action} #{packages.join(' ')}",
41
- :interactive => !assumeyes)
136
+ sys.execute!(
137
+ command,
138
+ :interactive => !assumeyes,
139
+ :valid_exit_statuses => valid_exit_statuses
140
+ )
141
+ end
142
+ end
143
+ # rubocop:enable Metrics/LineLength, Metrics/ParameterLists
42
144
 
145
+ def protector_config
146
+ File.exist?(protector_config_file) ? File.read(protector_config_file) : ''
147
+ end
148
+
149
+ def protector_config_file
150
+ PROTECTOR_CONFIG_FILE
151
+ end
152
+
153
+ def enable_protector
154
+ setup_protector(true)
155
+ end
156
+
157
+ def disable_protector
158
+ setup_protector(false)
159
+ end
160
+
161
+ def setup_protector(enabled)
162
+ config = protector_config
163
+ config += "\n" unless config[-1] == "\n"
164
+ enabled_re = /^\s*enabled\s*=.*$/
165
+ if enabled_re.match(config)
166
+ config = config.gsub(enabled_re, "enabled = #{enabled ? '1' : '0'}")
167
+ else
168
+ config += "enabled = #{enabled ? '1' : '0'}\n"
43
169
  end
170
+ File.open(protector_config_file, 'w') { |file| file.puts config }
44
171
  end
45
172
  end
46
173
  end
@@ -1,5 +1,4 @@
1
1
  require 'foreman_maintain/package_manager/base'
2
- require 'foreman_maintain/package_manager/yum'
3
2
  require 'foreman_maintain/package_manager/dnf'
4
3
  require 'foreman_maintain/package_manager/apt'
5
4
 
@@ -72,8 +72,8 @@ module ForemanMaintain::RepositoryManager
72
72
  entry.split(':', 2).last.strip
73
73
  end]
74
74
 
75
- # The EL7 yum repolist output includes extra info in the output,
76
- # as example
75
+ # repolist output includes extra info in the output
76
+ #
77
77
  # rhel-7-server-rpms/7Server/x86_64
78
78
  # rhel-server-rhscl-7-rpms/7Server/x86_64
79
79
  # This trims anything after first '/' to get correct repo label
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '1.4.0'.freeze
2
+ VERSION = '1.4.1'.freeze
3
3
  end
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: 1.4.0
4
+ version: 1.4.1
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: 2023-09-06 00:00:00.000000000 Z
11
+ date: 2023-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -158,7 +158,6 @@ files:
158
158
  - config/foreman_maintain.yml.packaging
159
159
  - config/hammer.yml.example
160
160
  - definitions/checks/backup/certs_tar_exist.rb
161
- - definitions/checks/backup/directory_ready.rb
162
161
  - definitions/checks/candlepin/db_up.rb
163
162
  - definitions/checks/check_for_newer_packages.rb
164
163
  - definitions/checks/check_hotfix_installed.rb
@@ -168,15 +167,12 @@ files:
168
167
  - definitions/checks/disk/available_space_postgresql12.rb
169
168
  - definitions/checks/disk/performance.rb
170
169
  - definitions/checks/env_proxy.rb
171
- - definitions/checks/foreman/check_checkpoint_segments.rb
172
170
  - definitions/checks/foreman/check_corrupted_roles.rb
173
171
  - definitions/checks/foreman/check_duplicate_permission.rb
174
- - definitions/checks/foreman/check_duplicate_roles.rb
175
172
  - definitions/checks/foreman/check_puppet_capsules.rb
176
173
  - definitions/checks/foreman/check_tuning_requirements.rb
177
174
  - definitions/checks/foreman/db_up.rb
178
175
  - definitions/checks/foreman/facts_names.rb
179
- - definitions/checks/foreman/puppet_class_duplicates.rb
180
176
  - definitions/checks/foreman/validate_external_db_version.rb
181
177
  - definitions/checks/foreman_openscap/invalid_report_associations.rb
182
178
  - definitions/checks/foreman_proxy/check_tftp_storage.rb
@@ -188,8 +184,7 @@ files:
188
184
  - definitions/checks/foreman_tasks/not_running.rb
189
185
  - definitions/checks/maintenance_mode/check_consistency.rb
190
186
  - definitions/checks/non_rh_packages.rb
191
- - definitions/checks/original_assets.rb
192
- - definitions/checks/package_manager/yum/validate_yum_config.rb
187
+ - definitions/checks/package_manager/dnf/validate_dnf_config.rb
193
188
  - definitions/checks/pulpcore/db_up.rb
194
189
  - definitions/checks/puppet/verify_no_empty_cacert_requests.rb
195
190
  - definitions/checks/repositories/check_non_rh_repository.rb
@@ -259,11 +254,9 @@ files:
259
254
  - definitions/procedures/crond/start.rb
260
255
  - definitions/procedures/crond/stop.rb
261
256
  - definitions/procedures/files/remove.rb
262
- - definitions/procedures/foreman/apipie_cache.rb
263
257
  - definitions/procedures/foreman/fix_corrupted_roles.rb
264
258
  - definitions/procedures/foreman/remove_duplicate_obsolete_roles.rb
265
259
  - definitions/procedures/foreman/remove_duplicate_permissions.rb
266
- - definitions/procedures/foreman_docker/remove_foreman_docker.rb
267
260
  - definitions/procedures/foreman_maintain_features.rb
268
261
  - definitions/procedures/foreman_openscap/invalid_report_associations.rb
269
262
  - definitions/procedures/foreman_proxy/features.rb
@@ -342,7 +335,6 @@ files:
342
335
  - extras/foreman_protector/dnf/foreman-protector.py
343
336
  - extras/foreman_protector/foreman-protector.conf
344
337
  - extras/foreman_protector/foreman-protector.whitelist
345
- - extras/foreman_protector/yum/foreman-protector.py
346
338
  - lib/foreman_maintain.rb
347
339
  - lib/foreman_maintain/check.rb
348
340
  - lib/foreman_maintain/cli.rb
@@ -397,7 +389,6 @@ files:
397
389
  - lib/foreman_maintain/package_manager/apt.rb
398
390
  - lib/foreman_maintain/package_manager/base.rb
399
391
  - lib/foreman_maintain/package_manager/dnf.rb
400
- - lib/foreman_maintain/package_manager/yum.rb
401
392
  - lib/foreman_maintain/param.rb
402
393
  - lib/foreman_maintain/procedure.rb
403
394
  - lib/foreman_maintain/reporter.rb
@@ -1,23 +0,0 @@
1
- module Checks::Backup
2
- class DirectoryReady < ForemanMaintain::Check
3
- metadata do
4
- description 'Check if the directory exists and is writable'
5
- tags :backup
6
- manual_detection
7
- param :backup_dir, 'Directory where to backup to', :required => true
8
- param :preserve_dir, 'Directory where to backup to', :flag => true, :default => false
9
- param :postgres_access, 'Whether the postgres user needs access', :flag => true,
10
- :default => false
11
- end
12
-
13
- def run
14
- assert(File.directory?(@backup_dir), "Backup directory (#{@backup_dir}) does not exist.")
15
- if feature(:instance).postgresql_local? && @postgres_access
16
- result = system("runuser - postgres -c 'test -w #{@backup_dir}'")
17
- assert(result, "Postgres user needs write access to the backup directory \n" \
18
- "Please allow the postgres user write access to #{@backup_dir}" \
19
- ' or choose another directory.')
20
- end
21
- end
22
- end
23
- end
@@ -1,59 +0,0 @@
1
- module Checks
2
- module Foreman
3
- class CheckpointSegments < ForemanMaintain::Check
4
- metadata do
5
- label :check_postgresql_checkpoint_segments
6
- description 'Check if checkpoint_segments configuration exists on the system'
7
- confine do
8
- feature(:foreman) && feature(:installer) &&
9
- File.exist?(feature(:installer).custom_hiera_file)
10
- end
11
- end
12
-
13
- def run
14
- failure_message = check_custom_hiera
15
- fail! failure_message if failure_message
16
- end
17
-
18
- # rubocop:disable Metrics/MethodLength
19
- def check_custom_hiera
20
- hiera_file = feature(:installer).custom_hiera_file
21
- begin
22
- config = YAML.load_file(hiera_file)
23
- if config.is_a?(Hash) && config.key?('postgresql::server::config_entries')
24
- if config['postgresql::server::config_entries'].nil?
25
- return <<-MESSAGE.strip_heredoc
26
- ERROR: 'postgresql::server::config_entries' cannot be null.
27
- Please remove it from following file and re-run the command.
28
- - #{hiera_file}
29
- MESSAGE
30
- elsif config['postgresql::server::config_entries'].key?('checkpoint_segments')
31
- message = <<-MESSAGE.strip_heredoc
32
- ERROR: Tuning option 'checkpoint_segments' found.
33
- This option is no longer valid for PostgreSQL 9.5 or newer.
34
- Please remove it from following file and re-run the command.
35
- - #{hiera_file}
36
- MESSAGE
37
- if feature(:katello)
38
- message += <<-MESSAGE.strip_heredoc
39
- The presence of checkpoint_segments in #{hiera_file} indicates manual tuning.
40
- Manual tuning can override values provided by the --tuning parameter.
41
- Review #{hiera_file} for values that are already provided by the built in tuning profiles.
42
- Built in tuning profiles also provide a supported upgrade path.
43
- MESSAGE
44
- end
45
- return message
46
- end
47
- elsif config.is_a?(String)
48
- fail! "Error: File #{hiera_file} is not a yaml file."
49
- exit 1
50
- end
51
- rescue Psych::SyntaxError
52
- fail! "Found syntax error in file: #{hiera_file}"
53
- exit 1
54
- end
55
- end
56
- # rubocop:enable Metrics/MethodLength
57
- end
58
- end
59
- end
@@ -1,42 +0,0 @@
1
- module Checks
2
- module Foreman
3
- class CheckDuplicateRoles < ForemanMaintain::Check
4
- metadata do
5
- label :duplicate_roles
6
- for_feature :foreman_database
7
- description 'Check for duplicate roles from DB'
8
- tags :pre_upgrade
9
- confine do
10
- check_max_version('foreman', '1.20')
11
- end
12
- end
13
-
14
- def run
15
- duplicate_roles = find_duplicate_roles
16
- roles_names = duplicate_roles.map { |r| r['name'] }.uniq
17
- assert(
18
- duplicate_roles.empty?,
19
- "Duplicate entries found for role(s) - #{roles_names.join(', ')} in your DB",
20
- :next_steps => [
21
- Procedures::Foreman::RemoveDuplicateObsoleteRoles.new,
22
- Procedures::KnowledgeBaseArticle.new(
23
- :doc => 'fix_db_migrate_failure_on_duplicate_roles'
24
- ),
25
- ]
26
- )
27
- end
28
-
29
- def find_duplicate_roles
30
- feature(:foreman_database).query(self.class.query_to_get_duplicate_roles)
31
- end
32
-
33
- def self.query_to_get_duplicate_roles
34
- <<-SQL
35
- SELECT r.id, r.name FROM roles r JOIN (
36
- SELECT name, COUNT(*) FROM roles GROUP BY name HAVING count(*) > 1
37
- ) dr ON r.name = dr.name ORDER BY r.name
38
- SQL
39
- end
40
- end
41
- end
42
- end
@@ -1,48 +0,0 @@
1
- module Checks
2
- module Foreman
3
- class PuppetClassDuplicates < ForemanMaintain::Check
4
- metadata do
5
- label :puppet_class_duplicates
6
- for_feature :foreman_database
7
- description 'Check for duplicate Puppet class records'
8
- tags :pre_upgrade
9
- confine do
10
- check_max_version('foreman', '1.20')
11
- end
12
- end
13
-
14
- def run
15
- duplicate_names = find_duplicate_names
16
- assert(duplicate_names.empty?, duplicate_msg(duplicate_names))
17
- end
18
-
19
- private
20
-
21
- def duplicate_msg(duplicate_names)
22
- msg = "There are #{duplicate_names.count} Puppet classes with duplicities:\n"
23
- classes_list = duplicate_names.reduce('') do |memo, hash|
24
- memo.tap { |acc| acc << "#{hash['name']} - #{hash['name_count']}\n" }
25
- end
26
- help_msg = 'Please head over to Configure -> Classes'
27
- help_msg << " and make sure there is only 1 Puppet class record for each name.\n"
28
- [msg, classes_list, help_msg].join('')
29
- end
30
-
31
- def find_duplicate_names
32
- feature(:foreman_database).query(duplicate_names_query)
33
- end
34
-
35
- def duplicate_names_query
36
- <<-SQL
37
- SELECT name, name_count
38
- FROM (
39
- SELECT name, count(name) AS name_count
40
- FROM puppetclasses
41
- GROUP BY name
42
- ) AS puppetclass_counts
43
- WHERE name_count > 1
44
- SQL
45
- end
46
- end
47
- end
48
- end
@@ -1,23 +0,0 @@
1
- class Checks::OriginalAssets < ForemanMaintain::Check
2
- metadata do
3
- description 'Check if only installed assets are present on the system'
4
- tags :post_upgrade
5
- for_feature :foreman_server
6
- end
7
-
8
- ASSETS_DIR = '/var/lib/foreman/public/assets'.freeze
9
-
10
- def run
11
- custom_assets = []
12
- product_name = feature(:instance).product_name
13
- with_spinner('Checking for presence of non-original assets...') do
14
- custom_assets = package_manager.files_not_owned_by_package(ASSETS_DIR)
15
- logger.info("Non-original assets detected:\n" + custom_assets.join("\n"))
16
- end
17
- remove_files = Procedures::Files::Remove.new(:files => custom_assets, :assumeyes => true)
18
- assert(custom_assets.empty?,
19
- "Some assets not owned by #{product_name} were detected on the system.\n" \
20
- 'Possible conflicting versions can affect operation of the Web UI.',
21
- :next_steps => remove_files)
22
- end
23
- end
@@ -1,12 +0,0 @@
1
- module Procedures::Foreman
2
- class ApipieCache < ForemanMaintain::Procedure
3
- metadata do
4
- advanced_run false
5
- description 'Regenerate Apipie cache'
6
- end
7
-
8
- def run
9
- execute!('FOREMAN_APIPIE_LANGS=en foreman-rake apipie:cache')
10
- end
11
- end
12
- end
@@ -1,16 +0,0 @@
1
- module Procedures::ForemanDocker
2
- class RemoveForemanDocker < ForemanMaintain::Procedure
3
- metadata do
4
- advanced_run false
5
- description 'Drop foreman_docker plugin'
6
- confine do
7
- find_package(foreman_plugin_name('foreman_docker'))
8
- end
9
- end
10
-
11
- def run
12
- execute!('foreman-rake foreman_docker:cleanup')
13
- packages_action(:remove, foreman_plugin_name('foreman_docker'), :assumeyes => true)
14
- end
15
- end
16
- end
@@ -1,86 +0,0 @@
1
- from yum.plugins import PluginYumExit
2
- from yum.plugins import TYPE_CORE
3
- from rpmUtils.miscutils import splitFilename
4
- from yum.packageSack import packagesNewestByName
5
-
6
- import urlgrabber
7
- import urlgrabber.grabber
8
-
9
- import os
10
- import fnmatch
11
- import tempfile
12
- import time
13
-
14
- requires_api_version = '2.1'
15
- plugin_type = (TYPE_CORE,)
16
-
17
- _package_whitelist = set()
18
- fileurl = None
19
-
20
- def _load_whitelist():
21
- try:
22
- if fileurl:
23
- llfile = urlgrabber.urlopen(fileurl)
24
- for line in llfile.readlines():
25
- if line.startswith('#') or line.strip() == '':
26
- continue
27
- _package_whitelist.add(line.rstrip().lower())
28
- llfile.close()
29
- except urlgrabber.grabber.URLGrabError as e:
30
- raise PluginYumExit('Unable to read Foreman protector"s configuration: %s' % e)
31
-
32
- def _add_obsoletes(conduit):
33
- if _package_whitelist:
34
- # If anything obsoletes something that we have whitelisted ... then
35
- # whitelist that too.
36
- for (pkgtup, instTup) in conduit._base.up.getObsoletesTuples():
37
- if instTup[0] not in _package_whitelist:
38
- continue
39
- _package_whitelist.add(pkgtup[0].lower())
40
-
41
- def _get_updates(base):
42
- updates = {}
43
-
44
- for p in base.pkgSack.returnNewestByName():
45
- if p.name in _package_whitelist:
46
- # This one is whitelisted, skip
47
- continue
48
- updates[p.name] = p
49
-
50
- return updates
51
-
52
- def config_hook(conduit):
53
- global fileurl
54
-
55
- fileurl = conduit.confString('main', 'whitelist')
56
-
57
- def _add_package_whitelist_excluders(conduit):
58
- if hasattr(conduit, 'registerPackageName'):
59
- conduit.registerPackageName("yum-plugin-foreman-protector")
60
- ape = conduit._base.pkgSack.addPackageExcluder
61
- exid = 'foreman-protector.W.'
62
- ape(None, exid + str(1), 'mark.washed')
63
- ape(None, exid + str(2), 'wash.name.in', _package_whitelist)
64
- ape(None, exid + str(3), 'exclude.marked')
65
-
66
- def exclude_hook(conduit):
67
- conduit.info(3, 'Reading Foreman protector configuration')
68
-
69
- _load_whitelist()
70
- _add_obsoletes(conduit)
71
-
72
- total = len(_get_updates(conduit._base))
73
- conduit.info(3, '*** Excluded total: %s' % total)
74
- if total:
75
- if total > 1:
76
- suffix = 's'
77
- else:
78
- suffix = ''
79
- conduit.info(1, '\n'
80
- 'WARNING: Excluding %d package%s due to foreman-protector. \n'
81
- 'Use foreman-maintain packages install/update <package> \n'
82
- 'to safely install packages without restrictions.\n'
83
- 'Use foreman-maintain upgrade run for full upgrade.\n'
84
- % (total, suffix))
85
-
86
- _add_package_whitelist_excluders(conduit)
@@ -1,142 +0,0 @@
1
- module ForemanMaintain::PackageManager
2
- class Yum < Base
3
- PROTECTOR_CONFIG_FILE = '/etc/yum/pluginconf.d/foreman-protector.conf'.freeze
4
- PROTECTOR_WHITELIST_FILE = '/etc/yum/pluginconf.d/foreman-protector.whitelist'.freeze
5
-
6
- def self.parse_envra(envra)
7
- # envra format: 0:foreman-1.20.1.10-1.el7sat.noarch
8
- parsed = envra.match(/\d*:?(?<name>.*)-[^-]+-[^-]+\.[^.]+/)
9
- parsed ? Hash[parsed.names.map(&:to_sym).zip(parsed.captures)].merge(:envra => envra) : nil
10
- end
11
-
12
- def lock_versions
13
- enable_protector
14
- end
15
-
16
- def unlock_versions
17
- disable_protector
18
- end
19
-
20
- def versions_locked?
21
- !!(protector_config =~ /^\s*enabled\s*=\s*1/) &&
22
- protector_whitelist_file_nonzero?
23
- end
24
-
25
- def protector_whitelist_file_nonzero?
26
- File.exist?(PROTECTOR_WHITELIST_FILE) &&
27
- !File.zero?(PROTECTOR_WHITELIST_FILE)
28
- end
29
-
30
- def version_locking_supported?
31
- true
32
- end
33
-
34
- def installed?(packages)
35
- packages_list = [packages].flatten(1).map { |pkg| "'#{pkg}'" }.join(' ')
36
- sys.execute?(%(rpm -q #{packages_list}))
37
- end
38
-
39
- def find_installed_package(name, queryformat = '')
40
- rpm_cmd = "rpm -q '#{name}'"
41
- unless queryformat.empty?
42
- rpm_cmd += " --qf '#{queryformat}'"
43
- end
44
- status, result = sys.execute_with_status(rpm_cmd)
45
- if status == 0
46
- result
47
- end
48
- end
49
-
50
- def install(packages, assumeyes: false)
51
- yum_action('install', packages, :assumeyes => assumeyes)
52
- end
53
-
54
- def reinstall(packages, assumeyes: false)
55
- yum_action('reinstall', packages, :assumeyes => assumeyes)
56
- end
57
-
58
- def remove(packages, assumeyes: false)
59
- yum_action('remove', packages, :assumeyes => assumeyes)
60
- end
61
-
62
- def update(packages = [], assumeyes: false, yum_options: [])
63
- yum_action('update', packages, :assumeyes => assumeyes, :yum_options => yum_options)
64
- end
65
-
66
- def clean_cache(assumeyes: false)
67
- yum_action('clean', 'all', :assumeyes => assumeyes)
68
- end
69
-
70
- def check_update(packages: nil, with_status: false)
71
- yum_action('check-update', packages, :assumeyes => true, :valid_exit_statuses => [0, 100],
72
- :with_status => with_status)
73
- end
74
-
75
- def update_available?(package)
76
- cmd_output = yum_action('check-update -q', package, :with_status => true, :assumeyes => false)
77
- cmd_output[0] == 100
78
- end
79
-
80
- def files_not_owned_by_package(directory)
81
- find_cmd = "find #{directory} -exec /bin/sh -c 'rpm -qf {} &> /dev/null || echo {}' \\;"
82
- sys.execute(find_cmd).split("\n")
83
- end
84
-
85
- def list_installed_packages(queryformat = '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n')
86
- # The queryformat should only include valid tag(s) as per `rpm --querytags` list.
87
- # If any special formatting is required with querytag then it should be provided with tag i.e,
88
- # "--%{VENDOR}"
89
- # The queryformat string must end with '\n'
90
- sys.execute!("rpm -qa --qf '#{queryformat}'").split("\n")
91
- end
92
-
93
- private
94
-
95
- def protector_config
96
- File.exist?(protector_config_file) ? File.read(protector_config_file) : ''
97
- end
98
-
99
- def protector_config_file
100
- PROTECTOR_CONFIG_FILE
101
- end
102
-
103
- def enable_protector
104
- setup_protector(true)
105
- end
106
-
107
- def disable_protector
108
- setup_protector(false)
109
- end
110
-
111
- def setup_protector(enabled)
112
- config = protector_config
113
- config += "\n" unless config[-1] == "\n"
114
- enabled_re = /^\s*enabled\s*=.*$/
115
- if enabled_re.match(config)
116
- config = config.gsub(enabled_re, "enabled = #{enabled ? '1' : '0'}")
117
- else
118
- config += "enabled = #{enabled ? '1' : '0'}\n"
119
- end
120
- File.open(protector_config_file, 'w') { |file| file.puts config }
121
- end
122
-
123
- def yum_action(action, packages, options)
124
- with_status = options.fetch(:with_status, false)
125
- assumeyes = options.fetch(:assumeyes, false)
126
- valid_exit_statuses = options.fetch(:valid_exit_statuses, [0])
127
- yum_options = options.fetch(:yum_options, [])
128
- packages = [packages].flatten(1)
129
- yum_options << '-y' if assumeyes
130
- yum_options << '--disableplugin=foreman-protector'
131
- yum_options_s = yum_options.empty? ? '' : ' ' + yum_options.join(' ')
132
- packages_s = packages.empty? ? '' : ' ' + packages.join(' ')
133
- if with_status
134
- sys.execute_with_status("yum#{yum_options_s} #{action}#{packages_s}",
135
- :interactive => !assumeyes)
136
- else
137
- sys.execute!("yum#{yum_options_s} #{action}#{packages_s}",
138
- :interactive => !assumeyes, :valid_exit_statuses => valid_exit_statuses)
139
- end
140
- end
141
- end
142
- end