morpheus-cli 5.3.2.3 → 5.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -158,11 +158,13 @@ class Morpheus::Cli::MonitoringChecksCommand
158
158
  end
159
159
  },
160
160
  "Type" => lambda {|it| format_monitoring_check_type(it) },
161
+ "API Key" => lambda {|it| it['apiKey'] },
161
162
  "Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : "System" },
162
163
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
163
164
  "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
164
165
  # "Last Error" => lambda {|it| format_local_dt(it['lastErrorDate']) },
165
166
  }
167
+ description_cols.delete("API Key") if !['pushCheck'].include?(check['checkType']['code']) || check['apiKey'].nil?
166
168
  print_description_list(description_cols, check)
167
169
 
168
170
  # Last Error
@@ -619,7 +619,7 @@ class Morpheus::Cli::NetworksCommand
619
619
  api_params['network.site.id'] = group ? group['id'] : 'shared'
620
620
  api_params['network.type.id'] = network_type['id']
621
621
  api_params['network.networkServer.id'] = network_server_id if !network_server_id.nil?
622
- network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,options[:options],@api_client, api_params)
622
+ network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,(options[:options] || {}).merge(payload),@api_client, api_params)
623
623
  # network context options belong at network level and not network.network
624
624
  network_context_params = network_type_params.delete('network')
625
625
  payload['network'].deep_merge!(network_context_params) if network_context_params
@@ -32,27 +32,35 @@ module Morpheus
32
32
  #out << "Options:\n"
33
33
  # the default way..
34
34
  # out << summarize().join("")
35
-
36
35
  # super hacky, should be examining the option, not the fully formatted description
37
36
  my_summaries = summarize()
38
- summarize().each do |opt_description|
39
- is_hidden = (@hidden_options || []).find { |hidden_switch|
40
- # opt_description.include?("--#{hidden_switch}")
41
- if hidden_switch.start_with?("-")
42
- opt_description.to_s.strip.start_with?("#{hidden_switch} ")
43
- else
44
- opt_description.to_s.strip.start_with?("--#{hidden_switch} ")
45
- end
46
- }
47
- if is_hidden
48
- if opts[:show_hidden_options]
49
- # out << opt_description + " (hidden)"
50
- out << opt_description
37
+ if opts[:show_hidden_options]
38
+ my_summaries.each do |full_line|
39
+ out << full_line
40
+ end
41
+ else
42
+ on_hidden_option = false
43
+ my_summaries.each do |full_line|
44
+ opt_description = full_line.to_s.strip
45
+ if opt_description.start_with?("-")
46
+ is_hidden = (@hidden_options || []).find { |hidden_switch|
47
+ if hidden_switch.start_with?("-")
48
+ opt_description.start_with?("#{hidden_switch} ")
49
+ else
50
+ opt_description.start_with?("--#{hidden_switch} ")
51
+ end
52
+ }
53
+ if is_hidden
54
+ on_hidden_option = true
55
+ else
56
+ on_hidden_option = false
57
+ out << full_line
58
+ end
51
59
  else
52
- # hidden
60
+ if on_hidden_option == false
61
+ out << full_line
62
+ end
53
63
  end
54
- else
55
- out << opt_description
56
64
  end
57
65
  end
58
66
  end
@@ -61,11 +61,11 @@ module Morpheus
61
61
  ).each do |option_type|
62
62
  context_map = results
63
63
  value = nil
64
- value_found=false
64
+ value_found = false
65
+ field_group = (option_type['fieldGroup'] || 'default').to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
65
66
 
66
- if cur_field_group != (option_type['fieldGroup'] || 'default')
67
- cur_field_group = option_type['fieldGroup']
68
- cur_field_group = cur_field_group.to_s.sub(/options\Z/i, "").strip # avoid "ADVANCED OPTION OPTIONS"
67
+ if cur_field_group != field_group
68
+ cur_field_group = field_group
69
69
  print "\n#{cur_field_group.upcase} OPTIONS\n#{"=" * ("#{cur_field_group} OPTIONS".length)}\n\n"
70
70
  end
71
71
 
@@ -102,10 +102,10 @@ module Morpheus
102
102
  end
103
103
 
104
104
  found_dep_value = match_type == 'all' ? true : false
