morpheus-cli 8.0.1 → 8.0.3
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/Dockerfile +1 -1
- data/lib/morpheus/cli/cli_command.rb +18 -3
- data/lib/morpheus/cli/commands/clusters.rb +50 -44
- data/lib/morpheus/cli/commands/hosts.rb +9 -3
- data/lib/morpheus/cli/commands/instances.rb +37 -66
- data/lib/morpheus/cli/commands/library_cluster_layouts_command.rb +1 -1
- data/lib/morpheus/cli/commands/processes_command.rb +2 -2
- data/lib/morpheus/cli/commands/shell.rb +18 -39
- data/lib/morpheus/cli/commands/snapshots.rb +24 -8
- data/lib/morpheus/cli/commands/virtual_images.rb +71 -17
- data/lib/morpheus/cli/mixins/execution_request_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/processes_helper.rb +34 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +535 -324
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +1 -1
- data/test/cli/auth_test.rb +6 -0
- data/test/cli/roles_test.rb +15 -2
- data/test/test_case.rb +1 -0
- metadata +2 -2
@@ -172,11 +172,8 @@ EOT
|
|
172
172
|
id
|
173
173
|
else
|
174
174
|
image = find_virtual_image_by_name_or_id(id)
|
175
|
-
if image
|
176
|
-
|
177
|
-
else
|
178
|
-
raise_command_error "virtual image not found for name '#{id}'"
|
179
|
-
end
|
175
|
+
return 1, "virtual image not found for name '#{id}'" if image.nil?
|
176
|
+
image['id']
|
180
177
|
end
|
181
178
|
end
|
182
179
|
return run_command_for_each_arg(id_list) do |arg|
|
@@ -383,15 +380,16 @@ EOT
|
|
383
380
|
# storageProviderId, format, name
|
384
381
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
385
382
|
opts.banner = subcommand_usage("[image] [options]")
|
386
|
-
opts.on('-n', '--name NAME', String, "Name (optional) of the new converted image. Default is name of the original image.") do |val|
|
387
|
-
|
388
|
-
end
|
389
|
-
opts.on('-f', '--format FORMAT', String, "Format (optional). Default is 'qcow2'") do |val|
|
390
|
-
|
391
|
-
end
|
392
|
-
opts.on('--storageProvider VALUE', String, "Storage Provider ID (optional). Default is storage provider of the original image.") do |val|
|
393
|
-
|
394
|
-
end
|
383
|
+
# opts.on('-n', '--name NAME', String, "Name (optional) of the new converted image. Default is name of the original image.") do |val|
|
384
|
+
# options[:options]['name'] = val
|
385
|
+
# end
|
386
|
+
# opts.on('-f', '--format FORMAT', String, "Format (optional). Default is 'qcow2'") do |val|
|
387
|
+
# options[:options]['format'] = val
|
388
|
+
# end
|
389
|
+
# opts.on('--storageProvider VALUE', String, "Storage Provider ID (optional). Default is storage provider of the original image.") do |val|
|
390
|
+
# options[:options]['storageProvider'] = val.to_s
|
391
|
+
# end
|
392
|
+
build_option_type_options(opts, options, convert_virtual_image_option_types)
|
395
393
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
396
394
|
opts.footer = "Convert a virtual image to a new format." + "\n" +
|
397
395
|
"[image] is required. This is the name or id of a virtual image."
|
@@ -411,7 +409,18 @@ EOT
|
|
411
409
|
payload.deep_merge!({virtual_image_object_key => passed_options}) unless passed_options.empty?
|
412
410
|
else
|
413
411
|
virtual_image_payload = passed_options
|
414
|
-
|
412
|
+
source_format = virtual_image['imageType']
|
413
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(convert_virtual_image_option_types(source_format), options[:options], @api_client, {'virtualImageId': virtual_image['id']})
|
414
|
+
v_prompt.deep_compact!
|
415
|
+
virtual_image_payload.deep_merge!(v_prompt)
|
416
|
+
# support "storageProviderId" too
|
417
|
+
if virtual_image_payload['storageProviderId']
|
418
|
+
virtual_image_payload['storageProvider'] = virtual_image_payload.delete('storageProviderId')
|
419
|
+
end
|
420
|
+
# convert "storageProvider":1 to "storageProvider": {"id":1}
|
421
|
+
if virtual_image_payload['storageProvider'] && !virtual_image_payload['storageProvider'].is_a?(Hash)
|
422
|
+
virtual_image_payload['storageProvider'] = {'id' => virtual_image_payload['storageProvider'].to_i }
|
423
|
+
end
|
415
424
|
payload = virtual_image_payload
|
416
425
|
end
|
417
426
|
@virtual_images_interface.setopts(options)
|
@@ -990,11 +999,20 @@ EOT
|
|
990
999
|
|
991
1000
|
def find_virtual_image_by_name(name)
|
992
1001
|
json_results = @virtual_images_interface.list({name: name.to_s})
|
993
|
-
|
1002
|
+
records = json_results['virtualImages']
|
1003
|
+
if records.empty?
|
994
1004
|
print_red_alert "Virtual Image not found by name #{name}"
|
995
1005
|
return nil
|
1006
|
+
elsif records.size > 1
|
1007
|
+
print_red_alert "More than one Virtual Image found by name '#{name}'"
|
1008
|
+
print_error "\n"
|
1009
|
+
puts_error as_pretty_table(records, [:id, :name], {color:red})
|
1010
|
+
print_red_alert "Try using ID instead"
|
1011
|
+
print_error reset,"\n"
|
1012
|
+
return nil
|
1013
|
+
else
|
1014
|
+
virtual_image = records[0]
|
996
1015
|
end
|
997
|
-
virtual_image = json_results['virtualImages'][0]
|
998
1016
|
return virtual_image
|
999
1017
|
end
|
1000
1018
|
|
@@ -1074,6 +1092,42 @@ EOT
|
|
1074
1092
|
list
|
1075
1093
|
end
|
1076
1094
|
|
1095
|
+
def convert_virtual_image_option_types(source_format=nil)
|
1096
|
+
[
|
1097
|
+
{'shorthand' => '-f', 'fieldName' => 'format', 'type' => 'select', 'fieldLabel' => 'Format', 'selectOptions' => get_convert_image_formats(source_format), 'required' => true, 'defaultValue' => (source_format == 'qcow2' ? nil : 'qcow2')},
|
1098
|
+
{'shorthand' => '-b', 'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Bucket', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider Bucket or File Share.'},
|
1099
|
+
{'shorthand' => '-n', 'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false}
|
1100
|
+
]
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
def convert_source_types
|
1104
|
+
["raw","qcow2","vmdk",'vmware', "vhd","ovf"]
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def convert_destination_types
|
1108
|
+
#["raw", "qcow2", "vmdk",'vmware',"vhd","ovf"]
|
1109
|
+
convert_source_types
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def get_convert_image_formats(source_format=nil)
|
1113
|
+
categories = [
|
1114
|
+
{'name' => 'QCOW2', 'value' => 'qcow2'},
|
1115
|
+
{'name' => 'VMDK', 'value' => 'ovf'},
|
1116
|
+
{'name' => 'VHD', 'value' => 'vhd'},
|
1117
|
+
{'name' => 'Raw', 'value' => 'raw'}
|
1118
|
+
]
|
1119
|
+
# if source format (imageType) is not in the list, then no options
|
1120
|
+
# else reject the current value
|
1121
|
+
if source_format
|
1122
|
+
if !convert_source_types.include?(source_format.to_s.downcase)
|
1123
|
+
categories = []
|
1124
|
+
else
|
1125
|
+
categories = categories.select {|it| it['value'] != source_format.to_s.downcase }
|
1126
|
+
end
|
1127
|
+
end
|
1128
|
+
return categories
|
1129
|
+
end
|
1130
|
+
|
1077
1131
|
def format_tenants(accounts)
|
1078
1132
|
if accounts && accounts.size > 0
|
1079
1133
|
accounts = accounts.sort {|a,b| a['name'] <=> b['name'] }.uniq {|it| it['id'] }
|
@@ -29,7 +29,7 @@ module Morpheus::Cli::ExecutionRequestHelper
|
|
29
29
|
# unless options[:quiet]
|
30
30
|
# print cyan, "Execution request has not yet finished. Refreshing every #{refresh_display_seconds} seconds...", "\n", reset
|
31
31
|
# end
|
32
|
-
while
|
32
|
+
while (options[:waiting_status] || ['new', 'pending']).include?(execution_request['status']) do
|
33
33
|
sleep(refresh_interval)
|
34
34
|
execution_request = execution_request_interface.get(execution_request_id)['executionRequest']
|
35
35
|
end
|
@@ -8,8 +8,17 @@ module Morpheus::Cli::ProcessesHelper
|
|
8
8
|
klass.send :include, Morpheus::Cli::PrintHelper
|
9
9
|
end
|
10
10
|
|
11
|
+
def api_client
|
12
|
+
raise "#{self.class} has not defined @api_client" if @api_client.nil?
|
13
|
+
@api_client
|
14
|
+
end
|
15
|
+
|
16
|
+
def processes_interface
|
17
|
+
# get_interface('processes')
|
18
|
+
api_client.processes
|
19
|
+
end
|
11
20
|
|
12
|
-
def print_process_details(process)
|
21
|
+
def print_process_details(process, options={})
|
13
22
|
description_cols = {
|
14
23
|
"Process ID" => lambda {|it| it['id'] },
|
15
24
|
"Name" => lambda {|it| it['displayName'] },
|
@@ -22,7 +31,7 @@ module Morpheus::Cli::ProcessesHelper
|
|
22
31
|
"Status" => lambda {|it| format_process_status(it) },
|
23
32
|
# "# Events" => lambda {|it| (it['events'] || []).size() },
|
24
33
|
}
|
25
|
-
print_description_list(description_cols, process)
|
34
|
+
print_description_list(description_cols, process, options)
|
26
35
|
|
27
36
|
if process['error']
|
28
37
|
print_h2 "Error"
|
@@ -39,7 +48,7 @@ module Morpheus::Cli::ProcessesHelper
|
|
39
48
|
end
|
40
49
|
end
|
41
50
|
|
42
|
-
def print_process_event_details(process_event)
|
51
|
+
def print_process_event_details(process_event, options={})
|
43
52
|
# process_event =~ process
|
44
53
|
description_cols = {
|
45
54
|
"Process ID" => lambda {|it| it['processId'] },
|
@@ -53,7 +62,7 @@ module Morpheus::Cli::ProcessesHelper
|
|
53
62
|
"Duration" => lambda {|it| format_process_duration(it) },
|
54
63
|
"Status" => lambda {|it| format_process_status(it) },
|
55
64
|
}
|
56
|
-
print_description_list(description_cols, process_event)
|
65
|
+
print_description_list(description_cols, process_event, options)
|
57
66
|
|
58
67
|
if process_event['error']
|
59
68
|
print_h2 "Error"
|
@@ -111,4 +120,25 @@ module Morpheus::Cli::ProcessesHelper
|
|
111
120
|
out
|
112
121
|
end
|
113
122
|
|
123
|
+
def wait_for_process_execution(process_id, options={}, print_output = true)
|
124
|
+
refresh_interval = 10
|
125
|
+
if options[:refresh_interval].to_i > 0
|
126
|
+
refresh_interval = options[:refresh_interval]
|
127
|
+
end
|
128
|
+
refresh_display_seconds = refresh_interval % 1.0 == 0 ? refresh_interval.to_i : refresh_interval
|
129
|
+
unless options[:quiet]
|
130
|
+
print cyan, "Refreshing every #{refresh_display_seconds} seconds until process is complete...", "\n", reset
|
131
|
+
end
|
132
|
+
process = processes_interface.get(process_id)['process']
|
133
|
+
while ['new','queued','pending','running'].include?(process['status']) do
|
134
|
+
sleep(refresh_interval)
|
135
|
+
process = processes_interface.get(process_id)['process']
|
136
|
+
end
|
137
|
+
if print_output && options[:quiet] != true
|
138
|
+
print_h1 "Process Details", [], options
|
139
|
+
print_process_details(process, options)
|
140
|
+
end
|
141
|
+
return process
|
142
|
+
end
|
143
|
+
|
114
144
|
end
|