foreman_maintain 0.4.6 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ec1d3cb6c78f4404fb0983479df446a46a5814428842c630f9723be36e58863
4
- data.tar.gz: b156422372ca41f5ebec896fe24c929c96cef1577576f4abf768938b6776d910
3
+ metadata.gz: 0d748d16a88ff4ea39bdefe64acb950f12838579e8b32bf4077c2ce600ee69ee
4
+ data.tar.gz: fbbdc32ce0d5b282c3c330a7cd6660126f8b07ba732ed323f91f433141f7d306
5
5
  SHA512:
6
- metadata.gz: 2df8afaa92f8871b3f3b59db30ec321af277059f0631a3ad2a54f064bf5067463160a209b7d7c1bc6fb15b83b30ac15015977fdf96621200b0eec87d690bcfd1
7
- data.tar.gz: c30552fdc8e0c3ae64625d5504bbf894b134c50f77be98d3c42c3cfb751c61104f4ad391d88e4dc63b2b86163cb2b2a3e610e636d6be43d33253e463145e93dd
6
+ metadata.gz: 870a8eec52a19ce134968b45435b0913efc3e950ec9cba783528b8588b5830098bd48c864c6916a9bc3e378b57c7ac7056066323914c1beca5fccaa9237c257b
7
+ data.tar.gz: 0d9c910b5ec28449a47a89615e7df4d1665d178aa7c6b79c24f238ededc751b85a5582889cad8d1a8a235931bf909c136ce9d457d8be946ca9ffe77085c93cd4
@@ -1,7 +1,7 @@
1
1
  module Checks
2
2
  class VersionLockingEnabled < ForemanMaintain::Check
3
3
  metadata do
4
- description 'Check if tooling for package version locking is installed'
4
+ description 'Check if tooling for package locking is installed'
5
5
  end
6
6
 
7
7
  def run
@@ -24,7 +24,7 @@ class Features::Installer < ForemanMaintain::Feature
24
24
  end
25
25
 
26
26
  def configuration
27
- YAML.load_file(config_file)
27
+ @configuration ||= YAML.load_file(config_file)
28
28
  end
29
29
 
30
30
  def config_file
@@ -85,7 +85,9 @@ class Features::Installer < ForemanMaintain::Feature
85
85
  end
86
86
 
87
87
  def run(arguments = '', exec_options = {})
88
- execute!("LANG=en_US.utf-8 #{installer_command} #{arguments}".strip, exec_options)
88
+ out = execute!("LANG=en_US.utf-8 #{installer_command} #{arguments}".strip, exec_options)
89
+ @configuration = nil
90
+ out
89
91
  end
90
92
 
91
93
  def upgrade(exec_options = {})
@@ -103,6 +105,14 @@ class Features::Installer < ForemanMaintain::Feature
103
105
  feature(:installer).answers['foreman']['admin_password']
104
106
  end
105
107
 
108
+ def lock_package_versions?
109
+ !!(configuration[:custom] && configuration[:custom][:lock_package_versions])
110
+ end
111
+
112
+ def lock_package_versions_supported?
113
+ !(configuration[:custom] && configuration[:custom][:lock_package_versions]).nil?
114
+ end
115
+
106
116
  private
107
117
 
108
118
  def load_answers(config)
@@ -6,8 +6,7 @@ class Features::PackageManager < ForemanMaintain::Feature
6
6
  extend Forwardable
7
7
  def_delegators :manager, :lock_versions, :unlock_versions,
8
8
  :installed?, :find_installed_package, :install, :update,
9
- :version_locking_enabled?, :configure_version_locking,
10
- :foreman_related_packages, :version_locking_packages,
9
+ :version_locking_enabled?, :install_version_locking,
11
10
  :versions_locked?, :clean_cache, :remove, :files_not_owned_by_package
12
11
 
13
12
  def self.type
@@ -0,0 +1,15 @@
1
+ module Procedures::Installer
2
+ class Run < ForemanMaintain::Procedure
3
+ metadata do
4
+ param :arguments, 'Arguments passed to installer'
5
+ end
6
+
7
+ def run
8
+ feature(:installer).run(@arguments, :interactive => true)
9
+ end
10
+
11
+ def description
12
+ "Running #{feature(:installer).installer_command} #{@arguments}"
13
+ end
14
+ end
15
+ end
@@ -6,12 +6,7 @@ module Procedures::Packages
6
6
  end
