foreman_maintain 0.1.6 → 0.2.0

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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -10
  3. data/bin/foreman-maintain-rotate-tar +18 -0
  4. data/definitions/checks/backup/certs_tar_exist.rb +24 -0
  5. data/definitions/checks/backup/directory_ready.rb +21 -0
  6. data/definitions/checks/candlepin/db_up.rb +29 -0
  7. data/definitions/checks/check_epel_repository.rb +21 -0
  8. data/definitions/checks/foreman/db_up.rb +29 -0
  9. data/definitions/checks/hammer_ping.rb +3 -1
  10. data/definitions/checks/mongo/db_up.rb +29 -0
  11. data/definitions/checks/mongo/tools_installed.rb +31 -0
  12. data/definitions/checks/repositories/validate.rb +0 -3
  13. data/definitions/checks/root_user.rb +12 -0
  14. data/definitions/features/candlepin.rb +16 -0
  15. data/definitions/features/candlepin_database.rb +3 -1
  16. data/definitions/features/downstream.rb +21 -22
  17. data/definitions/features/foreman_database.rb +2 -0
  18. data/definitions/features/foreman_proxy.rb +70 -7
  19. data/definitions/features/foreman_server.rb +29 -0
  20. data/definitions/features/foreman_tasks.rb +5 -1
  21. data/definitions/features/hammer.rb +158 -3
  22. data/definitions/features/installer.rb +106 -0
  23. data/definitions/features/instance.rb +39 -0
  24. data/definitions/features/katello.rb +43 -0
  25. data/definitions/features/mongo.rb +159 -0
  26. data/definitions/features/pulp.rb +30 -0
  27. data/definitions/features/puppet.rb +21 -0
  28. data/definitions/features/puppet_server.rb +2 -6
  29. data/definitions/features/service.rb +134 -0
  30. data/definitions/features/sync_plans.rb +1 -1
  31. data/definitions/features/tar.rb +69 -0
  32. data/definitions/procedures/backup/accessibility_confirmation.rb +14 -0
  33. data/definitions/procedures/backup/clean.rb +16 -0
  34. data/definitions/procedures/backup/compress_data.rb +26 -0
  35. data/definitions/procedures/backup/config_files.rb +36 -0
  36. data/definitions/procedures/backup/metadata.rb +56 -0
  37. data/definitions/procedures/backup/offline/candlepin_db.rb +57 -0
  38. data/definitions/procedures/backup/offline/foreman_db.rb +57 -0
  39. data/definitions/procedures/backup/offline/mongo.rb +56 -0
  40. data/definitions/procedures/backup/online/candlepin_db.rb +20 -0
  41. data/definitions/procedures/backup/online/foreman_db.rb +20 -0
  42. data/definitions/procedures/backup/online/mongo.rb +21 -0
  43. data/definitions/procedures/backup/online/pg_global_objects.rb +23 -0
  44. data/definitions/procedures/backup/online/safety_confirmation.rb +25 -0
  45. data/definitions/procedures/backup/prepare_directory.rb +29 -0
  46. data/definitions/procedures/backup/pulp.rb +68 -0
  47. data/definitions/procedures/backup/snapshot/clean_mount.rb +24 -0
  48. data/definitions/procedures/backup/snapshot/logical_volume_confirmation.rb +47 -0
  49. data/definitions/procedures/backup/snapshot/mount_base.rb +27 -0
  50. data/definitions/procedures/backup/snapshot/mount_candlepin_db.rb +48 -0
  51. data/definitions/procedures/backup/snapshot/mount_foreman_db.rb +48 -0
  52. data/definitions/procedures/backup/snapshot/mount_mongo.rb +35 -0
  53. data/definitions/procedures/backup/snapshot/mount_pulp.rb +24 -0
  54. data/definitions/procedures/backup/snapshot/prepare_mount.rb +16 -0
  55. data/definitions/procedures/foreman_tasks/fetch_tasks_status.rb +1 -0
  56. data/definitions/procedures/hammer_setup.rb +4 -39
  57. data/definitions/procedures/installer/upgrade.rb +1 -21
  58. data/definitions/procedures/repositories/setup.rb +0 -4
  59. data/definitions/procedures/service/base.rb +31 -0
  60. data/definitions/procedures/service/disable.rb +14 -0
  61. data/definitions/procedures/service/enable.rb +14 -0
  62. data/definitions/procedures/service/list.rb +26 -0
  63. data/definitions/procedures/service/restart.rb +49 -0
  64. data/definitions/procedures/service/start.rb +14 -0
  65. data/definitions/procedures/service/status.rb +14 -0
  66. data/definitions/procedures/service/stop.rb +14 -0
  67. data/definitions/scenarios/backup.rb +242 -0
  68. data/definitions/scenarios/services.rb +156 -0
  69. data/definitions/scenarios/upgrade_to_satellite_6_2.rb +2 -2
  70. data/definitions/scenarios/upgrade_to_satellite_6_2_z.rb +2 -2
  71. data/definitions/scenarios/upgrade_to_satellite_6_3.rb +2 -2
  72. data/definitions/scenarios/upgrade_to_satellite_6_3_z.rb +2 -2
  73. data/definitions/scenarios/upgrade_to_satellite_6_4.rb +79 -0
  74. data/definitions/scenarios/upgrade_to_satellite_6_4_z.rb +79 -0
  75. data/lib/foreman_maintain.rb +5 -0
  76. data/lib/foreman_maintain/cli.rb +4 -0
  77. data/lib/foreman_maintain/cli/backup_command.rb +157 -0
  78. data/lib/foreman_maintain/cli/base.rb +18 -8
  79. data/lib/foreman_maintain/cli/service_command.rb +112 -0
  80. data/lib/foreman_maintain/cli/transform_clamp_options.rb +1 -1
  81. data/lib/foreman_maintain/concerns/base_database.rb +57 -5
  82. data/lib/foreman_maintain/concerns/hammer.rb +0 -9
  83. data/lib/foreman_maintain/concerns/metadata.rb +3 -1
  84. data/lib/foreman_maintain/concerns/reporter.rb +12 -0
  85. data/lib/foreman_maintain/concerns/system_helpers.rb +45 -2
  86. data/lib/foreman_maintain/detector.rb +3 -3
  87. data/lib/foreman_maintain/error.rb +12 -0
  88. data/lib/foreman_maintain/executable.rb +29 -6
  89. data/lib/foreman_maintain/feature.rb +15 -0
  90. data/lib/foreman_maintain/param.rb +4 -3
  91. data/lib/foreman_maintain/reporter.rb +6 -2
  92. data/lib/foreman_maintain/reporter/cli_reporter.rb +26 -10
  93. data/lib/foreman_maintain/runner.rb +26 -15
  94. data/lib/foreman_maintain/runner/execution.rb +5 -1
  95. data/lib/foreman_maintain/scenario.rb +11 -3
  96. data/lib/foreman_maintain/upgrade_runner.rb +0 -2
  97. data/lib/foreman_maintain/utils.rb +2 -2
  98. data/lib/foreman_maintain/utils/command_runner.rb +0 -2
  99. data/lib/foreman_maintain/utils/hash_tools.rb +21 -0
  100. data/lib/foreman_maintain/utils/mongo_core.rb +37 -0
  101. data/lib/foreman_maintain/version.rb +1 -1
  102. metadata +58 -8
  103. data/definitions/features/katello_service.rb +0 -118
  104. data/definitions/procedures/katello_service/restart.rb +0 -24
  105. data/definitions/procedures/katello_service/start.rb +0 -19
  106. data/definitions/procedures/katello_service/stop.rb +0 -17
  107. data/lib/foreman_maintain/utils/facter.rb +0 -21
  108. data/lib/foreman_maintain/utils/hammer.rb +0 -79