105
- visible_option_check_value.split(',').each do |value|
105
+ visible_option_check_value.sub(',', ' ').split(' ').each do |value|
106
106
  parts = value.split(':')
107
107
  depends_on_code = parts[0]
108
- depends_on_value = parts.count > 1 ? parts[1].to_s.strip : '.'
108
+ depends_on_value = parts.count > 1 ? parts[1].to_s.strip : nil
109
109
  depends_on_option_type = option_types.find {|it| it["code"] == depends_on_code }
110
110
  if !depends_on_option_type
111
111
  depends_on_option_type = option_types.find {|it|
@@ -115,13 +115,18 @@ module Morpheus
115
115
 
116
116
  if depends_on_option_type
117
117
  depends_on_field_key = depends_on_option_type['fieldContext'].nil? || depends_on_option_type['fieldContext'].empty? ? "#{depends_on_option_type['fieldName']}" : "#{depends_on_option_type['fieldContext']}.#{depends_on_option_type['fieldName']}"
118
- field_value = get_object_value(results, depends_on_field_key) || get_object_value(options, depends_on_field_key)
118
+ else
119
+ depends_on_field_key = depends_on_code
120
+ end
119
121
 
120
- if !field_value.nil? && field_value.match?(depends_on_value)
121
- found_dep_value = true if match_type != 'all'
122
- else
123
- found_dep_value = false if match_type == 'all'
124
- end
122
+ field_value = get_object_value(results, depends_on_field_key) ||
123
+ get_object_value(options, depends_on_field_key) ||
124
+ get_object_value(api_params, depends_on_field_key)
125
+
126
+ if !field_value.nil? && (depends_on_value.nil? || depends_on_value.empty? || field_value.match?(depends_on_value))
127
+ found_dep_value = true if match_type != 'all'
128
+ else
129
+ found_dep_value = false if match_type == 'all'
125
130
  end
126
131
  end
127
132
  next if !found_dep_value
@@ -237,7 +242,7 @@ module Morpheus
237
242
  # I suppose the entered value should take precedence
238
243
  # api_params = api_params.merge(options) # this might be good enough
239
244
  # dup it
240
- value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).merge(results)), options[:no_prompt], nil, paging_enabled)
245
+ value = select_prompt(option_type, api_client, (option_type['noParams'] ? {} : (api_params || {}).deep_merge(results)), options[:no_prompt], nil, paging_enabled)
241
246
  if value && option_type['type'] == 'multiSelect'
242
247
  value = [value]
243
248
  while self.confirm("Add another #{option_type['fieldLabel']}?", {:default => false}) do
@@ -276,7 +281,8 @@ module Morpheus
276
281
  value = [value] if !value.nil? && !value.is_a?(Array)
277
282
  # parent_context_map[parent_ns] = value
278
283
  end
279
- context_map[field_name] = value
284
+ context_map[field_name] = value if !(value.nil? || (value.is_a?(Hash) && value.empty?))
285
+ parent_context_map.reject! {|k,v| k == parent_ns && (v.nil? || (v.is_a?(Hash) && v.empty?))}
280
286
  end
281
287
  results
282
288
  end
@@ -947,8 +953,9 @@ module Morpheus
947
953
  out << "\n"
948
954
  out << "#{header}\n"
949
955
  out << "#{'=' * header.length}\n"
956
+
950
957
  select_options.each do |option|
951
- out << " * #{option['name']} [#{option['value']}]\n"
958
+ out << (option['isGroup'] ? "- #{option['name']}\n" : " * #{option['name']} [#{option['value']}]\n")
952
959
  end
953
960
  return out
954
961
  end
@@ -418,6 +418,7 @@ EOT
418
418
  "Name" => 'name',
419
419
  "Description" => 'description',
420
420
  "Persistent" => lambda {|it| format_boolean(it['persistentUser']) },
421
+ "Recyclable" => lambda {|it| it['recyclable'].nil? ? nil : format_boolean(it['recyclable']) },
421
422
  "Enabled" => lambda {|it| format_boolean(it['enabled']) },