7
7
 
8
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
9
+ feature(:package_manager).install_version_locking(:assumeyes => @assumeyes)
15
10
  end
16
11
  end
17
12
  end
@@ -1,16 +1,27 @@
1
1
  module Procedures::Packages
2
2
  class Install < ForemanMaintain::Procedure
3
3
  metadata do
4
+ description 'Install packages'
4
5
  param :packages, 'List of packages to install', :array => true
5
6
  param :assumeyes, 'Do not ask for confirmation'
7
+ param :force, 'Do not skip if package is installed', :flag => true, :default => false
8
+ param :warn_on_errors, 'Do not interrupt scenario on failure',
9
+ :flag => true, :default => false
6
10
  end
7
11
 
8
12
  def run
9
- packages_action(:install, @packages, :assumeyes => @assumeyes.nil? ? assumeyes? : @assumeyes)
13
+ assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
14
+ packages_action(:install, @packages, :assumeyes => assumeyes_val)
15
+ rescue ForemanMaintain::Error::ExecutionError => e
16
+ if @warn_on_errors
17
+ set_status(:warning, e.message)
18
+ else
19
+ raise
20
+ end
10
21
  end
11
22
 
12
23
  def necessary?
13
- @packages.any? { |package| package_version(package).nil? }
24
+ @force || @packages.any? { |package| package_version(package).nil? }
14
25
  end
15
26
 
16
27
  def runtime_message
@@ -0,0 +1,18 @@
1
+ module Procedures::Packages
2
+ class InstallerConfirmation < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Confirm installer run is allowed'
5
+ end
6
+
7
+ def run
8
+ question = "WARNING: This script runs #{feature(:installer).installer_command} " \
9
+ "after the yum execution \n" \
10
+ "to ensure the #{feature(:instance).product_name} " \
11
+ "is in a consistent state.\n" \
12
+ "As a result some of your services may be restarted. \n\n" \
13
+ 'Do you want to proceed?'
14
+ answer = ask_decision(question, 'y(yes), q(quit)')
15
+ abort! unless answer == :yes
16
+ end
17
+ end
18
+ end
@@ -2,16 +2,12 @@ module Procedures::Packages
2
2
  class LockVersions < ForemanMaintain::Procedure
3
3
  metadata do
4
4
  for_feature :package_manager
5
- description 'Lock versions of Foreman-related packages'
5
+ description 'Lock packages'
6
6
  preparation_steps { [Checks::VersionLockingEnabled.new] }
7
7
  end
8
8
 
9
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
10
+ feature(:package_manager).lock_versions
15
11
  end
16
12
  end
17
13
  end
@@ -2,15 +2,37 @@ module Procedures::Packages
2
2
  class LockingStatus < ForemanMaintain::Procedure
3
3
  metadata do
4
4
  for_feature :package_manager
5
- description 'Check status of version locking of Foreman-related packages'
5
+ description 'Check status of version locking of packages'
6
6
  preparation_steps { [Checks::VersionLockingEnabled.new] }
7
7
  end
8
8
 
9
9
  def run
10
+ check_automatic_locking
11
+ check_version_locked
12
+ end
13
+
14
+ private
15
+
16
+ def check_version_locked
10
17
  if feature(:package_manager).versions_locked?
11
- puts 'Packages are locked.'
18
+ puts ' Packages are locked.'
19
+ else
20
+ puts ' Packages are not locked.'
21
+ puts " WARNING: When locking is disabled there is a risk of unwanted update\n" \
22
+ " of #{feature(:instance).product_name}' and its components and possible " \
23
+ 'data inconsistency'
24
+ end
25
+ end
26
+
27
+ def check_automatic_locking
28
+ if feature(:installer).lock_package_versions_supported?
29
+ if feature(:installer).lock_package_versions?
30
+ puts ' Automatic locking of package versions is enabled in installer.'
31
+ else
32
+ puts ' Automatic locking of package versions is disabled in installer.'
33
+ end
12
34
  else
13
- puts 'Packages are not locked.'
35
+ puts ' Automatic locking of package versions is not supported by installer.'
14
36
  end