@@ -34,17 +34,16 @@ module ForemanMaintain
34
34
  end
35
35
 
36
36
  def reporter
37
- @reporter ||= ForemanMaintain::Reporter::CLIReporter.new(STDOUT,
38
- STDIN,
39
- :assumeyes => assumeyes?)
37
+ @reporter ||= ForemanMaintain.reporter
40
38
  end
41
39
 
42
- def run_scenario(scenarios)
40
+ def run_scenario(scenarios, rescue_scenario = nil)
43
41
  @runner ||=
44
42
  ForemanMaintain::Runner.new(reporter, scenarios,
45
- :assumeyes => assumeyes?,
46
- :whitelist => whitelist || [],
47
- :force => force?)
43
+ :assumeyes => option_wrapper('assumeyes?'),
44
+ :whitelist => option_wrapper('whitelist') || [],
45
+ :force => option_wrapper('force?'),
46
+ :rescue_scenario => rescue_scenario)
48
47
  runner.run
49
48
  end
50
49
 
@@ -101,7 +100,9 @@ module ForemanMaintain
101
100
  delete_duplicate_assumeyes_if_any
102
101
 
103
102
  option ['-y', '--assumeyes'], :flag,
104
- 'Automatically answer yes for all questions'
103
+ 'Automatically answer yes for all questions' do |assume|
104
+ ForemanMaintain.reporter.assumeyes = assume
105
+ end
105
106
 