422
423
  "Pool Usage" => lambda {|it|
423
424
  # todo: [== ] 2/8 would be neat generate_usage_bar(...)
@@ -447,12 +448,13 @@ EOT
447
448
  "Max Size" => lambda {|it| format_number(it['maxPoolSize']) rescue '' },
448
449
  "Lease Timeout" => lambda {|it| format_number(it['allocationTimeoutMinutes']) rescue '' },
449
450
  "Persistent" => lambda {|it| format_boolean(it['persistentUser']) },
451
+ "Recyclable" => lambda {|it| it['recyclable'].nil? ? nil : format_boolean(it['recyclable']) },
452
+ "Enabled" => lambda {|it| format_boolean(it['enabled']) },
450
453
  "Allow Copy" => lambda {|it| format_boolean(it['allowCopy']) },
451
454
  "Allow Printer" => lambda {|it| format_boolean(it['allowPrinter']) },
452
455
  "Allow File Share" => lambda {|it| format_boolean(it['allowFileshare']) },
453
456
  "Allow Hypervisor Console" => lambda {|it| format_boolean(it['allowHypervisorConsole']) },
454
457
  "Auto Create User" => lambda {|it| format_boolean(it['autoCreateLocalUserOnReservation']) },
455
- "Enabled" => lambda {|it| format_boolean(it['enabled']) },
456
458
  "Logo" => lambda {|it| it['logo'] || it['imagePath'] },
457
459
  #"Config" => lambda {|it| it['config'] },
458
460
  "Group" => lambda {|it| it['group'] ? it['group']['name'] : nil },
@@ -484,6 +486,7 @@ EOT
484
486
  {'fieldName' => 'maxPoolSize', 'fieldLabel' => 'Max Size', 'type' => 'number', 'required' => true, 'description' => 'Max limit on number of allocations and instances within the pool.'},
485
487
  {'fieldName' => 'allocationTimeoutMinutes', 'fieldLabel' => 'Lease Timeout', 'type' => 'number', 'description' => 'Time (in minutes) after a user disconnects before an allocation is recycled or shutdown depending on persistence.'},
486
488
  {'fieldName' => 'persistentUser', 'fieldLabel' => 'Persistent', 'type' => 'checkbox', 'defaultValue' => false},
489
+ {'fieldName' => 'recyclable', 'fieldLabel' => 'Recyclable', 'type' => 'checkbox', 'defaultValue' => false, 'description' => 'Recyclable VDI Pools only work with cloud types that support snapshot management (i.e. Vmware, Nutanix, VCD)'},
487
490
  {'fieldName' => 'allowCopy', 'fieldLabel' => 'Allow Copy', 'type' => 'checkbox', 'defaultValue' => false},
488
491
  {'fieldName' => 'allowPrinter', 'fieldLabel' => 'Allow Printer', 'type' => 'checkbox', 'defaultValue' => false},
489
492
  {'fieldName' => 'allowFileshare', 'fieldLabel' => 'Allow File Share', 'type' => 'checkbox', 'defaultValue' => false},
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.3.2.3"
4
+ VERSION = "5.3.3"
5
5
  end
6
6
  end
@@ -11,8 +11,7 @@ class Morpheus::Cli::VirtualImages
11
11
  include Morpheus::Cli::ProvisioningHelper
12
12
 
13
13
  register_subcommands :list, :get, :add, :add_file, :remove_file, :update, :remove, :types => :virtual_image_types
14
- alias_subcommand :details, :get
15
- set_default_subcommand :list
14
+ register_subcommands :list_locations, :get_location, :remove_location
16
15
 
17
16
  # def initialize()
18
17
  # # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -188,6 +187,7 @@ EOT
188
187
  image = json_response['virtualImage']
189
188
  image_config = image['config'] || {}
190
189
  image_volumes = image['volumes'] || []
190
+ image_locations = image['locations'] || []
191
191
  image_files = json_response['cloudFiles'] || json_response['files']
192
192
  image_type = virtual_image_type_for_name_or_code(image['imageType'])
193
193
  image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
@@ -255,7 +255,7 @@ EOT
255
255
  # print "\n", reset
256
256
  end
257
257
 
258
- if image_files
258
+ if image_files && !image_files.empty?
259
259
  print_h2 "Files (#{image_files.size})"
260
260
  # image_files.each {|image_file|
261
261
  # pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
@@ -270,6 +270,11 @@ EOT
270
270
  print as_pretty_table(image_file_rows, [:filename, :size])
271
271
  # print reset,"\n"
272
272
  end
273
+
274
+ if image_locations && !image_locations.empty?
275
+ print_h2 "Locations", options
276
+ print as_pretty_table(image_locations, virtual_image_location_list_column_definitions.upcase_keys!, options)
277
+ end
273
278
 
274
279
  if options[:details] && image_config && !image_config.empty?
275
280
  print_h2 "Config", options
@@ -689,7 +694,7 @@ EOT
689
694
  image = find_virtual_image_by_name_or_id(image_name)
690
695
  return 1 if image.nil?
691
696
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image filename #{filename}?")
692
- exit
697
+ return 9, "aborted"
693
698
  end
694
699
  @virtual_images_interface.setopts(options)
695
700
  if options[:dry_run]
@@ -709,44 +714,188 @@ EOT
709
714
  end
710
715
 
711
716
  def remove(args)
717
+ params = {}
712
718
  options = {}
713
719
  optparse = Morpheus::Cli::OptionParser.new do |opts|
714
- opts.banner = subcommand_usage("[name]")
715
- build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
720
+ opts.banner = subcommand_usage("[image] [location]")
721
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from all clouds. Default is true.") do |val|
722
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
723
+ end
724
+ build_standard_remove_options(opts, options)
725
+ opts.footer = <<-EOT
726
+ Delete a virtual image.
727
+ [image] is required. This is the name or id of a virtual image.
728
+ EOT
716
729
  end
717
730
  optparse.parse!(args)
718
- if args.count < 1
719
- puts optparse
720
- exit 1
731
+ verify_args!(args:args, optparse:optparse, count:1)
732
+ connect(options)
733
+ image = find_virtual_image_by_name_or_id(args[0])
734
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
735
+ params.merge!(parse_query_options(options))
736
+ # Delete prompt
737
+ # [ X ] Remove from all clouds
738
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'removeFromCloud', 'fieldLabel' => 'Remove from all clouds', 'type' => 'checkbox', 'defaultValue' => true, 'required' => true, 'description' => "Remove from all clouds"}], options[:options], @api_client)
739
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
740
+ params['removeFromCloud'] = remove_from_cloud
741
+
742
+ # Delete confirmation
743
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image #{image['name']}?")
744
+ return 9, "aborted"
745
+ end
746
+
747
+ @virtual_images_interface.setopts(options)
748
+ if options[:dry_run]
749
+ print_dry_run @virtual_images_interface.dry.destroy(image['id'], params)
750
+ return
751
+ end
752
+ json_response = @virtual_images_interface.destroy(image['id'], params)
753
+ render_response(json_response, options) do
754
+ print_green_success "Removed virtual image #{image['name']}"
755
+ end
756
+ return 0, nil
757
+ end
758
+
759
+ def list_locations(args)
760
+ params = {}
761
+ options = {}
762
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
763
+ opts.banner = subcommand_usage("[image]")
764
+ build_standard_list_options(opts, options)
765
+ opts.footer = <<-EOT
766
+ List virtual image locations for a specific virtual image.
767
+ [image] is required. This is the name or id of a virtual image.
768
+ EOT
769
+ end
770
+ optparse.parse!(args)
771
+ verify_args!(args:args, optparse:optparse, min:1)
772
+ if args.count > 1
773
+ options[:phrase] = args[1..-1].join(" ")
721
774
  end
