manageiq-appliance_console 3.2.0 → 3.3.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.
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
|