15
37
  end
16
38
  end
@@ -2,7 +2,7 @@ module Procedures::Packages
2
2
  class UnlockVersions < ForemanMaintain::Procedure
3
3
  metadata do
4
4
  for_feature :package_manager
5
- description 'Unlock versions of Foreman-related packages'
5
+ description 'Unlock packages'
6
6
  preparation_steps { [Checks::VersionLockingEnabled.new] }
7
7
  end
8
8
 
@@ -3,16 +3,25 @@ module Procedures::Packages
3
3
  metadata do
4
4
  param :packages, 'List of packages to update', :array => true
5
5
  param :assumeyes, 'Do not ask for confirmation'
6
+ param :force, 'Do not skip if package is installed', :flag => true, :default => false
7
+ param :warn_on_errors, 'Do not interrupt scenario on failure',
8
+ :flag => true, :default => false
6
9
  end
7
10
 
8
11
  def run
9
12
  assumeyes_val = @assumeyes.nil? ? assumeyes? : @assumeyes
10
13
  feature(:package_manager).clean_cache
11
14
  packages_action(:update, @packages, :assumeyes => assumeyes_val)
15
+ rescue ForemanMaintain::Error::ExecutionError => e
16
+ if @warn_on_errors
17
+ set_status(:warning, e.message)
18
+ else
19
+ raise
20
+ end
12
21
  end
13
22
 
14
23
  def necessary?
15
- @packages.any? { |package| package_version(package).nil? }
24
+ @force || @packages.any? { |package| package_version(package).nil? }
16
25
  end
17
26
 
18
27
  def description
@@ -0,0 +1,90 @@
1
+ module ForemanMaintain::Scenarios
2
+ module Packages
3
+ class Status < ForemanMaintain::Scenario
4
+ metadata do
5
+ label :packages_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 :packages_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 :packages_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
+
39
+ class Install < ForemanMaintain::Scenario
40
+ metadata do
41
+ description 'install packages in unlocked session'
42
+ param :packages, 'List of packages to install', :array => true
43
+ param :assumeyes, 'Do not ask for confirmation'
44
+ manual_detection
45
+ end
46
+
47
+ def compose
48
+ add_step_with_context(Procedures::Packages::InstallerConfirmation)
49
+ add_step_with_context(Procedures::Packages::UnlockVersions)
50
+ add_step_with_context(Procedures::Packages::Install,
51
+ :force => true, :warn_on_errors => true)
52
+ add_step_with_context(Procedures::Installer::Run,
53
+ :arguments => '--upgrade --disable-system-checks')
54
+ add_step(Procedures::Packages::LockingStatus)
55
+ end
56
+
57
+ def set_context_mapping
58
+ context.map(:packages,
59
+ Procedures::Packages::Install => :packages)
60
+ context.map(:assumeyes,
61
+ Procedures::Packages::Install => :assumeyes)
62
+ end
63
+ end
64
+
65
+ class Update < ForemanMaintain::Scenario
66
+ metadata do
67
+ description 'update packages in unlocked session'
68
+ param :packages, 'List of packages to Update', :array => true
69
+ param :assumeyes, 'Do not ask for confirmation'
70
+ manual_detection
71
+ end
72
+
73
+ def compose
74
+ add_step_with_context(Procedures::Packages::InstallerConfirmation)
75
+ add_step_with_context(Procedures::Packages::UnlockVersions)
76
+ add_step_with_context(Procedures::Packages::Update, :force => true, :warn_on_errors => true)
77
+ add_step_with_context(Procedures::Installer::Run,
78
+ :arguments => '--upgrade --disable-system-checks')
79
+ add_step(Procedures::Packages::LockingStatus)
80
+ end
81
+
82
+ def set_context_mapping
83
+ context.map(:packages,
84
+ Procedures::Packages::Update => :packages)
85
+ context.map(:assumeyes,
86
+ Procedures::Packages::Update => :assumeyes)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+ function quit_if_in_maintenance_mode {
3
+ /usr/bin/foreman-maintain maintenance-mode is-enabled
4
+ if [ $? -eq 0 ]
5
+ then
6
+ echo "Maintenance mode is on can not continue"
7
+ exit 1
8
+ fi
9
+ }
10
+
11
+ function is_maintenance_mode_enabled {
12
+ /usr/bin/foreman-maintain maintenance-mode is-enabled
13
+ echo $?
14
+ }
@@ -0,0 +1,3 @@
1
+ [main]
2
+ enabled = 0
3
+ whitelist = /etc/yum/pluginconf.d/foreman-protector.whitelist
@@ -0,0 +1,85 @@
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, 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 update%s due to foreman-protector. \n'
81
+ 'Use foreman-maintain packages install/update <package> \n'
82
+ 'to safely install packages without restrictions.\n'
83
+ % (total, suffix))
84
+
85
+ _add_package_whitelist_excluders(conduit)
@@ -0,0 +1,19 @@
1
+ # list of packages allowed to be installed and updated freely
2
+ # foreman-maintain runtime installed deps
3
+ # fio and deps
4
+ fio
5
+ libaio
6
+ libibverbs
7
+ librbd1
8
+ libpmem
9
+ numactl-libs
10
+ ndctl-libs
11
+ daxctl-libs
12
+ libpmemblk
13
+ librados2
14
+ librdmacm
15
+ rdma-core
16
+ boost-random
17
+ boost-iostreams
18
+ # foreman-maintain
19
+ rubygem-foreman_maintain
@@ -0,0 +1,3 @@
1
+ # Configuration file /etc/cron.d/passenger-recycler to run passenger-recycler
2
+ # every 15 minutes.
3
+ */15 * * * * root /usr/bin/passenger-recycler
@@ -1,32 +1,60 @@
1
1
  module ForemanMaintain