722
- image_name = args[0]
723
775
  connect(options)
724
- begin
725
- image = find_virtual_image_by_name_or_id(image_name)
726
- return 1 if image.nil?
727
- unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image #{image['name']}?")
728
- exit
729
- end
730
- @virtual_images_interface.setopts(options)
731
- if options[:dry_run]
732
- print_dry_run @virtual_images_interface.dry.destroy(image['id'])
733
- return
734
- end
735
- json_response = @virtual_images_interface.destroy(image['id'])
736
- if options[:json]
737
- print JSON.pretty_generate(json_response)
776
+ image = find_virtual_image_by_name_or_id(args[0])
777
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
778
+ params.merge!(parse_list_options(options))
779
+ @virtual_images_interface.setopts(options)
780
+ if options[:dry_run]
781
+ print_dry_run @virtual_images_interface.dry.list_locations(image['id'], params)
782
+ return
783
+ end
784
+ json_response = @virtual_images_interface.list_locations(image['id'], params)
785
+ records = json_response['locations']
786
+ render_response(json_response, options, 'virtualImages') do
787
+ title = "Virtual Image Locations"
788
+ subtitles = parse_list_subtitles(options)
789
+ print_h1 title, subtitles
790
+ if records.empty?
791
+ print cyan,"No virtual image locations found.",reset,"\n"
738
792
  else
