foreman_maintain 0.4.6 → 0.4.8

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