2
2
  module Cli
3
3
  class PackagesCommand < Base
4
- subcommand 'lock', 'Prevent Foreman-related packages from automatic update' do
4
+ subcommand 'lock', 'Prevent packages from automatic update' do
5
5
  interactive_option
6
6
  def execute
7
- run_scenarios_and_exit(Scenarios::VersionLocking::Lock.new)
7
+ run_scenarios_and_exit(Scenarios::Packages::Lock.new)
8
8
  end
9
9
  end
10
10
 
11
- subcommand 'unlock', 'Enable Foreman-related packages for automatic update' do
11
+ subcommand 'unlock', 'Enable packages for automatic update' do
12
12
  interactive_option
13
13
  def execute
14
- run_scenarios_and_exit(Scenarios::VersionLocking::Unlock.new)
14
+ run_scenarios_and_exit(Scenarios::Packages::Unlock.new)
15
15
  end
16
16
  end
17
17
 
18
- subcommand 'status', 'Check if Foreman-related packages are protected against update' do
18
+ subcommand 'status', 'Check if packages are protected against update' do
19
19
  interactive_option
20
20
  def execute
21
- run_scenarios_and_exit(Scenarios::VersionLocking::Status.new)
21
+ run_scenarios_and_exit(Scenarios::Packages::Status.new)
22
22
  end
23
23
  end
24
24
 
25
- subcommand 'is-locked', 'Check if update of Foreman-related packages is allowed' do
25
+ subcommand 'install', 'Install packages in an unlocked session' do
26
+ interactive_option
27
+ parameter 'PACKAGES ...', 'packages to install', :attribute_name => :packages
28
+
29
+ def execute
30
+ run_scenarios_and_exit(
31
+ Scenarios::Packages::Install.new(
32
+ :packages => packages,
33
+ :assumeyes => assumeyes?
34
+ )
35
+ )
36
+ end
37
+ end
38
+
39
+ subcommand 'update', 'Update packages in an unlocked session' do
40
+ interactive_option
41
+ parameter 'PACKAGES ...', 'packages to update', :attribute_name => :packages
42
+
43
+ def execute
44
+ run_scenarios_and_exit(
45
+ Scenarios::Packages::Update.new(
46
+ :packages => packages,
47
+ :assumeyes => assumeyes?
48
+ )
49
+ )
50
+ end
51
+ end
52
+
53
+ subcommand 'is-locked', 'Check if update of packages is allowed' do
26
54
  interactive_option
27
55
  def execute
28
56
  locked = feature(:package_manager).versions_locked?
29
- puts "Foreman related packages are#{locked ? '' : ' not'} locked"
57
+ puts "Packages are#{locked ? '' : ' not'} locked"
30
58
  exit_code = locked ? 0 : 1
