manageiq-appliance_console 5.5.0 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +24 -25
  3. data/.rspec_ci +2 -0
  4. data/.rubocop.yml +3 -3
  5. data/.rubocop_cc.yml +3 -4
  6. data/.rubocop_local.yml +1 -1
  7. data/.travis.yml +4 -3
  8. data/Gemfile +1 -3
  9. data/README.md +1 -2
  10. data/Rakefile +20 -1
  11. data/bin/appliance_console +30 -6
  12. data/lib/manageiq/appliance_console/certificate_authority.rb +1 -1
  13. data/lib/manageiq/appliance_console/cli.rb +166 -70
  14. data/lib/manageiq/appliance_console/database_admin.rb +35 -206
  15. data/lib/manageiq/appliance_console/database_configuration.rb +10 -2
  16. data/lib/manageiq/appliance_console/database_replication.rb +1 -1
  17. data/lib/manageiq/appliance_console/database_replication_standby.rb +1 -1
  18. data/lib/manageiq/appliance_console/external_auth_options.rb +3 -13
  19. data/lib/manageiq/appliance_console/internal_database_configuration.rb +4 -12
  20. data/lib/manageiq/appliance_console/key_configuration.rb +8 -1
  21. data/lib/manageiq/appliance_console/logfile_configuration.rb +2 -2
  22. data/lib/manageiq/appliance_console/manageiq_user_mixin.rb +15 -0
  23. data/lib/manageiq/appliance_console/message_configuration.rb +205 -0
  24. data/lib/manageiq/appliance_console/message_configuration_client.rb +98 -0
  25. data/lib/manageiq/appliance_console/message_configuration_server.rb +321 -0
  26. data/lib/manageiq/appliance_console/oidc_authentication.rb +27 -1
  27. data/lib/manageiq/appliance_console/postgres_admin.rb +412 -0
  28. data/lib/manageiq/appliance_console/utilities.rb +61 -2
  29. data/lib/manageiq/appliance_console/version.rb +1 -1
  30. data/lib/manageiq-appliance_console.rb +2 -6
  31. data/locales/appliance/en.yml +0 -16
  32. data/manageiq-appliance_console.gemspec +4 -3
  33. metadata +54 -24
  34. data/lib/manageiq/appliance_console/messaging_configuration.rb +0 -92
@@ -23,22 +23,17 @@ module ManageIQ
23
23
 
24
24
  WARN
25
25
 
26
- attr_accessor :uri
27
- attr_reader :action, :backup_type, :task, :task_params, :delete_agree, :filename
26
+ attr_reader :action, :backup_type, :database_opts, :delete_agree, :filename
28
27
 
29
28
  def initialize(action = :restore, input = $stdin, output = $stdout)
30
29
  super(input, output)
31
30
 
32
- @action = action
33
- @task_params = []
31
+ @action = action
32
+ @database_opts = {:dbname => DatabaseConfiguration.database_name}
34
33
  end
35
34
 
36
- def local_backup?
37
- backup_type == "local".freeze
38
- end
39
-
40
- def object_store_backup?
41
- backup_type == "s3".freeze || backup_type == "swift".freeze
35
+ def uri
36
+ @database_opts[:local_file]
42
37
  end
43
38
 
44
39
  def ask_questions
@@ -51,7 +46,6 @@ module ManageIQ
51
46
  say(DB_DUMP_WARNING) if action == :dump
52
47
  ask_file_location
53
48
  ask_for_tables_to_exclude_in_dump
54
- ask_to_split_up_output
55
49
  end
56
50
 
57
51
  def activate
@@ -63,144 +57,11 @@ module ManageIQ
63
57
  end
64
58
 
65
59
  def ask_file_location