106
107
  option(['-w', '--whitelist'], 'whitelist',
107
108
  'Comma-separated list of labels of steps to be skipped') do |whitelist|
@@ -113,9 +114,18 @@ module ForemanMaintain
113
114
  'Force steps that would be skipped as they were already run'
114
115
  end
115
116
 
117
+ def self.service_options
118
+ option '--exclude', 'EXCLUDE', 'A comma-separated list of services to skip'
119
+ option '--only', 'ONLY', 'A comma-separated list of services to include'
120
+ end
121
+
116
122
  def self.delete_duplicate_assumeyes_if_any
117
123
  declared_options.delete_if { |opt| opt.handles?('--assumeyes') }
118
124
  end
125
+
126
+ def option_wrapper(option)
127
+ respond_to?(option.to_sym) ? send(option) : false
128
+ end
119
129
  end
120
130
  end
121
131
  end
@@ -0,0 +1,112 @@
1
+ module ForemanMaintain
2
+ module Cli
3
+ class ServiceCommand < Base
4
+ extend Concerns::Finders
5
+
6
+ subcommand 'start', 'Start applicable services' do
7
+ service_options
8
+
9
+ def execute
10
+ scenario = Scenarios::ServiceStart.new(
11
+ :only => only,
12
+ :exclude => exclude
13
+ )
14
+
15
+ run_scenario(scenario)
16
+ exit runner.exit_code
17
+ end
18
+ end
19
+
20
+ subcommand 'stop', 'Stop applicable services' do
21
+ service_options
22
+
23
+ def execute
24
+ scenario = Scenarios::ServiceStop.new(
25
+ :only => only,
26
+ :exclude => exclude
27
+ )
28
+
29
+ run_scenario(scenario)
30
+ exit runner.exit_code
31
+ end
32
+ end
33
+
34
+ subcommand 'restart', 'Restart applicable services' do
35
+ service_options
36
+ if feature(:katello)
37
+ option ['-p', '--wait-for-hammer-ping'], :flag,
38
+ 'Wait for hammer ping to return successfully before terminating'
39
+ end
40
+
41
+ def execute
42
+ scenario = Scenarios::ServiceRestart.new(
43
+ :only => only,
44
+ :exclude => exclude,
45
+ :wait_for_hammer_ping => option_wrapper('wait_for_hammer_ping?')
46
+ )
47
+
48
+ run_scenario(scenario)
49
+ exit runner.exit_code
50
+ end
51
+ end
52
+
53
+ subcommand 'status', 'Get statuses of applicable services' do
54
+ service_options
55
+
56
+ def execute
57
+ scenario = Scenarios::ServiceStatus.new(
58
+ :only => only,
59
+ :exclude => exclude
60
+ )
61
+
62
+ run_scenario(scenario)
63
+ exit runner.exit_code
64
+ end
65
+ end
66
+
67
+ subcommand 'list', 'List applicable services' do
68
+ service_options
69
+
70
+ def execute
71
+ scenario = Scenarios::ServiceList.new(
72
+ :only => only,
73
+ :exclude => exclude,
74
+ :action => 'status'
75
+ )
76
+
77
+ run_scenario(scenario)
78
+ exit runner.exit_code
79
+ end
80
+ end
81
+
82
+ subcommand 'enable', 'Enable applicable services' do
83
+ service_options
84
+
85
+ def execute
86
+ scenario = Scenarios::ServiceEnable.new(
87
+ :only => only,
88
+ :exclude => exclude, :action => 'status'
89
+ )
90
+
91
+ run_scenario(scenario)
92
+ exit runner.exit_code
93
+ end
94
+ end
95
+
96
+ subcommand 'disable', 'Disable applicable services' do
97
+ service_options
98
+
99
+ def execute
100
+ scenario = Scenarios::ServiceDisable.new(
101
+ :only => only,
102
+ :exclude => exclude,
103
+ :action => 'status'
104
+ )
105
+
106
+ run_scenario(scenario)
107
+ exit runner.exit_code
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -26,7 +26,7 @@ module ForemanMaintain
26
26
  private