31
59
  exit exit_code
32
60
  end
@@ -21,7 +21,7 @@ module ForemanMaintain
21
21
  subcommand 'service', 'Control applicable services', ServiceCommand
22
22
  subcommand 'backup', 'Backup server', BackupCommand
23
23
  subcommand 'restore', 'Restore a backup', RestoreCommand
24
- subcommand 'packages', 'Lock/Unlock installed packages', PackagesCommand
24
+ subcommand 'packages', 'Lock/Unlock package protection, install, update', PackagesCommand
25
25
  subcommand 'advanced', 'Advanced tools for server maintenance', AdvancedCommand
26
26
  subcommand 'maintenance-mode', 'Control maintenance-mode for application',
27
27
  MaintenanceModeCommand
@@ -1,23 +1,13 @@
1
1
  module ForemanMaintain::PackageManager
2
2
  # rubocop:disable Lint/UnusedMethodArgument
3
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
4
  # check tools are installed and enabled
14
5
  def version_locking_enabled?
15
6
  raise NotImplementedError
16
7
  end
17
8
 
18
9
  # make sure the version locking tools are configured
19
- # we can assume it is already installed
20
- def configure_version_locking
10
+ def install_version_locking(assumeyes: false)
21
11
  raise NotImplementedError
22
12
  end
23
13
 
@@ -46,8 +36,8 @@ module ForemanMaintain::PackageManager
46
36
  raise NotImplementedError
47
37
  end
48
38
 
49
- # prevent listed packages from update
50
- def lock_versions(package_list)
39
+ # prevent selected packages from update or install
40
+ def lock_versions
51
41
  raise NotImplementedError
52
42
  end
53
43
 
@@ -1,77 +1,36 @@
1
1
  module ForemanMaintain::PackageManager
2
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
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
+ PROTECTOR_PLUGIN_FILE = '/usr/lib/yum-plugins/foreman-protector.py'.freeze
7
6
 
8
7
  def self.parse_envra(envra)
9
8
  # envra format: 0:foreman-1.20.1.10-1.el7sat.noarch
10
9
  parsed = envra.match(/\d*:?(?<name>.*)-[^-]+-[^-]+\.[^.]+/)
11
- parsed ? Hash[parsed.names.zip(parsed.captures)].merge(:envra => envra) : nil
10
+ parsed ? Hash[parsed.names.map(&:to_sym).zip(parsed.captures)].merge(:envra => envra) : nil
12
11
  end
13
12
 
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
13
+ def lock_versions
14
+ enable_protector
36
15
  end
37
16
 
38
17
  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 }
18
+ disable_protector
43
19
  end
44
20
 
45
21
  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)
22
+ !!(protector_config =~ /^\s*enabled\s*=\s*1/)
50
23
  end
51
24
 
52
25
  def version_locking_enabled?
53
- installed?(version_locking_packages) && versionlock_config =~ /^\s*enabled\s+=\s+1/ \
54
- && File.exist?(versionlock_file)
26
+ File.exist?(PROTECTOR_PLUGIN_FILE) && File.exist?(PROTECTOR_CONFIG_FILE) &&
27
+ File.exist?(PROTECTOR_WHITELIST_FILE)
55
28
  end
56
29
 
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)
30
+ def install_version_locking(*)
31
+ install_extras('foreman_protector/foreman-protector.py', PROTECTOR_PLUGIN_FILE)
32
+ install_extras('foreman_protector/foreman-protector.conf', PROTECTOR_CONFIG_FILE)
33
+ install_extras('foreman_protector/foreman-protector.whitelist', PROTECTOR_WHITELIST_FILE)
75
34
  end
76
35
 
77
36
  def installed?(packages)
@@ -109,17 +68,32 @@ module ForemanMaintain::PackageManager
109
68
 
110
69
  private
111
70
 
112
- def versionlock_config
113
- File.exist?(versionlock_config_file) ? File.read(versionlock_config_file) : ''
71
+ def protector_config
72
+ File.exist?(protector_config_file) ? File.read(protector_config_file) : ''
114
73
  end
115
74
 
