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
@@ -17,12 +17,73 @@ class Features::ForemanProxy < ForemanMaintain::Feature
17
17
  dhcp_req_pass? && !syntax_error_exists?
18
18
  end
19
19
 
20
+ def services
21
+ {
22
+ 'foreman-proxy' => 20,
23
+ 'smart_proxy_dynflow_core' => 20
24
+ }
25
+ end
26
+
27
+ def features
28
+ # TODO: handle failures
29
+ run_curl_cmd("#{curl_cmd}/features").result
30
+ end
31
+
32
+ def internal?
33
+ !!feature(:foreman_server)
34
+ end
35
+
36
+ def config_files(for_features = ['all'])
37
+ configs = [
38
+ '/etc/foreman-proxy',
39
+ '/usr/share/foreman-proxy/.ssh/',
40
+ '/etc/smart_proxy_dynflow_core/settings.yml',
41
+ '/etc/sudoers.d/foreman-proxy'
42
+ ]
43
+ backup_features = backup_features(for_features)
44
+
45
+ configs.push(certs_tar) if certs_tar
46
+
47
+ configs.push('/var/lib/tftpboot') if backup_features.include?('tftp')
48
+ configs += ['/var/named/', '/etc/named*'] if backup_features.include?('dns')
49
+ configs += ['/var/lib/dhcpd', '/etc/dhcp'] if backup_features.include?('dhcp')
50
+ configs.push('/usr/share/xml/scap') if backup_features.include?('openscap')
51
+ configs
52
+ end
53
+
54
+ def content_module
55
+ return @content_module if @content_module_detected
56
+ @content_module_detected = true
57
+ answer = feature(:installer).answers.find do |_, config|
58
+ config.is_a?(Hash) && config.key?('certs_tar')
59
+ end
60
+ @content_module = answer.nil? ? 'foreman_proxy_content' : answer.first
61
+ logger.debug("foreman proxy content module detected: #{@content_module}")
62
+ @content_module
63
+ end
64
+
65
+ def certs_tar
66
+ feature(:installer).answers[content_module]['certs_tar'] if content_module
67
+ end
68
+
20
69
  private
21
70
 
22
- def dhcp_curl_cmd
71
+ def backup_features(for_features)
72
+ full_features = features
73
+ backup_features = for_features.include?('all') ? full_features : (full_features & for_features)
74
+ logger.info("Proxy features: #{full_features}")
75
+ logger.info("Proxy features to backup: #{backup_features}")
76
+ backup_features
77
+ end
78
+
79
+ def curl_cmd
23
80
  "curl -w '\n%{http_code}' --silent -ks --cert #{cert_path}/client_cert.pem \
24
81
  --key #{cert_path}/client_key.pem \
25
- --cacert #{cert_path}/proxy_ca.pem https://$(hostname):9090/dhcp"
82
+ --cacert #{cert_path}/proxy_ca.pem https://$(hostname):9090"
83
+ end
84
+
85
+ def dhcp_curl_cmd
86
+ "#{curl_cmd}/dhcp"
26
87
  end
27
88
 
28
89
  def find_http_error_msg(array_output, curl_http_status)
@@ -34,13 +95,15 @@ class Features::ForemanProxy < ForemanMaintain::Feature
34
95
  next unless str.include?('HTTP')
35
96
  http_line = str
36
97
  end
37
- return http_line if http_line.empty?
38
- http_line.split(curl_http_status.to_s).last.strip
98
+ msg = http_line.split(curl_http_status.to_s).last
99
+ msg = msg.strip unless msg.nil?
100
+ msg
39
101
  end
40
102
  end
41
103
 
42
- def run_dhcp_curl
43
- curl_resp = execute(dhcp_curl_cmd)
104
+ def run_curl_cmd(cmd)
105
+ # TODO: consider Net::HTTP instead of curl
106
+ curl_resp = execute(cmd)
44
107
  array_output = curl_resp.split(/\r?\n/)
45
108
  status_str = array_output.last
46
109
  curl_http_status = (status_str ? status_str.strip : status_str).to_i
@@ -53,7 +116,7 @@ class Features::ForemanProxy < ForemanMaintain::Feature
53
116
  end
54
117
 
55
118
  def dhcp_req_pass?