27
27
 
28
28
  def option_sym(option)
29
- option = option.switches.first[2..-1].to_s
29
+ option = underscorize(option.switches.first[2..-1].to_s)
30
30
  option.to_sym unless option.empty?
31
31
  end
32
32
 
@@ -1,10 +1,24 @@
1
1
  module ForemanMaintain
2
2
  module Concerns
3
3
  module BaseDatabase
4
+ def data_dir
5
+ '/var/lib/pgsql/data/'
6
+ end
7
+
4
8
  def configuration
5
9
  raise NotImplementedError
6
10
  end
7
11
 
12
+ def config_files
13
+ [
14
+ '/etc/systemd/system/postgresql.service'
15
+ ]
16
+ end
17
+
18
+ def local?(config = configuration)
19
+ ['localhost', '127.0.0.1', `hostname`.strip].include? config['host']
20
+ end
21
+
8
22
  def query(sql, config = configuration)
9
23
  parse_csv(query_csv(sql, config))
10
24
  end
@@ -15,14 +29,18 @@ module ForemanMaintain
15
29
 
16
30
  def psql(query, config = configuration)
17
31
  if ping(config)
18
- execute(psql_command(config), :stdin => query)
32
+ execute(psql_command(config),
33
+ :stdin => query,
34
+ :hidden_patterns => [config['password']])
19
35
  else
20
36
  raise_service_error
21
37
  end
22
38
  end
23
39
 
24
40
  def ping(config = configuration)
25
- execute?(psql_command(config), :stdin => 'SELECT 1 as ping')
41
+ execute?(psql_command(config),
42
+ :stdin => 'SELECT 1 as ping',
43
+ :hidden_patterns => [config['password']])
26
44
  end
27
45
 
28
46
  def backup_file_path(config = configuration)
@@ -30,19 +48,41 @@ module ForemanMaintain
30
48
  "#{backup_dir}/#{dump_file_name}.bz2"
31
49
  end
32
50
 
51
+ def dump_db(file, config = configuration)
52
+ execute!(dump_command(config) + " > #{file}", :hidden_patterns => [config['password']])
53
+ end
54
+
55
+ def backup_local(backup_file, extra_tar_options = {})
56
+ dir = extra_tar_options.fetch(:data_dir, data_dir)
57
+ FileUtils.cd(dir) do
58
+ tar_options = {
59
+ :archive => backup_file,
60
+ :command => 'create',
61
+ :transform => 's,^,var/lib/pgsql/data/,S'
62
+ }.merge(extra_tar_options)
63
+ feature(:tar).run(tar_options)
64
+ end
65
+ end
66
+
67
+ # TODO: refactor to use dump_db
33
68
  def backup_db_command(file_path, config = configuration)
34
69
  pg_dump_cmd = "pg_dump -Fc #{config['database']}"
35
70
  "runuser - postgres -c '#{pg_dump_cmd}' | bzip2 -9 > #{file_path}"
