foreman_maintain 1.4.0 → 1.4.1

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