56
- dhcp_curl_resp = run_dhcp_curl
119
+ dhcp_curl_resp = run_curl_cmd(dhcp_curl_cmd)
57
120
  success = true
58
121
  if dhcp_curl_resp.http_code.eql?(200)
59
122
  if dhcp_curl_resp.result.to_s.empty?
@@ -7,6 +7,35 @@ module ForemanMaintain
7
7
  server?
8
8
  end
9
9
  end
10
+
11
+ def services
12
+ {
13
+ 'postgresql' => 5,
14
+ 'httpd' => 30
15
+ }
16
+ end
17
+
18
+ def plugins
19
+ list_cmd = "export RUBYOPT='-W0'; foreman-rake plugin:list| grep 'Foreman plugin: '"
20
+ plugin_list = execute(list_cmd).lines
21
+ plugin_list.map do |line|
22
+ plugin = line.split
23
+ "#{plugin[2].chop}-#{plugin[3].chop}"
24
+ end
25
+ end
26
+
27
+ def config_files
28
+ [
29
+ '/etc/httpd',
30
+ '/var/www/html/pub',
31
+ '/etc/squid',
32
+ '/etc/foreman',
33
+ '/etc/selinux/targeted/contexts/files/file_contexts.subs',
34
+ '/etc/sysconfig/foreman',
35
+ '/usr/share/ruby/vendor_ruby/puppet/reports/foreman.rb',
36
+ '/var/lib/foreman'
37
+ ]
38
+ end
10
39
  end
11
40
  end
12
41
  end
@@ -95,7 +95,7 @@ class Features::ForemanTasks < ForemanMaintain::Feature
95
95
  end
96
96
 
97
97
  def resume_task_using_hammer
98
- hammer('task resume')
98
+ feature(:hammer).run('task resume')
99
99
  end
100
100
 
101
101
  def fetch_tasks_status(state, spinner)
@@ -107,6 +107,10 @@ class Features::ForemanTasks < ForemanMaintain::Feature
107
107
  puts "\nTimeout: #{e.message}. Try again."
108
108
  end
109
109
 
110
+ def services
111
+ { 'foreman-tasks' => 30 }
112
+ end
113
+
110
114
  private
111
115
 
112
116
  def check_task_count(state, spinner)
@@ -1,6 +1,14 @@
1
+ require 'uri'
2
+
1
3
  class Features::Hammer < ForemanMaintain::Feature
4
+ attr_reader :configuration, :config_files
5
+
2
6
  metadata do
3
7
  label :hammer
8
+ confine do
9
+ # FIXME: How does this run on proxy?
10
+ find_package('rubygem-hammer_cli') || find_package('tfm-rubygem-hammer_cli')
11
+ end
4
12
  end
5
13
 
6
14
  SERVICES_MAPPING = {
@@ -11,6 +19,32 @@ class Features::Hammer < ForemanMaintain::Feature
11
19
  'foreman_tasks' => %w[foreman-tasks]
12
20
  }.freeze
13
21
 
22
+ def initialize
23
+ @configuration = { :foreman => {} }
24
+ @config_files = []
25
+ @ready = nil
26
+ load_configuration
27
+ end
28
+
29
+ def config_directories
30
+ [
31
+ '~/.hammer/',
32
+ '/etc/hammer/'
33
+ ]
34
+ end
35
+
36
+ def setup_admin_access
37
+ return true if check_connection
38
+ logger.info('Hammer setup is not valid. Fixing configuration.')
39
+ custom_config = { :foreman => { :username => 'admin' } }
40
+ custom_config = on_invalid_host(custom_config)
41
+ custom_config = on_missing_password(custom_config) # get password from answers
42
+ custom_config = on_invalid_password(custom_config) # get password from answers
43
+ ask_password_and_check(custom_config) unless ready?
44
+ config_error unless ready?
45
+ ready?
46
+ end
47
+
14
48
  def hammer_ping_cmd
15
49
  cmd_output = exec_hammer_cmd('--output json ping', true)
16
50
  return init_result_obj(false, cmd_output) if cmd_output.is_a?(String)
@@ -21,6 +55,88 @@ class Features::Hammer < ForemanMaintain::Feature
21
55
  init_result_obj(false, msg_to_show, services)
22
56
  end
23
57
 