36
71
  end
37
72
 
73
+ # TODO: remove the backup file path tools from here. Lib Utils::Backup?
38
74
  def backup_dir
39
75
  @backup_dir ||= File.expand_path(ForemanMaintain.config.db_backup_dir)
40
76
  end
41
77
 
78
+ def backup_global_objects(file)
79
+ execute!("runuser - postgres -c 'pg_dumpall -g > #{file}'")
80
+ end
81
+
42
82
  def perform_backup(config = configuration)
43
83
  file_path = backup_file_path(config)
44
84
  backup_cmd = backup_db_command(file_path, config)
45
- execute!(backup_cmd)
85
+ execute!(backup_cmd, :hidden_patterns => [config['password']])
46
86
  puts "\n Note: Database backup file path - #{file_path}"
47
87
  puts "\n In case of any exception, use above dump file to restore DB."
48
88
  end
@@ -68,14 +108,26 @@ module ForemanMaintain
68
108
  end
69
109
  end
70
110
 
111
+ def find_base_directory(directory)
112
+ find_dir_containing_file(directory, 'postgresql.conf')
113
+ end
114
+
71
115
  private
72
116
 
73
- def psql_command(config)
117
+ def base_command(config, command = 'psql')
74
118
  "PGPASSWORD='#{config[%(password)]}' "\
75
- "psql -d #{config['database']} -h #{config['host'] || 'localhost'} "\
119
+ "#{command} -h #{config['host'] || 'localhost'} "\
76
120
  " -p #{config['port'] || '5432'} -U #{config['username']}"
77
121
  end
78
122
 
123
+ def psql_command(config)
124
+ base_command(config, 'psql') + " -d #{config['database']}"
125
+ end
126
+
127
+ def dump_command(config)
128
+ base_command(config, 'pg_dump') + " -Fc #{config['database']}"
129
+ end
130
+
79
131
  def raise_service_error
80
132
  raise Error::Fail, 'Please check whether database service is up & running state.'
81
133
  end
@@ -6,15 +6,6 @@ module ForemanMaintain
6
6
  preparation_steps { Procedures::HammerSetup.new }
7
7
  end
8
8
  end
9
-
10
- # Run a hammer command, examples:
11
- # hammer('host list')
12
- def hammer(args)
13
- Utils::Hammer.instance.run_command(args)
14
- end
15
-
16
- # TODO: method for specifying that the check that includes this method
17
- # requires hammer to be setup
18
9
  end
19
10
  end
20
11
  end
@@ -203,7 +203,9 @@ module ForemanMaintain
203
203
  def preparation_steps(recursion_depth = 0, trace = [])
204
204
  raise "Too many dependent steps #{trace}" if recursion_depth > MAX_PREPARATION_STEPS_DEPTH
205
205
  return @preparation_steps if defined?(@preparation_steps)
206
- preparation_steps = metadata[:preparation_steps_blocks].map(&:call)
206
+ preparation_steps = metadata[:preparation_steps_blocks].map do |block|
207
+ instance_exec(&block)
208
+ end.flatten.compact
207
209
  preparation_steps.each { |step| raise ArgumentError unless step.is_a?(Executable) }
208
210
  all_preparation_steps = []
209
211
  preparation_steps.each do |step|
@@ -0,0 +1,12 @@
1
+ module ForemanMaintain
2
+ module Concerns
3
+ module Reporter
4
+ extend Forwardable
5
+ def_delegators :reporter, :with_spinner, :puts, :print, :ask, :assumeyes?
6
+
7
+ def reporter
8
+ ForemanMaintain.reporter
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'csv'
3
+ require 'find'
3
4
  require 'shellwords'
4
5
 
5
6
  module ForemanMaintain
@@ -26,6 +27,19 @@ module ForemanMaintain
26
27
  end
27
28
  end
28
29
 