116
- def versionlock_config_file
117
- VERSIONLOCK_CONFIG_FILE
75
+ def protector_config_file
76
+ PROTECTOR_CONFIG_FILE
118
77
  end
119
78
 
120
- def versionlock_file
121
- result = versionlock_config.match(/^\s*locklist\s*=\s*(\S+)/)
122
- result.nil? ? nil : File.expand_path(result.captures[0])
79
+ def enable_protector
80
+ setup_protector(true)
81
+ end
82
+
83
+ def disable_protector
84
+ setup_protector(false)
85
+ end
86
+
87
+ def setup_protector(enabled)
88
+ config = protector_config
89
+ config += "\n" unless config[-1] == "\n"
90
+ enabled_re = /^\s*enabled\s*=.*$/
91
+ if enabled_re.match(config)
92
+ config = config.gsub(enabled_re, "enabled = #{enabled ? '1' : '0'}")
93
+ else
94
+ config += "enabled = #{enabled ? '1' : '0'}\n"
95
+ end
96
+ File.open(protector_config_file, 'w') { |file| file.puts config }
123
97
  end
124
98
 
125
99
  def yum_action(action, packages, assumeyes: false)
@@ -131,5 +105,14 @@ module ForemanMaintain::PackageManager
131
105
  sys.execute!("yum#{yum_options_s} #{action}#{packages_s}",
132
106
  :interactive => true)
133
107
  end
108
+
109
+ def install_extras(src, dest, override: false)
110
+ extras_src = File.expand_path('../../../../extras', __FILE__)
111
+ if override ||
112
+ (File.directory?(dest) && !File.exist?(File.join(dest, src))) ||
113
+ !File.exist?(dest)
114
+ FileUtils.cp(File.join(extras_src, src), dest)
115
+ end
116
+ end
134
117
  end
135
118
  end
@@ -16,6 +16,7 @@ module ForemanMaintain
16
16
  @scenarios = Array(scenarios)
17
17
  @quit = false
18
18
  @last_scenario = nil
19
+ @last_scenario_continuation_confirmed = false
19
20
  @exit_code = 0
20
21
  end
21
22
 
@@ -40,18 +41,19 @@ module ForemanMaintain
40
41
  end
41
42
  end
42
43
 
43
- def run_scenario(scenario, confirm = true)
44
+ def run_scenario(scenario)
44
45
  return if scenario.steps.empty?
45
46
  raise 'The runner is already in quit state' if quit?
46
47
 
47
- if confirm
48
- confirm_scenario(scenario)
49
- return if quit?
50
- end
48
+ confirm_scenario(scenario)
49
+ return if quit?
51
50
 
52
51
  execute_scenario_steps(scenario)
53
52
  ensure
54
- @last_scenario = scenario unless scenario.steps.empty?
53
+ unless scenario.steps.empty?
54
+ @last_scenario = scenario
55
+ @last_scenario_continuation_confirmed = false
56
+ end
55
57
  @exit_code = 1 if scenario.failed?
56
58
  end
57
59
 
@@ -60,12 +62,13 @@ module ForemanMaintain
60
62
  end
61
63
 
62
64
  def confirm_scenario(scenario)
63
- return unless @last_scenario
65
+ return if @last_scenario.nil? || @last_scenario_continuation_confirmed
64
66
 
65
67
  decision = if @last_scenario.steps_with_error(:whitelisted => false).any? ||
66
68
  @last_scenario.steps_with_abort(:whitelisted => false).any?
67
69
  :quit
68
70
  elsif @last_scenario.steps_with_warning(:whitelisted => false).any?
71
+ @last_scenario_continuation_confirmed = true
69
72
  reporter.ask_decision("Continue with [#{scenario.description}]")
70
73
  end
71
74
 
@@ -94,7 +97,7 @@ module ForemanMaintain
94
97
 
95
98
  def execute_scenario_steps(scenario, force = false)
96
99
  scenario.before_scenarios.flatten.each { |before_scenario| run_scenario(before_scenario) }
97
- confirm_scenario(scenario) if @rescue_scenario
100
+ confirm_scenario(scenario)
98
101
  return if !force && quit? # the before scenarios caused the stop of the execution
99
102
 
100
103
  @reporter.before_scenario_starts(scenario)
@@ -135,7 +135,7 @@ module ForemanMaintain
135
135
  confirm_scenario(scenario)