739
- print "\n", cyan, "Virtual Image #{image['name']} removed", reset, "\n\n"
793
+ print as_pretty_table(records, virtual_image_location_list_column_definitions.upcase_keys!, options)
794
+ print_results_pagination(json_response)
740
795
  end
741
- rescue RestClient::Exception => e
742
- print_rest_exception(e, options)
743
- exit 1
796
+ print reset,"\n"
797
+ end
798
+ return 0, nil
799
+ end
800
+
801
+ def get_location(args)
802
+ params = {}
803
+ options = {}
804
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
805
+ opts.banner = subcommand_usage("[image] [location]")
806
+ build_standard_remove_options(opts, options)
807
+ opts.footer = <<-EOT
808
+ Get details about a virtual image location.
809
+ [image] is required. This is the name or id of a virtual image.
810
+ [location] is required. This is the name or id of a virtual image location.
811
+ EOT
744
812
  end
813
+ optparse.parse!(args)
814
+ verify_args!(args:args, optparse:optparse, count:2)
815
+ connect(options)
816
+ image = find_virtual_image_by_name_or_id(args[0])
817
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
818
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
819
+ return 1, "location not found for '#{args[1]}'" if location.nil?
820
+ params.merge!(parse_query_options(options))
821
+ @virtual_images_interface.setopts(options)
822
+ if options[:dry_run]
823
+ print_dry_run @virtual_images_interface.dry.get_location(image['id'], location['id'])
824
+ return 0, nil
825
+ end
826
+ # json_response = @virtual_images_interface.get(image['id'], location['id'])
827
+ json_response = {'location' => location} # skip redundant request
828
+ render_response(json_response, options, 'location') do
829
+ location = json_response['location']
830
+ volumes = location['volumes'] || []
831
+ print_h1 "Virtual Image Location Details", [], options
832
+ print_description_list(virtual_image_location_column_definitions, location, options)
833
+ if volumes && !volumes.empty?
834
+ print_h2 "Volumes", options
835
+ volume_rows = location_volumes.collect do |volume|
836
+ {name: volume['name'], size: Filesize.from("#{volume['rawSize']} B").pretty}
837
+ end
838
+ print cyan
839
+ print as_pretty_table(volume_rows, [:name, :size], options)
840
+ print cyan
841
+ # print "\n", reset
842
+ end
843
+ print reset,"\n"
844
+ end
845
+ return 0, nil
745
846
  end
746
847
 
848
+ def remove_location(args)
849
+ params = {}
850
+ options = {}
851
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
852
+ opts.banner = subcommand_usage("[image] [location]")
853
+ opts.on('--remove-from-cloud [true|false]', String, "Remove from cloud. Default is true.") do |val|
854
+ options[:options]['removeFromCloud'] = ['','true','on'].include?(val.to_s)
855
+ end
856
+ build_standard_remove_options(opts, options)
857
+ opts.footer = <<-EOT
858
+ Delete a virtual image location.
859
+ [image] is required. This is the name or id of a virtual image.
860
+ [location] is required. This is the name or id of a virtual image location.
861
+ EOT
862
+ end
863
+ optparse.parse!(args)
864
+ verify_args!(args:args, optparse:optparse, count:2)
865
+ connect(options)
866
+ image = find_virtual_image_by_name_or_id(args[0])
867
+ return 1, "virtual image not found for '#{args[0]}'" if image.nil?
868
+ location = find_virtual_image_location_by_name_or_id(image['id'], args[1])
869
+ return 1, "location not found for '#{args[1]}'" if location.nil?
870
+
871
+ params.merge!(parse_query_options(options))
872
+
873
+ # Delete prompt
874
+ # [ X ] Remove from cloud
875
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'removeFromCloud', 'fieldLabel' => 'Remove from cloud', 'type' => 'checkbox', 'defaultValue' => true, 'required' => true, 'description' => "Remove from cloud"}], options[:options], @api_client)
876
+ remove_from_cloud = v_prompt['removeFromCloud'].to_s == 'true' || v_prompt['removeFromCloud'].to_s == 'on'
877
+ params['removeFromCloud'] = remove_from_cloud
878
+
879
+ # Delete confirmation
880
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the virtual image location #{location['id']}?")
881
+ return 9, "aborted"
882
+ end
883
+
884
+ @virtual_images_interface.setopts(options)
885
+ if options[:dry_run]
886
+ print_dry_run @virtual_images_interface.dry.destroy_location(image['id'], location['id'], params)
887
+ return
888
+ end
889
+ json_response = @virtual_images_interface.destroy_location(image['id'], location['id'], params)
890
+ render_response(json_response, options) do
891
+ print_green_success "Removed virtual image location #{location['id']}"
892
+ end
893
+ return 0, nil
894
+ end
747
895
 
