foreman_maintain 0.4.1 → 0.4.2

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