manageiq-appliance_console 5.5.0 → 7.0.1
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 +4 -4
- data/.codeclimate.yml +24 -25
- data/.rspec_ci +2 -0
- data/.rubocop.yml +3 -3
- data/.rubocop_cc.yml +3 -4
- data/.rubocop_local.yml +1 -1
- data/.travis.yml +4 -3
- data/Gemfile +1 -3
- data/README.md +1 -2
- data/Rakefile +20 -1
- data/bin/appliance_console +30 -6
- data/lib/manageiq/appliance_console/certificate_authority.rb +1 -1
- data/lib/manageiq/appliance_console/cli.rb +166 -70
- data/lib/manageiq/appliance_console/database_admin.rb +35 -206
- data/lib/manageiq/appliance_console/database_configuration.rb +10 -2
- data/lib/manageiq/appliance_console/database_replication.rb +1 -1
- data/lib/manageiq/appliance_console/database_replication_standby.rb +1 -1
- data/lib/manageiq/appliance_console/external_auth_options.rb +3 -13
- data/lib/manageiq/appliance_console/internal_database_configuration.rb +4 -12
- data/lib/manageiq/appliance_console/key_configuration.rb +8 -1
- data/lib/manageiq/appliance_console/logfile_configuration.rb +2 -2
- data/lib/manageiq/appliance_console/manageiq_user_mixin.rb +15 -0
- data/lib/manageiq/appliance_console/message_configuration.rb +205 -0
- data/lib/manageiq/appliance_console/message_configuration_client.rb +98 -0
- data/lib/manageiq/appliance_console/message_configuration_server.rb +321 -0
- data/lib/manageiq/appliance_console/oidc_authentication.rb +27 -1
- data/lib/manageiq/appliance_console/postgres_admin.rb +412 -0
- data/lib/manageiq/appliance_console/utilities.rb +61 -2
- data/lib/manageiq/appliance_console/version.rb +1 -1
- data/lib/manageiq-appliance_console.rb +2 -6
- data/locales/appliance/en.yml +0 -16
- data/manageiq-appliance_console.gemspec +4 -3
- metadata +54 -24
- data/lib/manageiq/appliance_console/messaging_configuration.rb +0 -92
@@ -23,22 +23,17 @@ module ManageIQ
|
|
23
23
|
|
24
24
|
WARN
|
25
25
|
|
26
|
-
|
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
|
33
|
-
@
|
31
|
+
@action = action
|
32
|
+
@database_opts = {:dbname => DatabaseConfiguration.database_name}
|
34
33
|
end
|
35
34
|
|
36
|
-
def
|
37
|
-
|
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
|
-
@
|
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
|
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
|
-
@
|
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
|
-
|
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
|
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
|
161
|
+
prompt += "\nExample: #{sample_url}"
|
351
162
|
[prompt, remote_type]
|
352
163
|
end
|
353
164
|
|
354
|
-
def sample_url
|
355
|
-
I18n.t("database_admin.sample_url
|
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
|
368
|
-
|
369
|
-
if
|
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 !
|
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
|
-
|
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.
|
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)
|
@@ -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
|
-
|
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 "
|
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
|