748
896
  private
749
- def find_virtual_image_by_name_or_id(val)
897
+
898
+ def find_virtual_image_by_name_or_id(val)
750
899
  if val.to_s =~ /\A\d{1,}\Z/
751
900
  return find_virtual_image_by_id(val)
752
901
  else
@@ -911,4 +1060,75 @@ EOT
911
1060
  out
912
1061
  end
913
1062
 
1063
+
1064
+ ## Virtual Image Locations
1065
+
1066
+ def virtual_image_location_object_key
1067
+ "location"
1068
+ end
1069
+
1070
+ def virtual_image_location_list_key
1071
+ "locations"
1072
+ end
1073
+
1074
+ def find_virtual_image_location_by_name_or_id(virtual_image_id, val)
1075
+ if val.to_s =~ /\A\d{1,}\Z/
1076
+ return find_virtual_image_location_by_id(virtual_image_id, val)
1077
+ else
1078
+ return find_virtual_image_location_by_name(virtual_image_id, val)
1079
+ end
1080
+ end
1081
+
1082
+ def virtual_image_location_list_column_definitions
1083
+ virtual_image_location_column_definitions
1084
+ end
1085
+
1086
+ def virtual_image_location_column_definitions
1087
+ {
1088
+ "ID" => 'id',
1089
+ "Name" => 'imageName',
1090
+ "Cloud" => lambda {|it| it['cloud']['name'] rescue '' },
1091
+ "Public" => lambda {|it| format_boolean(it['isPublic']) },
1092
+ "Region" => lambda {|it| it['imageRegion'] },
1093
+ "External ID" => lambda {|it| it['externalId'] },
1094
+ "Price Plan" => lambda {|it| it['pricePlan'] ? it['pricePlan']['name'] : nil },
1095
+ # "Virtual Image" => lambda {|it| it['virtualImage']['name'] rescue '' },
1096
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
1097
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
1098
+ }
1099
+ end
1100
+
1101
+
1102
+ def find_virtual_image_location_by_id(virtual_image_id, id)
1103
+ begin
1104
+ json_response = @virtual_images_interface.get_location(virtual_image_id, id.to_i)
1105
+ return json_response[virtual_image_location_object_key]
1106
+ rescue RestClient::Exception => e
1107
+ if e.response && e.response.code == 404
1108
+ print_red_alert "Virtual Image Location not found by id '#{id}'"
1109
+ else
1110
+ raise e
1111
+ end
1112
+ end
1113
+ end
1114
+
1115
+ def find_virtual_image_location_by_name(virtual_image_id, name)
1116
+ json_response = @virtual_images_interface.list_locations(virtual_image_id, {imageName: name.to_s})
1117
+ virtual_image_locations = json_response[virtual_image_location_list_key]
1118
+ if virtual_image_locations.empty?
1119
+ print_red_alert "Virtual Image Location not found by name '#{name}'"
1120
+ return nil
1121
+ elsif virtual_image_locations.size > 1
1122
+ print_red_alert "#{virtual_image_locations.size} Virtual Image Locations found by name '#{name}'"
1123
+ print_error "\n"
1124
+ puts_error as_pretty_table(virtual_image_locations, {"ID" => 'id', "NAME" => 'imageName'}, {color:red})
1125
+ print_red_alert "Try using ID instead"
1126
+ print_error reset,"\n"
1127
+ return nil
1128
+ else
1129
+ return virtual_image_locations[0]
1130
+ end
1131
+ end
1132
+
1133
+
914
1134
  end