manageiq-appliance_console 3.2.0 → 3.3.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dab9032437ce55e00eacbd51c230873b67c7c6ebbce41637ecdf167c687f1fb9
|
4
|
+
data.tar.gz: 7f3414f814c1afe4764c5a042c0ca4d5243efdaba391039ed34d0838401d57f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b10da6f428508db44d798a4486ffd9b0d19aad3aaf0141dbfd6d5bdb453bc436c2133962446535240e633e70217ec7918893f956c90ab587bafe468e859628d
|
7
|
+
data.tar.gz: 8657df612109649196c051e5054e30b9b66ecb599e56170b3746aa302bd7ec98b0b4776541b05a1b7296454feb444a12bc8c078d2b9c2a8ebe2dcab29f5dca77
|
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'manageiq/appliance_console/errors'
|
2
|
+
require 'uri'
|
2
3
|
|
3
4
|
module ManageIQ
|
4
5
|
module ApplianceConsole
|
5
6
|
class DatabaseAdmin < HighLine
|
6
7
|
include ManageIQ::ApplianceConsole::Prompts
|
7
8
|
|
8
|
-
LOCAL_FILE = "Local file".freeze
|
9
|
-
NFS_FILE = "Network File System (NFS)".freeze
|
10
|
-
SMB_FILE = "Samba (SMB)".freeze
|
11
|
-
S3_FILE = "Amazon S3 (S3)".freeze
|
12
|
-
FILE_OPTIONS = [LOCAL_FILE, NFS_FILE, SMB_FILE, S3_FILE, CANCEL].freeze
|
13
|
-
|
14
9
|
DB_RESTORE_FILE = "/tmp/evm_db.backup".freeze
|
15
10
|
DB_DEFAULT_DUMP_FILE = "/tmp/evm_db.dump".freeze
|
16
11
|
LOCAL_FILE_VALIDATOR = ->(a) { File.exist?(a) }.freeze
|
@@ -28,7 +23,8 @@ module ManageIQ
|
|
28
23
|
|
29
24
|
WARN
|
30
25
|
|
31
|
-
|
26
|
+
attr_accessor :uri
|
27
|
+
attr_reader :action, :backup_type, :task, :task_params, :delete_agree, :filename
|
32
28
|
|
33
29
|
def initialize(action = :restore, input = $stdin, output = $stdout)
|
34
30
|
super(input, output)
|
@@ -37,11 +33,20 @@ module ManageIQ
|
|
37
33
|
@task_params = []
|
38
34
|
end
|
39
35
|
|
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
|
42
|
+
end
|
43
|
+
|
40
44
|
def ask_questions
|
41
45
|
setting_header
|
42
46
|
say(DB_DUMP_WARNING) if action == :dump
|
43
47
|
ask_file_location
|
44
48
|
ask_for_tables_to_exclude_in_dump
|
49
|
+
ask_to_split_up_output
|
45
50
|
end
|
46
51
|
|
47
52
|
def activate
|
@@ -53,12 +58,14 @@ module ManageIQ
|
|
53
58
|
end
|
54
59
|
|
55
60
|
def ask_file_location
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
@backup_type = ask_with_menu(*file_menu_args) do |menu|
|
62
|
+
menu.choice(CANCEL) { |_| raise MiqSignalError }
|
63
|
+
end
|
64
|
+
if URI(backup_type).scheme
|
65
|
+
ask_custom_file_options(backup_type)
|
66
|
+
else
|
67
|
+
# calling methods like ask_ftp_file_options and ask_s3_file_options
|
68
|
+
send("ask_#{backup_type}_file_options")
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
@@ -120,8 +127,75 @@ module ManageIQ
|
|
120
127
|
@task_params = ["--", params]
|
121
128
|
end
|
122
129
|
|
130
|
+
def ask_ftp_file_options
|
131
|
+
@filename = just_ask(*filename_prompt_args) unless action == :restore
|
132
|
+
@uri = ask_for_uri(*remote_file_prompt_args_for("ftp"), :optional_path => true)
|
133
|
+
user = just_ask(USER_PROMPT)
|
134
|
+
pass = ask_for_password("password for #{user}")
|
135
|
+
|
136
|
+
params = { :uri => uri }
|
137
|
+
params[:uri_username] = user if user.present?
|
138
|
+
params[:uri_password] = pass if pass.present?
|
139
|
+
params[:remote_file_name] = filename if filename
|
140
|
+
|
141
|
+
@task = "evm:db:#{action}:remote"
|
142
|
+
@task_params = ["--", params]
|
143
|
+
end
|
144
|
+
|
145
|
+
def ask_custom_file_options(server_uri)
|
146
|
+
hostname = URI(server_uri).host
|
147
|
+
@filename = ask_custom_file_prompt(hostname)
|
148
|
+
@uri = server_uri
|
149
|
+
|
150
|
+
params = {:uri => uri, :remote_file_name => filename}
|
151
|
+
|
152
|
+
if (custom_params = custom_endpoint_config_for(hostname))
|
153
|
+
params.merge!(custom_params[:rake_options]) if custom_params[:rake_options]
|
154
|
+
end
|
155
|
+
|
156
|
+
@task = "evm:db:#{action}:remote"
|
157
|
+
@task_params = ["--", params]
|
158
|
+
end
|
159
|
+
|
160
|
+
def ask_swift_file_options
|
161
|
+
require 'uri'
|
162
|
+
swift_user_prompt = <<-PROMPT.strip_heredoc.chomp
|
163
|
+
User Name with access to this file.
|
164
|
+
Example: 'openstack_user'
|
165
|
+
PROMPT
|
166
|
+
|
167
|
+
@filename = just_ask(*filename_prompt_args) { |q| q.readline = false } unless action == :restore
|
168
|
+
@uri = URI(ask_for_uri(*remote_file_prompt_args_for("swift")) { |q| q.readline = false })
|
169
|
+
@task = "evm:db:#{action}:remote"
|
170
|
+
user = just_ask(swift_user_prompt) { |q| q.readline = false }
|
171
|
+
pass = ask_for_password("password for #{user}") { |q| q.readline = false }
|
172
|
+
@uri.query = swift_query_elements.join('&').presence
|
173
|
+
|
174
|
+
params = {
|
175
|
+
:uri => @uri.to_s,
|
176
|
+
:uri_username => user,
|
177
|
+
:uri_password => pass
|
178
|
+
}
|
179
|
+
params[:remote_file_name] = filename if filename
|
180
|
+
@task = "evm:db:#{action}:remote"
|
181
|
+
@task_params = ["--", params]
|
182
|
+
end
|
183
|
+
|
184
|
+
def swift_query_elements
|
185
|
+
region = just_ask("OpenStack Swift Region") { |q| q.readline = false }
|
186
|
+
@uri.port = just_ask("OpenStack Swift Port", "5000") { |q| q.readline = false }
|
187
|
+
security_protocol = ask_with_menu(*security_protocol_menu_args)
|
188
|
+
api_version = ask_with_menu(*api_version_menu_args) { |q| q.readline = false }
|
189
|
+
domain_ident = just_ask("OpenStack V3 Domain Identifier") { |q| q.readline = false } if api_version == "v3"
|
190
|
+
query_elements = []
|
191
|
+
query_elements << "region=#{region}" if region.present?
|
192
|
+
query_elements << "api_version=#{api_version}" if api_version.present?
|
193
|
+
query_elements << "domain_id=#{domain_ident}" if domain_ident.present?
|
194
|
+
query_elements << "security_protocol=#{security_protocol}" if security_protocol.present?
|
195
|
+
end
|
196
|
+
|
123
197
|
def ask_to_delete_backup_after_restore
|
124
|
-
if action == :restore &&
|
198
|
+
if action == :restore && local_backup?
|
125
199
|
say("The local database restore file is located at: '#{uri}'.\n")
|
126
200
|
@delete_agree = agree("Should this file be deleted after completing the restore? (Y/N): ")
|
127
201
|
end
|
@@ -147,6 +221,12 @@ module ManageIQ
|
|
147
221
|
end || true
|
148
222
|
end
|
149
223
|
|
224
|
+
def ask_to_split_up_output
|
225
|
+
if action == :dump && should_split_output?
|
226
|
+
@task_params.last[:byte_count] = ask_for_string("byte size to split by", "500M")
|
227
|
+
end || true
|
228
|
+
end
|
229
|
+
|
150
230
|
def confirm_and_execute
|
151
231
|
if allowed_to_execute?
|
152
232
|
processing_message
|
@@ -157,15 +237,46 @@ module ManageIQ
|
|
157
237
|
|
158
238
|
def allowed_to_execute?
|
159
239
|
return true unless action == :restore
|
240
|
+
|
160
241
|
say("\nNote: A database restore cannot be undone. The restore will use the file: #{uri}.\n")
|
161
242
|
agree("Are you sure you would like to restore the database? (Y/N): ")
|
162
243
|
end
|
163
244
|
|
245
|
+
def file_options
|
246
|
+
@file_options ||= I18n.t("database_admin.menu_order").each_with_object({}) do |file_option, h|
|
247
|
+
# special anonymous ftp sites are defined by uri
|
248
|
+
uri = URI(file_option)
|
249
|
+
if uri.scheme
|
250
|
+
h["#{uri.scheme} to #{uri.host}"] = file_option unless skip_file_location?(uri.host)
|
251
|
+
else
|
252
|
+
h[I18n.t("database_admin.#{file_option}")] = file_option
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def api_version_menu_args
|
258
|
+
[
|
259
|
+
"OpenStack API Version",
|
260
|
+
[["Keystone v2".freeze, "v2".freeze], ["Keystone v3".freeze, "v3".freeze], ["None".freeze, nil]].freeze,
|
261
|
+
["Keystone v2".freeze, "v2".freeze],
|
262
|
+
nil
|
263
|
+
]
|
264
|
+
end
|
265
|
+
|
164
266
|
def file_menu_args
|
165
267
|
[
|
166
268
|
action == :restore ? "Restore Database File" : "#{action.capitalize} Output File Name",
|
167
|
-
|
168
|
-
|
269
|
+
file_options,
|
270
|
+
"local",
|
271
|
+
nil
|
272
|
+
]
|
273
|
+
end
|
274
|
+
|
275
|
+
def security_protocol_menu_args
|
276
|
+
[
|
277
|
+
"OpenStack Security Protocol",
|
278
|
+
[["SSL without validation".freeze, "ssl".freeze], ["SSL".freeze, "ssl-with-validation".freeze], ["Non-SSL".freeze, "non-ssl".freeze], ["None".freeze, nil]].freeze,
|
279
|
+
["Non-SSL".freeze, "non-ssl".freeze],
|
169
280
|
nil
|
170
281
|
]
|
171
282
|
end
|
@@ -176,24 +287,53 @@ module ManageIQ
|
|
176
287
|
|
177
288
|
private
|
178
289
|
|
290
|
+
def ask_custom_file_prompt(hostname)
|
291
|
+
prompts = custom_endpoint_config_for(hostname)
|
292
|
+
prompt_text = prompts && prompts[:filename_text] || "Target filename for backup".freeze
|
293
|
+
prompt_regex = prompts && prompts[:filename_validator]
|
294
|
+
validator = prompt_regex ? ->(x) { x.to_s =~ /#{prompt_regex}/ } : ->(x) { x.to_s.present? }
|
295
|
+
just_ask(prompt_text, nil, validator)
|
296
|
+
end
|
297
|
+
|
298
|
+
def skip_file_location?(hostname)
|
299
|
+
config = custom_endpoint_config_for(hostname)
|
300
|
+
return false unless config && config[:enabled_for].present?
|
301
|
+
!Array(config[:enabled_for]).include?(action.to_s)
|
302
|
+
end
|
303
|
+
|
304
|
+
def custom_endpoint_config_for(hostname)
|
305
|
+
# hostname has a period in it, so we need to look it up by [] instead of the traditional i18n method
|
306
|
+
I18n.t("database_admin.prompts", :default => {})[hostname.to_sym]
|
307
|
+
end
|
308
|
+
|
179
309
|
def should_exclude_tables?
|
180
310
|
ask_yn?("Would you like to exclude tables in the dump") do |q|
|
181
311
|
q.readline = true
|
182
312
|
end
|
183
313
|
end
|
184
314
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
188
|
-
|
315
|
+
def should_split_output?
|
316
|
+
ask_yn?("Would you like to split the #{action} output into multiple parts") do |q|
|
317
|
+
q.readline = true
|
318
|
+
end
|
189
319
|
end
|
190
320
|
|
191
|
-
def
|
192
|
-
if action == :restore
|
193
|
-
|
194
|
-
|
195
|
-
|
321
|
+
def filename_prompt_args
|
322
|
+
return restore_prompt_args if action == :restore
|
323
|
+
default = action == :dump ? DB_DEFAULT_DUMP_FILE : DB_RESTORE_FILE
|
324
|
+
prompt = "location to save the #{action} file to"
|
325
|
+
if object_store_backup?
|
326
|
+
prompt = "name for the remote #{action} file"
|
327
|
+
default = File.basename(default)
|
196
328
|
end
|
329
|
+
[prompt, default, nil, "file that exists"]
|
330
|
+
end
|
331
|
+
|
332
|
+
def restore_prompt_args
|
333
|
+
default = DB_RESTORE_FILE
|
334
|
+
validator = LOCAL_FILE_VALIDATOR if local_backup?
|
335
|
+
prompt = "location of the local restore file"
|
336
|
+
[prompt, default, validator, "file that exists"]
|
197
337
|
end
|
198
338
|
|
199
339
|
def remote_file_prompt_args_for(remote_type)
|
@@ -202,10 +342,14 @@ module ManageIQ
|
|
202
342
|
else
|
203
343
|
"location to save the remote #{action} file to"
|
204
344
|
end
|
205
|
-
prompt += "\nExample: #{
|
345
|
+
prompt += "\nExample: #{sample_url(remote_type)}"
|
206
346
|
[prompt, remote_type]
|
207
347
|
end
|
208
348
|
|
349
|
+
def sample_url(scheme)
|
350
|
+
I18n.t("database_admin.sample_url.#{scheme}")
|
351
|
+
end
|
352
|
+
|
209
353
|
def processing_message
|
210
354
|
msg = if action == :restore
|
211
355
|
"\nRestoring the database..."
|
@@ -15,16 +15,6 @@ module ApplianceConsole
|
|
15
15
|
NONE_REGEXP = /^('?NONE'?)?$/i.freeze
|
16
16
|
HOSTNAME_REGEXP = /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/
|
17
17
|
|
18
|
-
SAMPLE_URLS = {
|
19
|
-
'nfs' => 'nfs://host.mydomain.com/exported/my_exported_folder/db.backup',
|
20
|
-
'smb' => 'smb://host.mydomain.com/my_share/daily_backup/db.backup',
|
21
|
-
's3' => 's3://mybucket/my_subdirectory/daily_backup/db.backup',
|
22
|
-
}
|
23
|
-
|
24
|
-
def sample_url(scheme)
|
25
|
-
SAMPLE_URLS[scheme]
|
26
|
-
end
|
27
|
-
|
28
18
|
def ask_for_uri(prompt, expected_scheme, opts = {})
|
29
19
|
require 'uri'
|
30
20
|
just_ask(prompt, nil, nil, 'a valid URI') do |q|
|
@@ -38,6 +28,7 @@ module ApplianceConsole
|
|
38
28
|
(u.host =~ HOSTNAME_REGEXP || u.hostname =~ IP_REGEXP) &&
|
39
29
|
(opts[:optional_path] || !u.path.empty?)
|
40
30
|
end
|
31
|
+
yield q if block_given?
|
41
32
|
end
|
42
33
|
end
|
43
34
|
|
data/locales/appliance/en.yml
CHANGED
@@ -42,3 +42,23 @@ en:
|
|
42
42
|
shutdown: Shut Down Appliance
|
43
43
|
summary: Summary Information
|
44
44
|
quit: Quit
|
45
|
+
database_admin:
|
46
|
+
menu_order:
|
47
|
+
- local
|
48
|
+
- nfs
|
49
|
+
- smb
|
50
|
+
- s3
|
51
|
+
- ftp
|
52
|
+
- swift
|
53
|
+
local: Local file
|
54
|
+
nfs: Network File System (NFS)
|
55
|
+
smb: Samba (SMB)
|
56
|
+
s3: Amazon S3 (S3)
|
57
|
+
ftp: File Transfer Protocol (FTP)
|
58
|
+
swift: OpenStack Swift (Swift)
|
59
|
+
sample_url:
|
60
|
+
nfs: nfs://host.mydomain.com/exported/my_exported_folder/db.backup
|
61
|
+
smb: smb://host.mydomain.com/my_share/daily_backup/db.backup
|
62
|
+
s3: s3://mybucket/my_subdirectory/daily_backup/db.backup
|
63
|
+
ftp: ftp://host.mydomain.com/path/to/daily_backup/db.backup
|
64
|
+
swift: swift://host.mydomain.com/path/to/daily_backup/db.backup
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_runtime_dependency "bcrypt", "~> 3.1.10"
|
27
27
|
spec.add_runtime_dependency "highline", "~> 1.6.21"
|
28
28
|
spec.add_runtime_dependency "i18n", "~> 0.7"
|
29
|
-
spec.add_runtime_dependency "linux_admin", "~> 1.0"
|
29
|
+
spec.add_runtime_dependency "linux_admin", ["~> 1.0", ">=1.2.2"]
|
30
30
|
spec.add_runtime_dependency "pg"
|
31
31
|
spec.add_runtime_dependency "trollop", "~> 2.0"
|
32
32
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-appliance_console
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -101,6 +101,9 @@ dependencies:
|
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '1.0'
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.2.2
|
104
107
|
type: :runtime
|
105
108
|
prerelease: false
|
106
109
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -108,6 +111,9 @@ dependencies:
|
|
108
111
|
- - "~>"
|
109
112
|
- !ruby/object:Gem::Version
|
110
113
|
version: '1.0'
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.2.2
|
111
117
|
- !ruby/object:Gem::Dependency
|
112
118
|
name: pg
|
113
119
|
requirement: !ruby/object:Gem::Requirement
|