58
+ def ready?
59
+ setup_admin_access if @ready.nil?
60
+ @ready
61
+ end
62
+
63
+ def check_connection
64
+ @ready = _check_connection
65
+ end
66
+
67
+ def server_uri
68
+ "https://#{hostname}/"
69
+ end
70
+
71
+ def custom_config_file
72
+ fm_config_dir = File.dirname(ForemanMaintain.config_file)
73
+ File.join(fm_config_dir, 'foreman-maintain-hammer.yml')
74
+ end
75
+
76
+ def command_base
77
+ if File.exist?(custom_config_file)
78
+ %(RUBYOPT='-W0' LANG=en_US.utf-8 hammer -c "#{custom_config_file}" --interactive=no)
79
+ else
80
+ %(RUBYOPT='-W0' LANG=en_US.utf-8 hammer --interactive=no)
81
+ end
82
+ end
83
+
84
+ # Run a hammer command, examples:
85
+ # run('host list')
86
+ def run(args)
87
+ setup_admin_access
88
+ execute("#{command_base} #{args}")
89
+ end
90
+
91
+ private
92
+
93
+ def on_invalid_host(custom_config)
94
+ hammer_host = URI.parse(configuration[:foreman][:host]).host if configuration[:foreman][:host]
95
+ if hammer_host != hostname
96
+ logger.info("Matching hostname was not found in hammer configs. Using #{server_uri}")
97
+ custom_config[:foreman][:host] = server_uri
98
+ end
99
+ custom_config
100
+ end
101
+
102
+ def on_invalid_password(custom_config)
103
+ if !ready? && custom_config[:foreman][:password].nil?
104
+ msg = 'Invalid admin password was found in hammer configs. Looking into installer answers'
105
+ logger.info(msg)
106
+ custom_config[:foreman][:password] = password_from_answers
107
+ save_config_and_check(custom_config)
108
+ end
109
+ custom_config
110
+ end
111
+
112
+ def ask_password_and_check(custom_config)
113
+ custom_config[:foreman][:password] = ask('Hammer admin password:', :password => true)
114
+ save_config_and_check(custom_config)
115
+ custom_config
116
+ end
117
+
118
+ def config_error
119
+ raise ForemanMaintain::HammerConfigurationError, 'Hammer configuration failed: '\
120
+ "Is the admin password correct? (it was stored in #{custom_config_file})" \
121
+ 'Is the server down?'
122
+ end
123
+
124
+ def on_missing_password(custom_config)
125
+ if admin_password_missing?
126
+ msg = 'Admin password was not found in hammer configs. Looking into installer answers'
127
+ logger.info(msg)
128
+ custom_config[:foreman][:password] = password_from_answers
129
+ end
130
+ save_config_and_check(custom_config)
131
+ custom_config
132
+ end
133
+
134
+ def admin_password_missing?
135
+ configuration[:foreman][:password].nil? ||
136
+ configuration[:foreman][:password].empty? ||
137
+ configuration[:foreman][:username] != 'admin'
138
+ end
139
+
24
140
  def find_resources_which_failed(hammer_ping_output)
25
141
  resources_failed = []
26
142
  hammer_ping_output.each do |resource, resp_obj|
@@ -29,8 +145,6 @@ class Features::Hammer < ForemanMaintain::Feature
29
145
  resources_failed
30
146
  end
31
147
 
32
- private
33
-
34
148
  def map_resources_with_services(resources)
35
149
  service_names = []
36
150
  resources.each do |resource|
@@ -48,8 +162,49 @@ class Features::Hammer < ForemanMaintain::Feature
48
162
  end
49
163
 
50
164
  def exec_hammer_cmd(cmd, required_json = false)
51
- response = ForemanMaintain::Utils::Hammer.instance.run_command(cmd)
165
+ response = run(cmd)
52
166
  json_str = parse_json(response) if required_json
53
167
  json_str ? json_str : response
54
168
  end