30
+ def systemd_installed?
31
+ File.exist?('/usr/bin/systemctl')
32
+ end
33
+
34
+ def service_exists?(service)
35
+ if systemd_installed?
36
+ systemd = execute("systemctl is-enabled #{service} 2>&1 | tail -1").strip
37
+ systemd == 'enabled' || systemd == 'disabled'
38
+ else
39
+ File.exist?("/etc/init.d/#{service}")
40
+ end
41
+ end
42
+
29
43
  def check_min_version(name, minimal_version)
30
44
  current_version = package_version(name)
31
45
  if current_version
@@ -38,8 +52,8 @@ module ForemanMaintain
38
52
  (execute('rpm -q foreman') =~ /sat.noarch/)
39
53
  end
40
54
 
41
- def execute?(command, input = nil)
42
- execute(command, :stdin => input)
55
+ def execute?(command, options = {})
56
+ execute(command, options)
43
57
  $CHILD_STATUS.success?
44
58
  end
45
59
 
@@ -153,6 +167,35 @@ module ForemanMaintain
153
167
  result = execute(cmd).strip
154
168
  result.split(/\n/)
155
169
  end
170
+
171
+ def directory_empty?(dir)
172
+ Dir.entries(dir).size <= 2
173
+ end
174
+
175
+ def get_lv_info(dir)
176
+ execute("findmnt -n --target #{dir} -o SOURCE,FSTYPE").split
177
+ end
178
+
179
+ def create_lv_snapshot(name, block_size, path)
180
+ execute!("lvcreate -n#{name} -L#{block_size} -s #{path}")
181
+ end
182
+
183
+ def get_lv_path(lv_name)
184
+ execute("lvs --noheadings -o lv_path -S lv_name=#{lv_name}").strip
185
+ end
186
+
187
+ def local_psql_database?
188
+ (feature(:foreman_database) && feature(:foreman_database).local?) ||
189
+ (feature(:candlepin_database) && feature(:candlepin_database).local?)
190
+ end
191
+
192
+ def find_dir_containing_file(directory, target)
193
+ result = nil
194
+ Find.find(directory) do |path|
195
+ result = File.dirname(path) if File.basename(path) == target
196
+ end
197
+ result
198
+ end
156
199
  end
157
200
  end
158
201
  end
@@ -58,7 +58,9 @@ module ForemanMaintain
58
58
  def available_scenarios(filter_conditions = nil)
59
59
  unless @available_scenarios
60
60
  ensure_features_detected
61
- @available_scenarios = @scenarios.select(&:present?).map(&:new)
61
+ @available_scenarios = @scenarios.select do |scenario|
62
+ scenario.present? && scenario.autodetect?
63
+ end.map(&:new)
62
64
  end
63
65
  filter(@available_scenarios, filter_conditions)
64
66
  end
@@ -104,7 +106,6 @@ module ForemanMaintain
104
106
  ret
105
107
  end
106
108
 
107
- # rubocop:disable Metrics/AbcSize
108
109
  def detect_feature(label)
109
110
  return @features_by_label[label] if @features_by_label.key?(label)
110
111
  return unless autodetect_features.key?(label)
@@ -122,7 +123,6 @@ module ForemanMaintain
122
123
  end
123
124
  present_feature
124
125
  end
125
- # rubocop:enable Metrics/AbcSize
126
126
 
127
127
  def autodetect_features
128
128
  @autodetect_features ||= Feature.sub_classes.reduce({}) do |hash, feature_class|
@@ -6,6 +6,12 @@ module ForemanMaintain
6
6
  class Warn < StandardError
7
7
  end
8
8
 
9
+ class Skip < StandardError
10
+ end
11
+
12
+ class Abort < StandardError
13
+ end
14
+
9
15
  class MultipleBeforeDetected < StandardError
10
16
  def initialize(step_labels)
11
17
  @step_labels = step_labels
@@ -38,5 +44,11 @@ module ForemanMaintain
38
44
  # Error caused by incorrect usage, usually connected to passed CLI options
39
45
  class UsageError < StandardError
40
46
  end
47
+
48
+ class Validation < StandardError
49
+ end
50
+ end
51
+
52
+ class HammerConfigurationError < StandardError
41
53
  end
42
54
  end