66
- @backup_type = ask_with_menu(*file_menu_args) do |menu|
67
- menu.choice(CANCEL) { |_| raise MiqSignalError }
68
- end
69
- if URI(backup_type).scheme
70
- ask_custom_file_options(backup_type)
71
- else
72
- # calling methods like ask_ftp_file_options and ask_s3_file_options
73
- send("ask_#{backup_type}_file_options")
74
- end
75
- end
76
-
77
- def ask_local_file_options
78
- @uri = just_ask(*filename_prompt_args)
79
- @task = "evm:db:#{action}:local"
80
- @task_params = ["--", {:local_file => uri}]
81
- end
82
-
83
- def ask_nfs_file_options
84
- @filename = just_ask(*filename_prompt_args) unless action == :restore
85
- @uri = ask_for_uri(*remote_file_prompt_args_for("nfs"))
86
- @task = "evm:db:#{action}:remote"
87
-
88
- params = {:uri => uri}
89
- params[:remote_file_name] = filename if filename
90
-
91
- @task_params = ["--", params]
92
- end
93
-
94
- def ask_smb_file_options
95
- @filename = just_ask(*filename_prompt_args) unless action == :restore
96
- @uri = ask_for_uri(*remote_file_prompt_args_for("smb"))
97
- user = just_ask(USER_PROMPT)
98
- pass = ask_for_password("password for #{user}")
99
-
100
- params = {
101
- :uri => uri,
102
- :uri_username => user,
103
- :uri_password => pass
104
- }
105
- params[:remote_file_name] = filename if filename
106
-
107
- @task = "evm:db:#{action}:remote"
108
- @task_params = ["--", params]
109
- end
110
-
111
- def ask_s3_file_options
112
- access_key_prompt = <<-PROMPT.strip_heredoc.chomp
113
- Access Key ID with access to this file.
114
- Example: 'amazon_aws_user'
115
- PROMPT
116
-
117
- @filename = just_ask(*filename_prompt_args) unless action == :restore
118
- @uri = ask_for_uri(*remote_file_prompt_args_for("s3"), :optional_path => true)
119
- region = just_ask("Amazon Region for database file", "us-east-1")
120
- user = just_ask(access_key_prompt)
121
- pass = ask_for_password("Secret Access Key for #{user}")
122
-
123
- params = {
124
- :uri => uri,
125
- :uri_username => user,
126
- :uri_password => pass,
127
- :aws_region => region
128
- }
129
- params[:remote_file_name] = filename if filename
130
-
131
- @task = "evm:db:#{action}:remote"
132
- @task_params = ["--", params]
133
- end
134
-
135
- def ask_ftp_file_options
136
- @filename = just_ask(*filename_prompt_args) unless action == :restore
137
- @uri = ask_for_uri(*remote_file_prompt_args_for("ftp"), :optional_path => true)
138
- user = just_ask(USER_PROMPT)
139
- pass = ask_for_password("password for #{user}")
140
-
141
- params = { :uri => uri }
142
- params[:uri_username] = user if user.present?
143
- params[:uri_password] = pass if pass.present?
144
- params[:remote_file_name] = filename if filename
145
-
146
- @task = "evm:db:#{action}:remote"
147
- @task_params = ["--", params]
148
- end
149
-
150
- def ask_custom_file_options(server_uri)
151
- hostname = URI(server_uri).host
152
- @filename = ask_custom_file_prompt(hostname)
153
- @uri = server_uri
154
-
155
- params = {:uri => uri, :remote_file_name => filename}
156
-
157
- if (custom_params = custom_endpoint_config_for(hostname))
158
- params.merge!(custom_params[:rake_options]) if custom_params[:rake_options]
159
- end
160
-
161
- @task = "evm:db:#{action}:remote"
162
- @task_params = ["--", params]
163
- end
164
-
165
- def ask_swift_file_options
166
- require 'uri'
167
- swift_user_prompt = <<-PROMPT.strip_heredoc.chomp
168
- User Name with access to this file.
169
- Example: 'openstack_user'
170
- PROMPT
171
-
172
- @filename = just_ask(*filename_prompt_args) { |q| q.readline = false } unless action == :restore
173
- @uri = URI(ask_for_uri(*remote_file_prompt_args_for("swift")) { |q| q.readline = false })
174
- @task = "evm:db:#{action}:remote"
175
- user = just_ask(swift_user_prompt) { |q| q.readline = false }
176
- pass = ask_for_password("password for #{user}") { |q| q.readline = false }
177
- @uri.query = swift_query_elements.join('&').presence
178
-
179
- params = {
180
- :uri => @uri.to_s,
181
- :uri_username => user,
182
- :uri_password => pass
183
- }
184
- params[:remote_file_name] = filename if filename
185
- @task = "evm:db:#{action}:remote"
186
- @task_params = ["--", params]
187
- end
188
-
189
- def swift_query_elements
190
- region = just_ask("OpenStack Swift Region") { |q| q.readline = false }
191
- @uri.port = just_ask("OpenStack Swift Port", "5000") { |q| q.readline = false }
192
- security_protocol = ask_with_menu(*security_protocol_menu_args)
193
- api_version = ask_with_menu(*api_version_menu_args) { |q| q.readline = false }
194
- domain_ident = just_ask("OpenStack V3 Domain Identifier") { |q| q.readline = false } if api_version == "v3"
195
- query_elements = []
196
- query_elements << "region=#{region}" if region.present?
197
- query_elements << "api_version=#{api_version}" if api_version.present?
198
- query_elements << "domain_id=#{domain_ident}" if domain_ident.present?
199
- query_elements << "security_protocol=#{security_protocol}" if security_protocol.present?
60
+ @database_opts[:local_file] = just_ask(*filename_prompt_args)
200
61
  end