169
+
170
+ def load_configuration
171
+ config_directories.reverse.each do |path|
172
+ full_path = File.expand_path path
173
+ next unless File.directory? full_path
174
+ load_from_file(File.join(full_path, 'cli_config.yml'))
175
+ load_from_file(File.join(full_path, 'defaults.yml'))
176
+ # load config for modules
177
+ Dir.glob(File.join(full_path, 'cli.modules.d/*.yml')).sort.each do |f|
178
+ load_from_file(f)
179
+ end
180
+ end
181
+ end
182
+
183
+ def load_from_file(file_path)
184
+ if File.file? file_path
185
+ config = YAML.load(File.open(file_path))
186
+ if config
187
+ ForemanMaintain::Utils::HashTools.deep_merge!(@configuration, config)
188
+ @config_files << file_path
189
+ end
190
+ end
191
+ end
192
+
193
+ def password_from_answers
194
+ return nil unless feature(:installer)
195
+ feature(:installer).answers['foreman']['admin_password']
196
+ end
197
+
198
+ def save_config_and_check(config)
199
+ save_config(config)
200
+ check_connection
201
+ end
202
+
203
+ def save_config(config)
204
+ File.open(custom_config_file, 'w', 0o600) { |f| f.puts YAML.dump(config) }
205
+ end
206
+
207
+ def _check_connection
208
+ `#{command_base} architecture list 2>&1` && $CHILD_STATUS.exitstatus == 0
209
+ end
55
210
  end
@@ -0,0 +1,106 @@
1
+ class Features::Installer < ForemanMaintain::Feature
2
+ metadata do
3
+ label :installer
4
+
5
+ confine do
6
+ find_package('foreman-installer') ||
7
+ find_package('katello-installer') ||
8
+ find_package('capsule-installer')
9
+ end
10
+ end
11
+
12
+ def initialize
13
+ @installer_type = if find_package('foreman-installer')
14
+ :scenarios
15
+ elsif find_package('katello-installer')
16
+ :legacy_katello
17
+ elsif find_package('capsule-installer')
18
+ :legacy_capsule
19
+ end
20
+ end
21
+
22
+ def answers
23
+ case @installer_type
24
+ when :scenarios
25
+ last_scenario_answers
26
+ when :legacy_katello
27
+ load_answers(File.join(config_directory, 'katello-installer.yaml'))
28
+ when :legacy_capsule
29
+ load_answers(File.join(config_directory, 'capsule-installer.yaml'))
30
+ end
31
+ end
32
+
33
+ def with_scenarios?
34
+ @installer_type == :scenarios
35
+ end
36
+
37
+ def config_directory
38
+ case @installer_type
39
+ when :scenarios
40
+ '/etc/foreman-installer'
41
+ when :legacy_katello
42
+ '/etc/katello-installer'
43
+ when :legacy_capsule
44
+ '/etc/capsule-installer'
45
+ end
46
+ end
47
+
48
+ def can_upgrade?
49
+ @installer_type == :scenarios || @installer_type == :legacy_katello
50
+ end
51
+
52
+ def config_files
53
+ Dir.glob(File.join(config_directory, '**/*')) +
54
+ [
55
+ '/usr/local/bin/validate_postgresql_connection.sh'
56
+ ]
57
+ end
58
+
59
+ def last_scenario
60
+ return nil unless with_scenarios?
61
+ File.basename(last_scenario_config).split('.')[0]
62
+ end
63
+
64
+ def installer_command
65
+ case @installer_type
66
+ when :scenarios
67
+ if feature(:downstream)
68
+ 'satellite-installer'
69
+ else
70
+ 'foreman-installer'
71
+ end
72
+ when :legacy_katello
73
+ 'katello-installer'
74
+ when :legacy_capsule
75
+ 'capsule-installer'
76
+ end
77
+ end
78
+
79
+ def run(arguments = '', exec_options = {})
80
+ execute!("LANG=en_US.utf-8 #{installer_command} #{arguments}".strip, exec_options)
81
+ end
82
+
83
+ def upgrade(exec_options = {})
84
+ arguments = '--upgrade' if can_upgrade?
85
+ run(arguments, exec_options)
86
+ end
87
+
88
+ private
89
+
90
+ def load_answers(config_file)
91
+ config = YAML.load_file(config_file)
92
+ YAML.load_file(config[:answer_file])
93
+ end
94
+
95
+ def scenario_answers(scenario)
96
+ load_answers(File.join(config_directory, "scenarios.d/#{scenario}.yaml"))
97
+ end
98
+
99
+ def last_scenario_answers
100
+ scenario_answers(last_scenario)
101
+ end
102
+
103
+ def last_scenario_config
104
+ Pathname.new(File.join(config_directory, 'scenarios.d/last_scenario.yaml')).realpath.to_s
105
+ end
106
+ end