foreman_maintain 1.6.3 → 1.6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/definitions/checks/repositories/validate.rb +3 -1
- data/definitions/procedures/packages/check_for_reboot.rb +1 -1
- data/definitions/procedures/packages/update.rb +7 -6
- data/definitions/procedures/packages/update_all_confirmation.rb +1 -4
- data/definitions/scenarios/packages.rb +23 -7
- data/definitions/scenarios/update.rb +126 -0
- data/definitions/scenarios/upgrade_to_capsule_6_16.rb +1 -1
- data/definitions/scenarios/upgrade_to_capsule_6_16_z.rb +1 -1
- data/definitions/scenarios/upgrade_to_katello_nightly.rb +1 -1
- data/definitions/scenarios/upgrade_to_satellite_6_16.rb +1 -1
- data/definitions/scenarios/upgrade_to_satellite_6_16_z.rb +1 -1
- data/extras/foreman_protector/dnf/foreman-protector.py +5 -1
- data/lib/foreman_maintain/cli/packages_command.rb +4 -1
- data/lib/foreman_maintain/cli/update_command.rb +48 -0
- data/lib/foreman_maintain/cli.rb +2 -0
- data/lib/foreman_maintain/concerns/system_helpers.rb +7 -3
- data/lib/foreman_maintain/executable.rb +5 -1
- data/lib/foreman_maintain/package_manager/apt.rb +14 -3
- data/lib/foreman_maintain/package_manager/dnf.rb +16 -5
- data/lib/foreman_maintain/scenario.rb +3 -3
- data/lib/foreman_maintain/update_runner.rb +156 -0
- data/lib/foreman_maintain/utils/service/systemd.rb +8 -0
- data/lib/foreman_maintain/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9832b114fa0e778b687140d47774ffa583742e69c0883f7e0738fad23e6d0f87
|
4
|
+
data.tar.gz: dfd33002a93b7171aab581342c169d0eef6cee318302bad7d24108581e05b514
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30c727eed2a0f6fb4402caedfcbca2b5e8466b322f94f938523e16726b9439d3b00737950d88c41993fdd61f8cedea7c67752d1917e91ff6a6dde57dfbca1544
|
7
|
+
data.tar.gz: fd20b2f2ea602071e1371266b62e7640b945a942208469019f0ee173ab90afd51de78e91c9790c525d1d6e689f5d47779e57ce22c032a1a1d3c53f61eb566135
|
@@ -12,7 +12,7 @@ module Checks::Repositories
|
|
12
12
|
|
13
13
|
param :version,
|
14
14
|
'Version for which repositories needs to be validated',
|
15
|
-
:required =>
|
15
|
+
:required => false
|
16
16
|
|
17
17
|
manual_detection
|
18
18
|
end
|
@@ -21,6 +21,8 @@ module Checks::Repositories
|
|
21
21
|
if feature(:instance).downstream.subscribed_using_activation_key?
|
22
22
|
skip 'Your system is subscribed using custom activation key'
|
23
23
|
else
|
24
|
+
@version ||= package_version(feature(:instance).downstream.package_name)
|
25
|
+
|
24
26
|
with_spinner("Validating availability of repositories for #{@version}") do |spinner|
|
25
27
|
find_absent_repos(spinner)
|
26
28
|
end
|
@@ -7,13 +7,18 @@ module Procedures::Packages
|
|
7
7
|
param :warn_on_errors, 'Do not interrupt scenario on failure',
|
8
8
|
:flag => true, :default => false
|
9
9
|
param :dnf_options, 'Extra dnf options if any', :array => true, :default => []
|
10
|
+
param :download_only, 'Download and cache packages only', :flag => true, :default => false
|
10
11
|
param :clean_cache, 'If true will cause a DNF cache clean', :flag => true, :default => true
|
11
12
|
end
|
12
13
|
|
13
14
|
def run
|
14
15
|
assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
|
15
16
|
package_manager.clean_cache(:assumeyes => assumeyes_val) if @clean_cache
|
16
|
-
opts = {
|
17
|
+
opts = {
|
18
|
+
:assumeyes => assumeyes_val,
|
19
|
+
:options => @dnf_options,
|
20
|
+
:download_only => @download_only,
|
21
|
+
}
|
17
22
|
packages_action(:update, @packages, opts)
|
18
23
|
rescue ForemanMaintain::Error::ExecutionError => e
|
19
24
|
if @warn_on_errors
|
@@ -28,15 +33,11 @@ module Procedures::Packages
|
|
28
33
|
end
|
29
34
|
|
30
35
|
def description
|
31
|
-
if download_only
|
36
|
+
if @download_only
|
32
37
|
"Download package(s) #{@packages.join(', ')}"
|
33
38
|
else
|
34
39
|
"Update package(s) #{@packages.join(', ')}"
|
35
40
|
end
|
36
41
|
end
|
37
|
-
|
38
|
-
def download_only?
|
39
|
-
@dnf_options.include?('--downloadonly')
|
40
|
-
end
|
41
42
|
end
|
42
43
|
end
|
@@ -10,13 +10,10 @@ module Procedures::Packages
|
|
10
10
|
if @packages.nil? || @packages.empty?
|
11
11
|
question = "\nWARNING: No specific packages to update were provided\n" \
|
12
12
|
"so we are going to update all available packages.\n" \
|
13
|
-
"It is recommended to update everything only as part of upgrade\n" \
|
14
|
-
"of the #{feature(:instance).product_name} to the next version. \n" \
|
15
13
|
"To Upgrade to next version use 'foreman-maintain upgrade'.\n\n" \
|
16
|
-
"NOTE: --assumeyes is not applicable for this check\n\n" \
|
17
14
|
"Do you want to proceed with update of everything regardless\n" \
|
18
15
|
'of the recommendations?'
|
19
|
-
answer = ask_decision(question, actions_msg: 'y(yes), q(quit)'
|
16
|
+
answer = ask_decision(question, actions_msg: 'y(yes), q(quit)')
|
20
17
|
abort! unless answer == :yes
|
21
18
|
end
|
22
19
|
end
|
@@ -97,25 +97,41 @@ module ForemanMaintain::Scenarios
|
|
97
97
|
description 'update packages in unlocked session'
|
98
98
|
param :packages, 'List of packages to Update', :array => true
|
99
99
|
param :assumeyes, 'Do not ask for confirmation'
|
100
|
+
param :downloadonly, 'Download and cache packages'
|
100
101
|
manual_detection
|
101
102
|
end
|
102
103
|
|
104
|
+
# rubocop:disable Metrics/MethodLength
|
103
105
|
def compose
|
104
106
|
if Packages.skip_installer_run?(context.get(:packages))
|
105
107
|
add_step_with_context(Procedures::Packages::Update,
|
106
108
|
:force => true, :warn_on_errors => true)
|
107
109
|
else
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
110
|
+
unless context.get(:downloadonly)
|
111
|
+
add_steps_with_context(
|
112
|
+
Procedures::Packages::UpdateAllConfirmation,
|
113
|
+
Procedures::Packages::InstallerConfirmation
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
112
117
|
add_step_with_context(Procedures::Packages::UnlockVersions)
|
113
|
-
add_step_with_context(
|
114
|
-
|
115
|
-
|
118
|
+
add_step_with_context(
|
119
|
+
Procedures::Packages::Update,
|
120
|
+
:force => true,
|
121
|
+
:warn_on_errors => true,
|
122
|
+
:download_only => context.get(:downloadonly)
|
123
|
+
)
|
124
|
+
|
125
|
+
if context.get(:downloadonly)
|
126
|
+
add_step_with_context(Procedures::Packages::LockVersions)
|
127
|
+
else
|
128
|
+
add_step_with_context(Procedures::Installer::Run)
|
129
|
+
end
|
130
|
+
|
116
131
|
add_step(Procedures::Packages::LockingStatus)
|
117
132
|
end
|
118
133
|
end
|
134
|
+
# rubocop:enable Metrics/MethodLength
|
119
135
|
|
120
136
|
def set_context_mapping
|
121
137
|
context.map(:packages,
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Scenarios::Update
|
2
|
+
class Abstract < ForemanMaintain::Scenario
|
3
|
+
def self.update_metadata(&block)
|
4
|
+
metadata do
|
5
|
+
tags :update_scenario
|
6
|
+
instance_eval(&block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class PreUpdateCheck < Abstract
|
12
|
+
update_metadata do
|
13
|
+
description 'Checks before updating'
|
14
|
+
tags :pre_update_checks
|
15
|
+
run_strategy :fail_slow
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/MethodLength
|
19
|
+
def compose
|
20
|
+
add_steps(
|
21
|
+
Checks::Foreman::FactsNames, # if Foreman database present
|
22
|
+
Checks::ForemanProxy::CheckTftpStorage, # if Satellite with foreman-proxy+tftp
|
23
|
+
Checks::ForemanProxy::VerifyDhcpConfigSyntax, # if foreman-proxy+dhcp-isc
|
24
|
+
Checks::ForemanTasks::NotPaused, # if foreman-tasks present
|
25
|
+
Checks::Puppet::VerifyNoEmptyCacertRequests, # if puppetserver
|
26
|
+
Checks::ServerPing,
|
27
|
+
Checks::ServicesUp,
|
28
|
+
Checks::SystemRegistration,
|
29
|
+
Checks::CheckHotfixInstalled,
|
30
|
+
Checks::CheckTmout,
|
31
|
+
Checks::CheckUpstreamRepository,
|
32
|
+
Checks::Disk::AvailableSpace,
|
33
|
+
Checks::Disk::AvailableSpaceCandlepin, # if candlepin
|
34
|
+
Checks::Foreman::ValidateExternalDbVersion, # if external database
|
35
|
+
Checks::Foreman::CheckCorruptedRoles,
|
36
|
+
Checks::Foreman::CheckDuplicatePermissions,
|
37
|
+
Checks::Foreman::TuningRequirements, # if katello present
|
38
|
+
Checks::ForemanOpenscap::InvalidReportAssociations, # if foreman-openscap
|
39
|
+
Checks::ForemanTasks::Invalid::CheckOld, # if foreman-tasks
|
40
|
+
Checks::ForemanTasks::Invalid::CheckPendingState, # if foreman-tasks
|
41
|
+
Checks::ForemanTasks::Invalid::CheckPlanningState, # if foreman-tasks
|
42
|
+
Checks::ForemanTasks::NotRunning, # if foreman-tasks
|
43
|
+
Checks::NonRhPackages,
|
44
|
+
Checks::PackageManager::Dnf::ValidateDnfConfig,
|
45
|
+
Checks::Repositories::CheckNonRhRepository,
|
46
|
+
Checks::Repositories::Validate
|
47
|
+
)
|
48
|
+
end
|
49
|
+
# rubocop:enable Metrics/MethodLength
|
50
|
+
end
|
51
|
+
|
52
|
+
class PreMigrations < Abstract
|
53
|
+
update_metadata do
|
54
|
+
description 'Procedures before migrating'
|
55
|
+
tags :pre_migrations
|
56
|
+
end
|
57
|
+
|
58
|
+
def compose
|
59
|
+
add_steps(
|
60
|
+
Procedures::Packages::Update.new(
|
61
|
+
:assumeyes => true,
|
62
|
+
:dnf_options => ['--downloadonly']
|
63
|
+
),
|
64
|
+
Procedures::MaintenanceMode::EnableMaintenanceMode,
|
65
|
+
Procedures::Crond::Stop,
|
66
|
+
Procedures::SyncPlans::Disable
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Migrations < Abstract
|
72
|
+
update_metadata do
|
73
|
+
description 'Migration scripts'
|
74
|
+
tags :migrations
|
75
|
+
run_strategy :fail_fast
|
76
|
+
end
|
77
|
+
|
78
|
+
def compose
|
79
|
+
add_steps(
|
80
|
+
Procedures::Service::Stop,
|
81
|
+
Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false),
|
82
|
+
Procedures::Installer::Run.new(:assumeyes => true),
|
83
|
+
Procedures::Installer::UpgradeRakeTask
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class PostMigrations < Abstract
|
89
|
+
update_metadata do
|
90
|
+
description 'Procedures after migrating'
|
91
|
+
tags :post_migrations
|
92
|
+
end
|
93
|
+
|
94
|
+
def compose
|
95
|
+
add_steps(
|
96
|
+
Procedures::RefreshFeatures,
|
97
|
+
Procedures::Service::Start,
|
98
|
+
Procedures::Crond::Start,
|
99
|
+
Procedures::SyncPlans::Enable,
|
100
|
+
Procedures::MaintenanceMode::DisableMaintenanceMode
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class PostUpdateChecks < Abstract
|
106
|
+
update_metadata do
|
107
|
+
description 'Checks after update'
|
108
|
+
tags :post_update_checks
|
109
|
+
run_strategy :fail_slow
|
110
|
+
end
|
111
|
+
|
112
|
+
def compose
|
113
|
+
add_steps(
|
114
|
+
Checks::Foreman::FactsNames, # if Foreman database present
|
115
|
+
Checks::ForemanProxy::CheckTftpStorage, # if Satellite with foreman-proxy+tftp
|
116
|
+
Checks::ForemanProxy::VerifyDhcpConfigSyntax, # if foreman-proxy+dhcp-isc
|
117
|
+
Checks::ForemanTasks::NotPaused, # if foreman-tasks present
|
118
|
+
Checks::Puppet::VerifyNoEmptyCacertRequests, # if puppetserver
|
119
|
+
Checks::ServerPing,
|
120
|
+
Checks::ServicesUp,
|
121
|
+
Checks::SystemRegistration,
|
122
|
+
Procedures::Packages::CheckForReboot
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -63,7 +63,7 @@ module Scenarios::Capsule_6_16
|
|
63
63
|
end
|
64
64
|
add_step(Procedures::Packages::Update.new(
|
65
65
|
:assumeyes => true,
|
66
|
-
:
|
66
|
+
:download_only => true
|
67
67
|
))
|
68
68
|
add_step(Procedures::Service::Stop.new)
|
69
69
|
add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
|
@@ -60,7 +60,7 @@ module Scenarios::Katello_Nightly
|
|
60
60
|
end
|
61
61
|
add_step(Procedures::Packages::Update.new(
|
62
62
|
:assumeyes => true,
|
63
|
-
:
|
63
|
+
:download_only => true
|
64
64
|
))
|
65
65
|
add_step(Procedures::Service::Stop.new)
|
66
66
|
add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
|
@@ -65,7 +65,7 @@ module Scenarios::Satellite_6_16
|
|
65
65
|
end
|
66
66
|
add_step(Procedures::Packages::Update.new(
|
67
67
|
:assumeyes => true,
|
68
|
-
:
|
68
|
+
:download_only => true
|
69
69
|
))
|
70
70
|
add_step(Procedures::Service::Stop.new)
|
71
71
|
add_step(Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false))
|
@@ -1,8 +1,10 @@
|
|
1
|
+
import configparser
|
2
|
+
import os
|
3
|
+
|
1
4
|
import dnf
|
2
5
|
import dnf.exceptions
|
3
6
|
from dnfpluginscore import _, logger
|
4
7
|
|
5
|
-
import configparser
|
6
8
|
|
7
9
|
PROTECT_COMMANDS = ('install', 'downgrade', 'reinstall', 'distro-sync', 'swap', 'upgrade', 'upgrade-minimal')
|
8
10
|
|
@@ -53,6 +55,8 @@ class ForemanProtector(dnf.Plugin):
|
|
53
55
|
def sack(self):
|
54
56
|
if self.cli is not None and self.cli.command._basecmd not in PROTECT_COMMANDS:
|
55
57
|
return
|
58
|
+
if os.environ.get('LEAPP_IPU_IN_PROGRESS') is not None:
|
59
|
+
return
|
56
60
|
whitelist_and_obsoletes = self._add_obsoletes()
|
57
61
|
all_available_packages = self.base.sack.query().available()
|
58
62
|
excluded_pkgs_query = all_available_packages.difference(whitelist_and_obsoletes)
|
@@ -55,12 +55,15 @@ module ForemanMaintain
|
|
55
55
|
subcommand 'update', 'Update packages in an unlocked session' do
|
56
56
|
interactive_option(['assumeyes'])
|
57
57
|
parameter '[PACKAGES] ...', 'packages to update', :attribute_name => :packages
|
58
|
+
option '--downloadonly', :flag, 'Downloads and caches package updates only',
|
59
|
+
:default => false
|
58
60
|
|
59
61
|
def execute
|
60
62
|
run_scenarios_and_exit(
|
61
63
|
Scenarios::Packages::Update.new(
|
62
64
|
:packages => packages,
|
63
|
-
:assumeyes => assumeyes
|
65
|
+
:assumeyes => assumeyes?,
|
66
|
+
:downloadonly => @downloadonly
|
64
67
|
)
|
65
68
|
)
|
66
69
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'foreman_maintain/update_runner'
|
2
|
+
|
3
|
+
module ForemanMaintain
|
4
|
+
module Cli
|
5
|
+
class UpdateCommand < Base
|
6
|
+
def self.disable_self_update_option
|
7
|
+
option '--disable-self-update', :flag, 'Disable automatic self update',
|
8
|
+
:default => false
|
9
|
+
end
|
10
|
+
|
11
|
+
def update_runner
|
12
|
+
update_runner = ForemanMaintain::UpdateRunner.new(
|
13
|
+
reporter,
|
14
|
+
:assumeyes => assumeyes?,
|
15
|
+
:whitelist => whitelist || [],
|
16
|
+
:force => force?
|
17
|
+
)
|
18
|
+
update_runner.load
|
19
|
+
update_runner
|
20
|
+
end
|
21
|
+
|
22
|
+
subcommand 'check', 'Run pre-update checks before updating' do
|
23
|
+
interactive_option
|
24
|
+
disable_self_update_option
|
25
|
+
|
26
|
+
def execute
|
27
|
+
ForemanMaintain.validate_downstream_packages
|
28
|
+
ForemanMaintain.perform_self_upgrade unless disable_self_update?
|
29
|
+
update_runner.run_phase(:pre_update_checks)
|
30
|
+
exit update_runner.exit_code
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
subcommand 'run', 'Run an update' do
|
35
|
+
interactive_option
|
36
|
+
disable_self_update_option
|
37
|
+
|
38
|
+
def execute
|
39
|
+
ForemanMaintain.validate_downstream_packages
|
40
|
+
ForemanMaintain.perform_self_upgrade unless disable_self_update?
|
41
|
+
update_runner.run
|
42
|
+
update_runner.save
|
43
|
+
exit update_runner.exit_code
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/foreman_maintain/cli.rb
CHANGED
@@ -12,6 +12,7 @@ require 'foreman_maintain/cli/maintenance_mode_command'
|
|
12
12
|
require 'foreman_maintain/cli/packages_command'
|
13
13
|
require 'foreman_maintain/cli/plugin_command'
|
14
14
|
require 'foreman_maintain/cli/self_upgrade_command'
|
15
|
+
require 'foreman_maintain/cli/update_command'
|
15
16
|
|
16
17
|
Clamp.allow_options_after_parameters = true
|
17
18
|
|
@@ -22,6 +23,7 @@ module ForemanMaintain
|
|
22
23
|
|
23
24
|
subcommand 'health', 'Health related commands', HealthCommand
|
24
25
|
subcommand 'upgrade', 'Upgrade related commands', UpgradeCommand
|
26
|
+
subcommand 'update', 'Update related commands', UpdateCommand
|
25
27
|
subcommand 'service', 'Control applicable services', ServiceCommand
|
26
28
|
subcommand 'backup', 'Backup server', BackupCommand
|
27
29
|
subcommand 'restore', 'Restore a backup', RestoreCommand
|
@@ -100,13 +100,17 @@ module ForemanMaintain
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def packages_action(action, packages, options = {})
|
103
|
-
options.validate_options!(:assumeyes, :
|
103
|
+
options.validate_options!(:assumeyes, :options, :download_only)
|
104
104
|
case action
|
105
105
|
when :install
|
106
106
|
package_manager.install(packages, :assumeyes => options[:assumeyes])
|
107
107
|
when :update
|
108
|
-
package_manager.update(
|
109
|
-
|
108
|
+
package_manager.update(
|
109
|
+
packages,
|
110
|
+
:assumeyes => options[:assumeyes],
|
111
|
+
:options => options[:options],
|
112
|
+
:download_only => options[:download_only]
|
113
|
+
)
|
110
114
|
when :remove
|
111
115
|
package_manager.remove(packages, :assumeyes => options[:assumeyes])
|
112
116
|
else
|
@@ -138,7 +138,11 @@ module ForemanMaintain
|
|
138
138
|
def __run__(execution)
|
139
139
|
setup_execution_state(execution)
|
140
140
|
unless skipped?
|
141
|
-
|
141
|
+
if defined?(self.class.present?)
|
142
|
+
run if self.class.present?
|
143
|
+
else
|
144
|
+
run
|
145
|
+
end
|
142
146
|
end
|
143
147
|
rescue Error::Skip => e
|
144
148
|
set_skip(e.message)
|
@@ -19,10 +19,12 @@ module ForemanMaintain::PackageManager
|
|
19
19
|
apt_action('remove', packages, :assumeyes => assumeyes)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
23
|
+
def update(packages = [], assumeyes: false, options: [], download_only: false)
|
23
24
|
action = packages.any? ? '--only-upgrade install' : 'upgrade'
|
24
|
-
apt_action(action, packages, :assumeyes => assumeyes)
|
25
|
+
apt_action(action, packages, :assumeyes => assumeyes, :download_only => download_only)
|
25
26
|
end
|
27
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
26
28
|
|
27
29
|
def clean_cache(assumeyes: false)
|
28
30
|
apt_action('clean', :assumeyes => assumeyes)
|
@@ -60,10 +62,18 @@ module ForemanMaintain::PackageManager
|
|
60
62
|
false
|
61
63
|
end
|
62
64
|
|
63
|
-
def
|
65
|
+
def reboot_required?
|
66
|
+
status = File.exist?('/var/run/reboot-required') ? 1 : 0
|
67
|
+
output = ''
|
68
|
+
[status, output]
|
69
|
+
end
|
70
|
+
|
71
|
+
# rubocop:disable Layout/LineLength
|
72
|
+
def apt_action(action, packages, with_status: false, assumeyes: false, valid_exit_statuses: [0], download_only: false)
|
64
73
|
apt_options = []
|
65
74
|
packages = [packages].flatten(1)
|
66
75
|
apt_options << '-y' if assumeyes
|
76
|
+
apt_options << '--download-only' if download_only
|
67
77
|
apt_options_s = apt_options.empty? ? '' : ' ' + apt_options.join(' ')
|
68
78
|
packages_s = packages.empty? ? '' : ' ' + packages.join(' ')
|
69
79
|
if with_status
|
@@ -74,5 +84,6 @@ module ForemanMaintain::PackageManager
|
|
74
84
|
:interactive => !assumeyes, :valid_exit_statuses => valid_exit_statuses)
|
75
85
|
end
|
76
86
|
end
|
87
|
+
# rubocop:enable Layout/LineLength
|
77
88
|
end
|
78
89
|
end
|
@@ -59,8 +59,14 @@ module ForemanMaintain::PackageManager
|
|
59
59
|
dnf_action('remove', packages, assumeyes: assumeyes)
|
60
60
|
end
|
61
61
|
|
62
|
-
def update(packages = [], assumeyes: false,
|
63
|
-
dnf_action(
|
62
|
+
def update(packages = [], assumeyes: false, options: [], download_only: false)
|
63
|
+
dnf_action(
|
64
|
+
'update',
|
65
|
+
packages,
|
66
|
+
assumeyes: assumeyes,
|
67
|
+
dnf_options: options,
|
68
|
+
download_only: download_only
|
69
|
+
)
|
64
70
|
end
|
65
71
|
|
66
72
|
def check_update(packages: nil, with_status: false)
|
@@ -121,13 +127,18 @@ module ForemanMaintain::PackageManager
|
|
121
127
|
dnf_action('module info', name, with_status: true, assumeyes: true)
|
122
128
|
end
|
123
129
|
|
130
|
+
def reboot_required?
|
131
|
+
sys.execute_with_status('dnf needs-restarting --reboothint', :interactive => false)
|
132
|
+
end
|
133
|
+
|
124
134
|
private
|
125
135
|
|
126
|
-
# rubocop:disable
|
127
|
-
def dnf_action(action, packages, with_status: false, assumeyes: false, dnf_options: [], valid_exit_statuses: [0])
|
136
|
+
# rubocop:disable Layout/LineLength, Metrics/ParameterLists
|
137
|
+
def dnf_action(action, packages, with_status: false, assumeyes: false, dnf_options: [], valid_exit_statuses: [0], download_only: false)
|
128
138
|
packages = [packages].flatten(1)
|
129
139
|
|
130
140
|
dnf_options << '-y' if assumeyes
|
141
|
+
dnf_topions << '--downloadonly' if download_only
|
131
142
|
dnf_options << '--disableplugin=foreman-protector'
|
132
143
|
|
133
144
|
command = ['dnf', dnf_options.join(' '), action]
|
@@ -148,7 +159,7 @@ module ForemanMaintain::PackageManager
|
|
148
159
|
)
|
149
160
|
end
|
150
161
|
end
|
151
|
-
# rubocop:enable
|
162
|
+
# rubocop:enable Layout/LineLength, Metrics/ParameterLists
|
152
163
|
|
153
164
|
def protector_config
|
154
165
|
File.exist?(protector_config_file) ? File.read(protector_config_file) : ''
|
@@ -163,14 +163,14 @@ module ForemanMaintain
|
|
163
163
|
scenarios
|
164
164
|
end
|
165
165
|
|
166
|
-
def add_steps(steps)
|
167
|
-
steps.each do |step|
|
166
|
+
def add_steps(*steps)
|
167
|
+
steps.flatten.each do |step|
|
168
168
|
self.steps << step.ensure_instance
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
172
|
def add_step(step)
|
173
|
-
add_steps(
|
173
|
+
add_steps(step) unless step.nil?
|
174
174
|
end
|
175
175
|
|
176
176
|
def add_step_with_context(definition, extra_params = {})
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module ForemanMaintain
|
2
|
+
class UpdateRunner < Runner
|
3
|
+
include Concerns::Finders
|
4
|
+
|
5
|
+
PHASES = [
|
6
|
+
:pre_update_checks,
|
7
|
+
:pre_migrations,
|
8
|
+
:migrations,
|
9
|
+
:post_migrations,
|
10
|
+
:post_update_checks,
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
attr_reader :phase
|
14
|
+
|
15
|
+
def initialize(reporter, options = {})
|
16
|
+
super(reporter, [], options)
|
17
|
+
@scenario_cache = {}
|
18
|
+
self.phase = :pre_update_checks
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_scenario(phase)
|
22
|
+
return @scenario_cache[phase] if @scenario_cache.key?(phase)
|
23
|
+
|
24
|
+
condition = { :tags => [:update_scenario, phase] }
|
25
|
+
matching_scenarios = find_scenarios(condition)
|
26
|
+
@scenario_cache[phase] = matching_scenarios.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
PHASES.each do |phase|
|
31
|
+
return run_rollback if quit?
|
32
|
+
|
33
|
+
run_phase(phase)
|
34
|
+
end
|
35
|
+
|
36
|
+
finish_update unless quit?
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_rollback
|
40
|
+
# we only are able to rollback from pre_migrations phase
|
41
|
+
if phase == :pre_migrations
|
42
|
+
rollback_pre_migrations
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def finish_update
|
47
|
+
@finished = true
|
48
|
+
@reporter.hline
|
49
|
+
@reporter.puts("Update finished.")
|
50
|
+
end
|
51
|
+
|
52
|
+
def storage
|
53
|
+
ForemanMaintain.storage("update")
|
54
|
+
end
|
55
|
+
|
56
|
+
# serializes the state of the run to storage
|
57
|
+
def save
|
58
|
+
if @finished
|
59
|
+
storage.delete(:serialized)
|
60
|
+
else
|
61
|
+
storage[:serialized] = to_hash
|
62
|
+
end
|
63
|
+
storage.save
|
64
|
+
end
|
65
|
+
|
66
|
+
# deserializes the state of the run from the storage
|
67
|
+
def load
|
68
|
+
return unless storage[:serialized]
|
69
|
+
|
70
|
+
load_from_hash(storage[:serialized])
|
71
|
+
end
|
72
|
+
|
73
|
+
def run_phase(phase)
|
74
|
+
scenario = find_scenario(phase)
|
75
|
+
return if scenario.nil? || scenario.steps.empty?
|
76
|
+
|
77
|
+
confirm_scenario(scenario)
|
78
|
+
return if quit?
|
79
|
+
|
80
|
+
self.phase = phase
|
81
|
+
run_scenario(scenario)
|
82
|
+
# if we started from the :pre_update_checks, ensure to ask before
|
83
|
+
# continuing with the rest of the update
|
84
|
+
@ask_to_confirm_update = phase == :pre_update_checks
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def rollback_pre_migrations
|
90
|
+
raise "Unexpected phase #{phase}, expecting pre_migrations" unless phase == :pre_migrations
|
91
|
+
|
92
|
+
rollback_needed = scenario(:pre_migrations).steps.any? { |s| s.executed? && s.success? }
|
93
|
+
if rollback_needed
|
94
|
+
@quit = false
|
95
|
+
# prevent the unnecessary confirmation questions
|
96
|
+
@last_scenario = nil
|
97
|
+
@last_scenario_continuation_confirmed = true
|
98
|
+
[:post_migrations, :post_update_checks].each do |phase|
|
99
|
+
run_phase(phase)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
self.phase = :pre_update_checks # rollback finished
|
103
|
+
@reporter.puts("The update failed and system was restored to pre-update state.")
|
104
|
+
end
|
105
|
+
|
106
|
+
def with_non_empty_scenario(phase)
|
107
|
+
next_scenario = scenario(phase)
|
108
|
+
unless next_scenario.nil? || next_scenario.steps.empty?
|
109
|
+
yield next_scenario
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_hash
|
114
|
+
ret = { :phase => phase, :scenarios => {} }
|
115
|
+
@scenario_cache.each do |key, scenario|
|
116
|
+
ret[:scenarios][key] = scenario.to_hash
|
117
|
+
end
|
118
|
+
ret
|
119
|
+
end
|
120
|
+
|
121
|
+
def load_from_hash(hash)
|
122
|
+
unless @scenario_cache.empty?
|
123
|
+
raise "Some scenarios are already initialized: #{@scenario_cache.keys}"
|
124
|
+
end
|
125
|
+
|
126
|
+
self.phase = hash[:phase]
|
127
|
+
hash[:scenarios].each do |key, scenario_hash|
|
128
|
+
@scenario_cache[key] = Scenario.new_from_hash(scenario_hash)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def confirm_scenario(scenario)
|
133
|
+
decision = super(scenario)
|
134
|
+
# we have not asked the user already about next steps
|
135
|
+
if decision.nil? && @ask_to_confirm_update
|
136
|
+
response = reporter.ask_decision(<<-MESSAGE.strip_heredoc.strip)
|
137
|
+
The pre-update checks indicate that the system is ready for update.
|
138
|
+
It's recommended to perform a backup at this stage.
|
139
|
+
Confirm to continue with the modification part of the update
|
140
|
+
MESSAGE
|
141
|
+
if [:no, :quit].include?(response)
|
142
|
+
ask_to_quit
|
143
|
+
end
|
144
|
+
end
|
145
|
+
response
|
146
|
+
ensure
|
147
|
+
@ask_to_confirm_update = false
|
148
|
+
end
|
149
|
+
|
150
|
+
def phase=(phase)
|
151
|
+
raise "Unknown phase #{phase}" unless PHASES.include?(phase)
|
152
|
+
|
153
|
+
@phase = phase
|
154
|
+
end
|
155
|
+
end
|
156
|
+
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.6.
|
4
|
+
version: 1.6.5
|
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: 2024-04-
|
11
|
+
date: 2024-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
@@ -316,6 +316,7 @@ files:
|
|
316
316
|
- definitions/scenarios/restore.rb
|
317
317
|
- definitions/scenarios/self_upgrade.rb
|
318
318
|
- definitions/scenarios/services.rb
|
319
|
+
- definitions/scenarios/update.rb
|
319
320
|
- definitions/scenarios/upgrade_to_capsule_6_16.rb
|
320
321
|
- definitions/scenarios/upgrade_to_capsule_6_16_z.rb
|
321
322
|
- definitions/scenarios/upgrade_to_foreman_nightly.rb
|
@@ -346,6 +347,7 @@ files:
|
|
346
347
|
- lib/foreman_maintain/cli/self_upgrade_command.rb
|
347
348
|
- lib/foreman_maintain/cli/service_command.rb
|
348
349
|
- lib/foreman_maintain/cli/transform_clamp_options.rb
|
350
|
+
- lib/foreman_maintain/cli/update_command.rb
|
349
351
|
- lib/foreman_maintain/cli/upgrade_command.rb
|
350
352
|
- lib/foreman_maintain/concerns/base_database.rb
|
351
353
|
- lib/foreman_maintain/concerns/directory_marker.rb
|
@@ -391,6 +393,7 @@ files:
|
|
391
393
|
- lib/foreman_maintain/runner/stored_execution.rb
|
392
394
|
- lib/foreman_maintain/scenario.rb
|
393
395
|
- lib/foreman_maintain/top_level_modules.rb
|
396
|
+
- lib/foreman_maintain/update_runner.rb
|
394
397
|
- lib/foreman_maintain/upgrade_runner.rb
|
395
398
|
- lib/foreman_maintain/utils.rb
|
396
399
|
- lib/foreman_maintain/utils/backup.rb
|
@@ -433,7 +436,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
433
436
|
- !ruby/object:Gem::Version
|
434
437
|
version: '0'
|
435
438
|
requirements: []
|
436
|
-
rubygems_version: 3.3.
|
439
|
+
rubygems_version: 3.3.27
|
437
440
|
signing_key:
|
438
441
|
specification_version: 4
|
439
442
|
summary: Foreman maintenance tool belt
|