201
62
 
202
63
  def ask_to_delete_backup_after_restore
203
- if action == :restore && local_backup?
64
+ if action == :restore
204
65
  say("The local database restore file is located at: '#{uri}'.\n")
205
66
  @delete_agree = agree("Should this file be deleted after completing the restore? (Y/N): ")
206
67
  end
@@ -222,20 +83,14 @@ module ManageIQ
222
83
  255,
223
84
  Float::INFINITY)
224
85
 
225
- @task_params.last[:"exclude-table-data"] = table_excludes
226
- end || true
227
- end
228
-
229
- def ask_to_split_up_output
230
- if action == :dump && should_split_output?
231
- @task_params.last[:byte_count] = ask_for_string("byte size to split by", "500M")
86
+ @database_opts[:exclude_table_data] = table_excludes
232
87
  end || true
233
88
  end
234
89
 
235
90
  def confirm_and_execute
236
91
  if allowed_to_execute?
237
92
  processing_message
238
- run_rake
93
+ run_action
239
94
  end
240
95
  press_any_key
241
96
  end
@@ -259,58 +114,18 @@ module ManageIQ
259
114
  end
260
115
  end
261
116
 
262
- def api_version_menu_args
263
- [
264
- "OpenStack API Version",
265
- [["Keystone v2".freeze, "v2".freeze], ["Keystone v3".freeze, "v3".freeze], ["None".freeze, nil]].freeze,
266
- ["Keystone v2".freeze, "v2".freeze],
267
- nil
268
- ]
269
- end
270
-
271
- def file_menu_args
272
- [
273
- action == :restore ? "Restore Database File Source" : "#{action.capitalize} Output File Destination",
274
- file_options,
275
- "local",
276
- nil
277
- ]
278
- end
279
-
280
- def security_protocol_menu_args
281
- [
282
- "OpenStack Security Protocol",
283
- [["SSL without validation".freeze, "ssl".freeze], ["SSL".freeze, "ssl-with-validation".freeze], ["Non-SSL".freeze, "non-ssl".freeze], ["None".freeze, nil]].freeze,
284
- ["Non-SSL".freeze, "non-ssl".freeze],
285
- nil
286
- ]
287
- end
288
-
289
117
  def setting_header