136
136
  return if quit?
137
137
  self.phase = phase
138
- run_scenario(scenario, false)
138
+ run_scenario(scenario)
139
139
  # if we started from the :pre_upgrade_checks, ensure to ask before
140
140
  # continuing with the rest of the upgrade
141
141
  @ask_to_confirm_upgrade = phase == :pre_upgrade_checks
@@ -155,12 +155,15 @@ module ForemanMaintain
155
155
 
156
156
  private
157
157
 
158
+ # rubocop:disable Metrics/MethodLength
158
159
  def rollback_pre_migrations
159
160
  raise "Unexpected phase #{phase}, expecting pre_migrations" unless phase == :pre_migrations
160
161
  rollback_needed = scenario(:pre_migrations).steps.any? { |s| s.executed? && s.success? }
161
162
  if rollback_needed
162
163
  @quit = false
163
- @last_scenario = nil # to prevent the unnecessary confirmation questions
164
+ # prevent the unnecessary confirmation questions
165
+ @last_scenario = nil
166
+ @last_scenario_continuation_confirmed = true
164
167
  [:post_migrations, :post_upgrade_checks].each do |phase|
165
168
  if quit? && phase == :post_upgrade_checks
166
169
  self.phase = :pre_migrations
@@ -174,6 +177,7 @@ module ForemanMaintain
174
177
  The upgrade failed and system was restored to pre-upgrade state.
175
178
  MESSAGE
176
179
  end
180
+ # rubocop:enable Metrics/MethodLength
177
181
 
178
182
  def with_non_empty_scenario(phase)
179
183
  next_scenario = scenario(phase)
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '0.4.6'.freeze
2
+ VERSION = '0.4.8'.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: 0.4.6
4
+ version: 0.4.8
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-08-29 00:00:00.000000000 Z
11
+ date: 2019-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -219,6 +219,7 @@ files:
219
219
  - definitions/procedures/foreman_tasks/resume.rb
220
220
  - definitions/procedures/foreman_tasks/ui_investigate.rb
221
221
  - definitions/procedures/hammer_setup.rb
222
+ - definitions/procedures/installer/run.rb
222
223
  - definitions/procedures/installer/upgrade.rb
223
224
  - definitions/procedures/iptables/add_maintenance_mode_chain.rb
224
225
  - definitions/procedures/iptables/remove_maintenance_mode_chain.rb
@@ -226,6 +227,7 @@ files:
226
227
  - definitions/procedures/maintenance_mode/is_enabled.rb
227
228
  - definitions/procedures/packages/enable_version_locking.rb
228
229
  - definitions/procedures/packages/install.rb
230
+ - definitions/procedures/packages/installer_confirmation.rb
229
231
  - definitions/procedures/packages/lock_versions.rb
230
232
  - definitions/procedures/packages/locking_status.rb
231
233
  - definitions/procedures/packages/unlock_versions.rb
@@ -261,6 +263,7 @@ files:
261
263
  - definitions/procedures/sync_plans/enable.rb
262
264
  - definitions/scenarios/backup.rb
263
265
  - definitions/scenarios/maintenance_mode.rb
266
+ - definitions/scenarios/packages.rb
264
267
  - definitions/scenarios/restore.rb
265
268
  - definitions/scenarios/services.rb
266
269
  - definitions/scenarios/upgrade_to_satellite_6_2.rb
@@ -273,7 +276,11 @@ files:
273
276
  - definitions/scenarios/upgrade_to_satellite_6_5_z.rb
274
277
  - definitions/scenarios/upgrade_to_satellite_6_6.rb
275
278
  - definitions/scenarios/upgrade_to_satellite_6_6_z.rb
276
- - definitions/scenarios/version_locking.rb
279
+ - extras/foreman-maintain.sh
280
+ - extras/foreman_protector/foreman-protector.conf
281
+ - extras/foreman_protector/foreman-protector.py
282
+ - extras/foreman_protector/foreman-protector.whitelist
283
+ - extras/passenger-recycler.cron
277
284
  - lib/foreman_maintain.rb
278
285
  - lib/foreman_maintain/check.rb
279
286
  - lib/foreman_maintain/cli.rb
@@ -1,39 +0,0 @@
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