290
118
  say("#{I18n.t("advanced_settings.db#{action}")}\n\n")
291
119
  end
292
120
 
293
121
  private
294
122
 
295
- def ask_custom_file_prompt(hostname)
296
- prompts = custom_endpoint_config_for(hostname)
297
- prompt_text = prompts && prompts[:filename_text] || "Target filename for backup".freeze
298
- prompt_regex = prompts && prompts[:filename_validator]
299
- validator = prompt_regex ? ->(x) { x.to_s =~ /#{prompt_regex}/ } : ->(x) { x.to_s.present? }
300
- just_ask(prompt_text, nil, validator)
301
- end
302
-
303
123
  def skip_file_location?(hostname)
304
124
  config = custom_endpoint_config_for(hostname)
305
125
  return false unless config && config[:enabled_for].present?
306
126
  !Array(config[:enabled_for]).include?(action.to_s)
307
127
  end
308
128
 
309
- def custom_endpoint_config_for(hostname)
310
- # hostname has a period in it, so we need to look it up by [] instead of the traditional i18n method
311
- I18n.t("database_admin.prompts", :default => {})[hostname.to_sym]
312
- end
313
-
314
129
  def should_exclude_tables?
315
130
  ask_yn?("Would you like to exclude tables in the dump") do |q|
316
131
  q.readline = true
@@ -327,16 +142,12 @@ module ManageIQ
327
142
  return restore_prompt_args if action == :restore
328
143
  default = action == :dump ? DB_DEFAULT_DUMP_FILE : DB_RESTORE_FILE
329
144
  prompt = "location to save the #{action} file to"
330
- if object_store_backup?
331
- prompt = "name for the remote #{action} file"
332
- default = File.basename(default)
333
- end
334
145
  [prompt, default, nil, "file that exists"]
335
146
  end
336
147
 
337
148
  def restore_prompt_args
338
149
  default = DB_RESTORE_FILE
339
- validator = LOCAL_FILE_VALIDATOR if local_backup?
150
+ validator = LOCAL_FILE_VALIDATOR
340
151
  prompt = "location of the local restore file"
341
152
  [prompt, default, validator, "file that exists"]
342
153
  end
@@ -347,12 +158,12 @@ module ManageIQ
347
158
  else
348
159
  "location to save the remote #{action} file to"
349
160
  end
350
- prompt += "\nExample: #{sample_url(remote_type)}"
161
+ prompt += "\nExample: #{sample_url}"
351
162
  [prompt, remote_type]
352
163
  end
353
164
 
354
- def sample_url(scheme)
355
- I18n.t("database_admin.sample_url.#{scheme}")
165
+ def sample_url
166
+ I18n.t("database_admin.sample_url.nfs")
356
167
  end
357
168
 
358
169
  def processing_message
@@ -364,15 +175,33 @@ module ManageIQ
364
175
  say(msg)
365
176
  end
366
177
 
367
- def run_rake
368
- rake_success = ManageIQ::ApplianceConsole::Utilities.rake(task, task_params)
369
- if rake_success && action == :restore && delete_agree
178
+ def run_action
179
+ success = send(action)
180
+ if success && action == :restore && delete_agree
370
181
  say("\nRemoving the database restore file #{uri}...")
371
182
  File.delete(uri)
372
- elsif !rake_success
183
+ elsif !success
373
184
  say("\nDatabase #{action} failed. Check the logs for more information")
374
185
  end
375
186
  end
187
+
188
+ def backup
189
+ result = PostgresAdmin.backup(database_opts)
190
+ ManageIQ::ApplianceConsole.logger.info("[#{@database_opts[:dbname]}] database has been backed up to file: [#{uri}]")
191
+ result
192
+ end
193
+
194
+ def dump
195
+ result = PostgresAdmin.backup_pg_dump(database_opts)
196
+ ManageIQ::ApplianceConsole.logger.info("[#{@database_opts[:dbname]}] database has been dumped up to file: [#{uri}]")
197
+ result
198
+ end
199
+
200
+ def restore
201
+ result = PostgresAdmin.restore(database_opts.merge(:backup_type => backup_type))
202
+ ManageIQ::ApplianceConsole.logger.info("[#{@database_opts[:dbname]}] database has been restored from file: [#{uri}]")
203
+ result
204
+ end
376
205
  end
377
206
  end
378
207
  end
@@ -5,10 +5,15 @@ require 'manageiq-password'
5
5
  require 'pathname'
6
6
  require 'fileutils'
7
7
 
8
+ require_relative './manageiq_user_mixin'
9
+
8
10
  module ManageIQ
9
11
  module ApplianceConsole
10
12
  class DatabaseConfiguration
11
- attr_accessor :adapter, :host, :username, :database, :password, :port, :region
13
+ include ManageIQ::ApplianceConsole::ManageiqUserMixin
14
+
15
+ attr_accessor :adapter, :host, :username, :database, :port, :region
16
+ attr_reader :password
12
17
 
13
18
  class ModelWithNoBackingTable < ActiveRecord::Base
14
19
  end
@@ -274,7 +279,10 @@ FRIENDLY
274
279
 
275
280
  def do_save(settings)
276
281
  require 'yaml'
277
- File.write(DB_YML, YAML.dump(settings))
282
+ File.open(DB_YML, "w") do |f|
283
+ f.write(YAML.dump(settings))
284
+ f.chown(manageiq_uid, manageiq_gid)
285
+ end
278
286
  end
279
287
 
280
288
  def initialize_from_hash(hash)
@@ -1,6 +1,6 @@
1
1
  require 'pg'
2
2
  require 'English'
3
- require 'util/postgres_admin'
3
+ require 'manageiq/appliance_console/postgres_admin'
4
4
 
5
5
  module ManageIQ
6
6
  module ApplianceConsole
@@ -1,4 +1,4 @@
1
- require 'util/postgres_admin'
1
+ require 'manageiq/appliance_console/postgres_admin'
2
2
  require 'fileutils'
3
3
  require 'linux_admin'
4
4
 
@@ -82,8 +82,7 @@ module ApplianceConsole
82
82
  say("\nUpdating external authentication options on appliance ...")
83
83
  params = update_hash.collect { |key, value| "#{key}=#{value}" }
84
84
  params = configure_provider_type!(params)
85
- result = ManageIQ::ApplianceConsole::Utilities.rake_run("evm:settings:set", params)
86
- raise parse_errors(result).join(', ') if result.failure?
85
+ ManageIQ::ApplianceConsole::Utilities.rake_run!("evm:settings:set", params)
87
86
  end
88
87
  end
89
88
 
@@ -152,17 +151,8 @@ module ApplianceConsole
152
151
 
153
152
  def load_current
154
153
  say("\nFetching external authentication options from appliance ...")
155
- result = ManageIQ::ApplianceConsole::Utilities.rake_run("evm:settings:get", EXT_AUTH_OPTIONS.keys)
156
-
157
- if result.success?
158
- return parse_response(result)
159
- else
160
- raise parse_errors(result).join(', ')
161
- end
162
- end
163
-
164
- def parse_errors(result)
165
- result.error.split("\n").collect { |line| line if line =~ /^error: /i }.compact
154
+ result = ManageIQ::ApplianceConsole::Utilities.rake_run!("evm:settings:get", EXT_AUTH_OPTIONS.keys)
155
+ parse_response(result)
166
156
  end
167
157
 
168
158
  def normalize_key(key)
@@ -1,6 +1,5 @@
1
1
  require "pathname"
2
- require "util/postgres_admin"
3
- require "pg"
2
+ require "manageiq/appliance_console/postgres_admin"
4
3
  require "linux_admin"
5
4
 
6
5
  module ManageIQ
@@ -149,14 +148,14 @@ module ApplianceConsole
149
148
  end
150
149
 
151
150
  def create_postgres_root_user
152
- with_pg_connection do |conn|
151
+ PostgresAdmin.with_pg_connection do |conn|
153
152
  esc_pass = conn.escape_string(password)
154
153
  conn.exec("CREATE ROLE #{username} WITH LOGIN CREATEDB SUPERUSER PASSWORD '#{esc_pass}'")
155
154
  end
156
155
  end
157
156
 
158
157
  def create_postgres_database
159
- with_pg_connection do |conn|
158
+ PostgresAdmin.with_pg_connection do |conn|
160
159
  conn.exec("CREATE DATABASE #{database} OWNER #{username} ENCODING 'utf8'")
161
160
  end
162
161
  end
@@ -165,16 +164,9 @@ module ApplianceConsole
165
164
  AwesomeSpawn.run!("/sbin/restorecon -R -v #{mount_point}")
166
165
  end
167
166
 
168
- def with_pg_connection
169
- conn = PG.connect(:user => "postgres", :dbname => "postgres")
170
- yield conn
171
- ensure
172
- conn.close
173
- end
174
-
175
167
  def apply_initial_configuration
176
168
  shared_buffers = run_as_evm_server ? SHARED_DB_SHARED_BUFFERS : DEDICATED_DB_SHARED_BUFFERS
177
- with_pg_connection { |conn| conn.exec("ALTER SYSTEM SET shared_buffers TO #{shared_buffers}") }
169
+ PostgresAdmin.with_pg_connection { |conn| conn.exec("ALTER SYSTEM SET shared_buffers TO #{shared_buffers}") }
178
170
 
179
171
  restart_postgres
180
172
  end