morpheus-cli 5.2.4.1 → 5.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +1 -3
  4. data/lib/morpheus/api/api_client.rb +48 -14
  5. data/lib/morpheus/api/certificate_types_interface.rb +14 -0
  6. data/lib/morpheus/api/certificates_interface.rb +9 -0
  7. data/lib/morpheus/api/integration_types_interface.rb +14 -0
  8. data/lib/morpheus/api/integrations_interface.rb +7 -22
  9. data/lib/morpheus/api/network_services_interface.rb +14 -0
  10. data/lib/morpheus/api/read_interface.rb +23 -0
  11. data/lib/morpheus/api/rest_interface.rb +12 -10
  12. data/lib/morpheus/api/roles_interface.rb +7 -0
  13. data/lib/morpheus/api/servers_interface.rb +7 -0
  14. data/lib/morpheus/api/user_settings_interface.rb +38 -18
  15. data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
  16. data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
  17. data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
  18. data/lib/morpheus/api/vdi_interface.rb +28 -0
  19. data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
  20. data/lib/morpheus/cli.rb +9 -2
  21. data/lib/morpheus/cli/activity_command.rb +7 -4
  22. data/lib/morpheus/cli/apps.rb +59 -75
  23. data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
  24. data/lib/morpheus/cli/certificates_command.rb +575 -0
  25. data/lib/morpheus/cli/cli_command.rb +61 -6
  26. data/lib/morpheus/cli/clouds.rb +1 -0
  27. data/lib/morpheus/cli/clusters.rb +5 -2
  28. data/lib/morpheus/cli/commands/standard/history_command.rb +4 -5
  29. data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
  30. data/lib/morpheus/cli/dashboard_command.rb +3 -3
  31. data/lib/morpheus/cli/execution_request_command.rb +15 -5
  32. data/lib/morpheus/cli/hosts.rb +245 -224
  33. data/lib/morpheus/cli/instances.rb +150 -167
  34. data/lib/morpheus/cli/integrations_command.rb +588 -41
  35. data/lib/morpheus/cli/invoices_command.rb +23 -46
  36. data/lib/morpheus/cli/login.rb +7 -0
  37. data/lib/morpheus/cli/mixins/option_source_helper.rb +15 -16
  38. data/lib/morpheus/cli/mixins/print_helper.rb +36 -18
  39. data/lib/morpheus/cli/mixins/provisioning_helper.rb +3 -3
  40. data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
  41. data/lib/morpheus/cli/network_domains_command.rb +2 -2
  42. data/lib/morpheus/cli/network_routers_command.rb +22 -9
  43. data/lib/morpheus/cli/networks_command.rb +2 -2
  44. data/lib/morpheus/cli/option_types.rb +34 -33
  45. data/lib/morpheus/cli/remote.rb +3 -2
  46. data/lib/morpheus/cli/reports_command.rb +5 -2
  47. data/lib/morpheus/cli/roles.rb +215 -55
  48. data/lib/morpheus/cli/service_plans_command.rb +4 -1
  49. data/lib/morpheus/cli/subnets_command.rb +11 -2
  50. data/lib/morpheus/cli/user_settings_command.rb +268 -57
  51. data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
  52. data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
  53. data/lib/morpheus/cli/vdi_command.rb +359 -0
  54. data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
  55. data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
  56. data/lib/morpheus/cli/version.rb +1 -1
  57. data/lib/morpheus/rest_client.rb +30 -0
  58. data/lib/morpheus/terminal.rb +15 -7
  59. metadata +18 -2
@@ -140,32 +140,32 @@ class Morpheus::Cli::InvoicesCommand
140
140
  # construct params
141
141
  params.merge!(parse_list_options(options))
142
142
  if options[:clouds]
143
- cloud_ids = parse_cloud_id_list(options[:clouds])
143
+ cloud_ids = parse_cloud_id_list(options[:clouds], {}, false, true)
144
144
  return 1, "clouds not found for #{options[:clouds]}" if cloud_ids.nil?
145
145
  params['zoneId'] = cloud_ids
146
146
  end
147
147
  if options[:groups]
148
- group_ids = parse_group_id_list(options[:groups])
148
+ group_ids = parse_group_id_list(options[:groups], {}, false, true)
149
149
  return 1, "groups not found for #{options[:groups]}" if group_ids.nil?
150
150
  params['siteId'] = group_ids
151
151
  end
152
152
  if options[:instances]
153
- instance_ids = parse_instance_id_list(options[:instances])
153
+ instance_ids = parse_instance_id_list(options[:instances], {}, false, true)
154
154
  return 1, "instances not found for #{options[:instances]}" if instance_ids.nil?
155
155
  params['instanceId'] = instance_ids
156
156
  end
157
157
  if options[:servers]
158
- server_ids = parse_server_id_list(options[:servers])
158
+ server_ids = parse_server_id_list(options[:servers], {}, false, true)
159
159
  return 1, "servers not found for #{options[:servers]}" if server_ids.nil?
160
160
  params['serverId'] = server_ids
161
161
  end
162
162
  if options[:users]
163
- user_ids = parse_user_id_list(options[:users])
163
+ user_ids = parse_user_id_list(options[:users], {}, false, true)
164
164
  return 1, "users not found for #{options[:users]}" if user_ids.nil?
165
165
  params['userId'] = user_ids
166
166
  end
167
167
  if options[:projects]
168
- project_ids = parse_project_id_list(options[:projects])
168
+ project_ids = parse_project_id_list(options[:projects], {}, false, true)
169
169
  return 1, "projects not found for #{options[:projects]}" if project_ids.nil?
170
170
  params['projectId'] = project_ids
171
171
  end
@@ -636,37 +636,20 @@ Update an invoice.
636
636
  params = {}
637
637
  payload = {}
638
638
  optparse = Morpheus::Cli::OptionParser.new do |opts|
639
- opts.banner = subcommand_usage("[--daily] [--costing] [--current] [-c CLOUD]")
640
- opts.on( '--daily', "Refresh Daily Invoices" ) do
641
- payload[:daily] = true
642
- end
643
- opts.on( '--costing', "Refresh Costing Data" ) do
644
- payload[:costing] = true
645
- end
646
- opts.on( '--current', "Collect the most up to date costing data." ) do
647
- payload[:current] = true
648
- end
649
- opts.on( '--date DATE', String, "Date to collect costing for. By default the cost data is collected for the end of the previous period." ) do |val|
650
- payload[:date] = val.to_s
651
- end
652
- opts.on( '-c', '--cloud CLOUD', "Specify cloud(s) to refresh costing for." ) do |val|
639
+ opts.banner = subcommand_usage("[-c CLOUD]")
640
+ opts.on( '-c', '--clouds CLOUD', "Specify clouds to refresh costing for." ) do |val|
653
641
  payload[:clouds] ||= []
654
642
  payload[:clouds] << val
655
643
  end
656
- opts.on( '--all', "Refresh costing for all clouds." ) do
644
+ opts.on( '--all', "Refresh costing for all clouds. This can be used instead of --clouds" ) do
657
645
  payload[:all] = true
658
646
  end
659
- # opts.on( '-f', '--force', "Force Refresh" ) do
660
- # query_params[:force] = 'true'
661
- # end
647
+ opts.on( '--date DATE', String, "Date to collect costing for. By default the cost data is collected for the end of the previous job interval (hour or day)." ) do |val|
648
+ payload[:date] = val.to_s
649
+ end
662
650
  build_standard_update_options(opts, options, [:query, :auto_confirm])
663
651
  opts.footer = <<-EOT
664
- Refresh invoices.
665
- By default, nothing is changed.
666
- Include --daily to regenerate invoice records.
667
- Include --costing to refresh actual costing data.
668
- Include --current to refresh costing data for the actual current time.
669
- To get the latest invoice costing data, include --daily --costing --current --all
652
+ Refresh invoice costing data for the specified clouds.
670
653
  EOT
671
654
  end
672
655
  optparse.parse!(args)
@@ -677,17 +660,11 @@ EOT
677
660
  payload = options[:payload]
678
661
  end
679
662
  payload.deep_merge!(parse_passed_options(options))
680
- # --clouds
663
+ # --clouds lookup ID for name
681
664
  if payload[:clouds]
682
- payload[:clouds] = parse_id_list(payload[:clouds]).collect {|cloud_id|
683
- if cloud_id.to_s =~ /\A\d{1,}\Z/
684
- cloud_id
685
- else
686
- cloud = find_cloud_option(cloud_id)
687
- return 1 if cloud.nil?
688
- cloud['id']
689
- end
690
- }
665
+ cloud_ids = parse_cloud_id_list(payload[:clouds], {}, false, true)
666
+ return 1, "clouds not found for #{payload[:clouds]}" if cloud_ids.nil?
667
+ payload[:clouds] = cloud_ids
691
668
  end
692
669
  # are you sure?
693
670
  unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to refresh invoices?")
@@ -831,32 +808,32 @@ EOT
831
808
  # construct params
832
809
  params.merge!(parse_list_options(options))
833
810
  if options[:clouds]
834
- cloud_ids = parse_cloud_id_list(options[:clouds])
811
+ cloud_ids = parse_cloud_id_list(options[:clouds], {}, false, true)
835
812
  return 1, "clouds not found for #{options[:clouds]}" if cloud_ids.nil?
836
813
  params['zoneId'] = cloud_ids
837
814
  end
838
815
  if options[:groups]
839
- group_ids = parse_group_id_list(options[:groups])
816
+ group_ids = parse_group_id_list(options[:groups], {}, false, true)
840
817
  return 1, "groups not found for #{options[:groups]}" if group_ids.nil?
841
818
  params['siteId'] = group_ids
842
819
  end
843
820
  if options[:instances]
844
- instance_ids = parse_instance_id_list(options[:instances])
821
+ instance_ids = parse_instance_id_list(options[:instances], {}, false, true)
845
822
  return 1, "instances not found for #{options[:instances]}" if instance_ids.nil?
846
823
  params['instanceId'] = instance_ids
847
824
  end
848
825
  if options[:servers]
849
- server_ids = parse_server_id_list(options[:servers])
826
+ server_ids = parse_server_id_list(options[:servers], {}, false, true)
850
827
  return 1, "servers not found for #{options[:servers]}" if server_ids.nil?
851
828
  params['serverId'] = server_ids
852
829
  end
853
830
  if options[:users]
854
- user_ids = parse_user_id_list(options[:users])
831
+ user_ids = parse_user_id_list(options[:users], {}, false, true)
855
832
  return 1, "users not found for #{options[:users]}" if user_ids.nil?
856
833
  params['userId'] = user_ids
857
834
  end
858
835
  if options[:projects]
859
- project_ids = parse_project_id_list(options[:projects])
836
+ project_ids = parse_project_id_list(options[:projects], {}, false, true)
860
837
  return 1, "projects not found for #{options[:projects]}" if project_ids.nil?
861
838
  params['projectId'] = project_ids
862
839
  end
@@ -36,6 +36,13 @@ class Morpheus::Cli::Login
36
36
  opts.on( '-p', '--password PASSWORD', "Password" ) do |val|
37
37
  password = val
38
38
  end
39
+ opts.on( '--password-file FILE', String, "Password File, read a file containing the password." ) do |val|
40
+ password_file = File.expand_path(val)
41
+ if !File.exists?(password_file) || !File.file?(password_file) # check readable too
42
+ raise ::OptionParser::InvalidOption.new("File not found: #{password_file}")
43
+ end
44
+ password = File.read(password_file) #.to_s.split("\n").first.strip
45
+ end
39
46
  opts.on( '-t', '--test', "Test credentials only, does not update stored credentials for the appliance." ) do
40
47
  options[:test_only] = true
41
48
  end
@@ -178,7 +178,7 @@ module Morpheus::Cli::OptionSourceHelper
178
178
  # todo: some other common ones, accounts (tenants), etc.
179
179
  # todo: a generic set of parse and find methods like
180
180
  # like this:
181
- def parse_option_source_id_list(option_source, id_list, api_params={}, refresh=false)
181
+ def parse_option_source_id_list(option_source, id_list, api_params={}, refresh=false, allow_any_id=false)
182
182
  option_source_label = option_source.to_s # .capitalize
183
183
  option_data = load_option_source_data(option_source, api_params, refresh)
184
184
  found_ids = []
@@ -189,9 +189,8 @@ module Morpheus::Cli::OptionSourceHelper
189
189
  # never match blank nil or empty strings
190
190
  print_red_alert "#{option_source_label} cannot be not found by with a blank id!"
191
191
  return nil
192
- # elsif record_id.to_s =~ /\A\d{1,}\Z/
193
- # # always allow any ID for now..
194
- # found_ids << record_id
192
+ elsif allow_any_id && record_id.to_s =~ /\A\d{1,}\Z/
193
+ found_ids << record_id.to_i
195
194
  else
196
195
  # search with in a presedence by value, then name, then id (usually same as value)
197
196
  # exact match on value first.
@@ -228,28 +227,28 @@ module Morpheus::Cli::OptionSourceHelper
228
227
  return found_ids
229
228
  end
230
229
 
231
- def parse_cloud_id_list(id_list, api_params={}, refresh=false)
232
- parse_option_source_id_list('clouds', id_list, api_params, refresh)
230
+ def parse_cloud_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
231
+ parse_option_source_id_list('clouds', id_list, api_params, refresh, allow_any_id)
233
232
  end
234
233
 
235
- def parse_group_id_list(id_list, api_params={}, refresh=false)
236
- parse_option_source_id_list('groups', id_list, api_params, refresh)
234
+ def parse_group_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
235
+ parse_option_source_id_list('groups', id_list, api_params, refresh, allow_any_id)
237
236
  end
238
237
 
239
- def parse_user_id_list(id_list, api_params={}, refresh=false)
240
- parse_option_source_id_list('users', id_list, api_params, refresh)
238
+ def parse_user_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
239
+ parse_option_source_id_list('users', id_list, api_params, refresh, allow_any_id)
241
240
  end
242
241
 
243
- def parse_tenant_id_list(id_list, api_params={}, refresh=false)
244
- parse_option_source_id_list('allTenants', id_list, api_params, refresh)
242
+ def parse_tenant_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
243
+ parse_option_source_id_list('allTenants', id_list, api_params, refresh, allow_any_id)
245
244
  end
246
245
 
247
- # def parse_blueprints_id_list(id_list)
248
- # parse_option_source_id_list('blueprints', id_list, api_params, refresh)
246
+ # def parse_blueprints_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
247
+ # parse_option_source_id_list('blueprints', id_list, api_params, refresh, allow_any_id)
249
248
  # end
250
249
 
251
- def parse_project_id_list(id_list, api_params={}, refresh=false)
252
- parse_option_source_id_list('projects', id_list, api_params, refresh)
250
+ def parse_project_id_list(id_list, api_params={}, refresh=false, allow_any_id=false)
251
+ parse_option_source_id_list('projects', id_list, api_params, refresh, allow_any_id)
253
252
  end
254
253
 
255
254
  end
@@ -228,7 +228,8 @@ module Morpheus::Cli::PrintHelper
228
228
  out << cyan
229
229
  if payload
230
230
  out << "\n"
231
- content_type = (headers && headers['Content-Type']) ? headers['Content-Type'] : 'application/x-www-form-urlencoded'
231
+ is_multipart = (payload.is_a?(Hash) && payload[:multipart] == true)
232
+ content_type = (headers && headers['Content-Type']) ? headers['Content-Type'] : (is_multipart ? 'multipart/form-data' : 'application/x-www-form-urlencoded')
232
233
  if content_type == 'application/json'
233
234
  if payload.is_a?(String)
234
235
  begin
@@ -257,12 +258,21 @@ module Morpheus::Cli::PrintHelper
257
258
  out << payload
258
259
  end
259
260
  else
260
- if content_type == 'application/x-www-form-urlencoded'
261
+ if content_type == 'application/x-www-form-urlencoded' || content_type.to_s.include?('multipart')
261
262
  body_str = payload.to_s
262
263
  begin
264
+ payload.delete(:multipart) if payload.is_a?(Hash)
265
+ # puts "grailsifying it!"
266
+ payload = Morpheus::RestClient.grails_params(payload)
267
+ payload.each do |k,v|
268
+ if v.is_a?(File)
269
+ payload[k] = "@#{v.path}"
270
+ payload[k] = v.path
271
+ end
272
+ end
263
273
  body_str = URI.encode_www_form(payload)
264
274
  rescue => ex
265
- # raise ex
275
+ raise ex
266
276
  end
267
277
  if options[:scrub]
268
278
  out << Morpheus::Logging.scrub_message(body_str)
@@ -273,7 +283,7 @@ module Morpheus::Cli::PrintHelper
273
283
  if options[:scrub]
274
284
  out << Morpheus::Logging.scrub_message(payload)
275
285
  else
276
- out << payload
286
+ out << payload.to_s
277
287
  end
278
288
  end
279
289
  end
@@ -327,7 +337,9 @@ module Morpheus::Cli::PrintHelper
327
337
  else
328
338
  out << " -d '#{payload}'"
329
339
  end
340
+ out << "\n"
330
341
  else
342
+ is_multipart = (payload.is_a?(Hash) && payload[:multipart] == true)
331
343
  content_type = headers['Content-Type'] || 'application/x-www-form-urlencoded'
332
344
 
333
345
  if payload.is_a?(File)
@@ -337,21 +349,22 @@ module Morpheus::Cli::PrintHelper
337
349
  out << " -d @#{payload.path}"
338
350
  elsif payload.is_a?(String)
339
351
  out << " -d '#{payload}'"
340
- else
341
- if content_type == 'application/x-www-form-urlencoded'
342
- body_str = payload.to_s
343
- begin
344
- body_str = URI.encode_www_form(payload)
345
- rescue => ex
346
- # raise ex
352
+ elsif payload.respond_to?(:map)
353
+ payload.delete(:multipart) if payload.is_a?(Hash)
354
+ # puts "grailsifying it!"
355
+ payload = Morpheus::RestClient.grails_params(payload)
356
+ payload.each do |k,v|
357
+ if v.is_a?(File)
358
+ out << " -F '#{k}=@#{v.path}"
359
+ else
360
+ out << " -d '#{URI.encode_www_form({(k) => v})}'"
347
361
  end
348
- out << " -d '#{body_str}'"
349
- else
350
- out << " -d '#{payload}'"
362
+ out << "\n"
351
363
  end
364
+ #body_str = URI.encode_www_form(payload)
365
+ # out << " -d '#{body_str}'"
352
366
  end
353
367
  end
354
- out << "\n"
355
368
  else
356
369
  out << "\n"
357
370
  end
@@ -431,12 +444,13 @@ module Morpheus::Cli::PrintHelper
431
444
  out = ""
432
445
  bars = []
433
446
  percent = 0
447
+ percent_sigdig = opts[:percent_sigdig] || 2
434
448
  if max_value.to_i == 0
435
449
  percent = 0
436
450
  else
437
451
  percent = ((used_value.to_f / max_value.to_f) * 100)
438
452
  end
439
- percent_label = ((used_value.nil? || max_value.to_f == 0.0) ? "n/a" : "#{percent.round(2)}%").rjust(6, ' ')
453
+ percent_label = ((used_value.nil? || max_value.to_f == 0.0) ? "n/a" : "#{percent.round(percent_sigdig)}%").rjust(6, ' ')
440
454
  bar_display = ""
441
455
  if percent > 100
442
456
  max_bars.times { bars << "|" }
@@ -674,7 +688,7 @@ module Morpheus::Cli::PrintHelper
674
688
  else
675
689
  # so let's use the passed in column definitions instead of the raw data properties
676
690
  # columns = options[:include_fields]
677
- new_columns = []
691
+ new_columns = {}
678
692
  options[:include_fields].each do |f|
679
693
  matching_column = nil
680
694
  # column definitions vary right now, array of symbols/strings/hashes or perhaps a single hash
@@ -692,7 +706,7 @@ module Morpheus::Cli::PrintHelper
692
706
  matching_column = columns[matching_key]
693
707
  end
694
708
  end
695
- new_columns << (matching_column ? matching_column : f)
709
+ new_columns[f] = matching_column ? matching_column : f
696
710
  end
697
711
  columns = new_columns
698
712
  end
@@ -720,6 +734,7 @@ module Morpheus::Cli::PrintHelper
720
734
  columns.each do |column_def|
721
735
  # r << column_def.display_method.respond_to?(:call) ? column_def.display_method.call(row_data) : get_object_value(row_data, column_def.display_method)
722
736
  value = column_def.display_method.call(row_data)
737
+ value = JSON.fast_generate(value) if value.is_a?(Hash) || value.is_a?(Array)
723
738
  row << value
724
739
  end
725
740
  rows << row
@@ -802,6 +817,7 @@ module Morpheus::Cli::PrintHelper
802
817
  columns.each do |column_def|
803
818
  # r << column_def.display_method.respond_to?(:call) ? column_def.display_method.call(row_data) : get_object_value(row_data, column_def.display_method)
804
819
  value = column_def.display_method.call(row_data)
820
+ value = JSON.fast_generate(value) if value.is_a?(Hash) || value.is_a?(Array)
805
821
  row << value
806
822
  end
807
823
  rows << row
@@ -879,6 +895,7 @@ module Morpheus::Cli::PrintHelper
879
895
  label = label.upcase if ALL_LABELS_UPCASE
880
896
  # value = get_object_value(obj, column_def.display_method)
881
897
  value = column_def.display_method.call(obj)
898
+ value = JSON.fast_generate(value) if value.is_a?(Hash) || value.is_a?(Array)
882
899
  if label.size > max_label_width
883
900
  max_label_width = label.size
884
901
  end
@@ -1069,6 +1086,7 @@ module Morpheus::Cli::PrintHelper
1069
1086
  column_defs.each do |column_def|
1070
1087
  label = column_def.label
1071
1088
  value = column_def.display_method.call(obj)
1089
+ value = value.is_a?(String) ? value : JSON.fast_generate(value)
1072
1090
  # value = get_object_value(obj, column_def)
1073
1091
  if do_quotes
1074
1092
  cells << quote_csv_value(value)
@@ -696,7 +696,7 @@ module Morpheus::Cli::ProvisioningHelper
696
696
  # prompt for service plan
697
697
  plan_id = nil
698
698
  service_plan = nil
699
- service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
699
+ service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
700
700
  service_plans = service_plans_json["plans"]
701
701
  if locked_fields.include?('plan.id')
702
702
  plan_id = options[:options]['plan']['id'] rescue nil
@@ -764,7 +764,7 @@ module Morpheus::Cli::ProvisioningHelper
764
764
  # pluck out the resourcePoolId option type to prompt for
765
765
  resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
766
766
  option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
767
- resource_pool_options = @options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], planId: service_plan["id"], layoutId: layout["id"]})['data']
767
+ resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], planId: service_plan["id"], layoutId: layout["id"]})['data']
768
768
  resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
769
769
 
770
770
  if resource_pool
@@ -1409,7 +1409,7 @@ module Morpheus::Cli::ProvisioningHelper
1409
1409
  if plan_info['addVolumes']
1410
1410
  volume_index = current_volumes.size
1411
1411
  has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
1412
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?"))
1412
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?", {:default => false}))
1413
1413
  while add_another_volume do
1414
1414
  #puts "Configure Data #{volume_index} Volume"
1415
1415
 
@@ -0,0 +1,246 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+ # Provides common finder methods for VDI Pool management commands
3
+ module Morpheus::Cli::VdiHelper
4
+
5
+ def self.included(klass)
6
+ klass.send :include, Morpheus::Cli::PrintHelper
7
+ end
8
+
9
+ ## VDI Pools
10
+
11
+ def vdi_pools_interface
12
+ raise "#{self.class} has not defined @vdi_pools_interface" if @vdi_pools_interface.nil?
13
+ @vdi_pools_interface
14
+ end
15
+
16
+ def vdi_pool_object_key
17
+ 'vdiPool'
18
+ end
19
+
20
+ def vdi_pool_list_key
21
+ 'vdiPools'
22
+ end
23
+
24
+ def find_vdi_pool_by_name_or_id(val)
25
+ if val.to_s =~ /\A\d{1,}\Z/
26
+ return find_vdi_pool_by_id(val)
27
+ else
28
+ return find_vdi_pool_by_name(val)
29
+ end
30
+ end
31
+
32
+ def find_vdi_pool_by_id(id)
33
+ begin
34
+ json_response = vdi_pools_interface.get(id.to_i)
35
+ return json_response[vdi_pool_object_key]
36
+ rescue RestClient::Exception => e
37
+ if e.response && e.response.code == 404
38
+ print_red_alert "VDI Pool not found by id '#{id}'"
39
+ else
40
+ raise e
41
+ end
42
+ end
43
+ end
44
+
45
+ def find_vdi_pool_by_name(name)
46
+ json_response = vdi_pools_interface.list({name: name.to_s})
47
+ vdi_pools = json_response[vdi_pool_list_key]
48
+ if vdi_pools.empty?
49
+ print_red_alert "VDI Pool not found by name '#{name}'"
50
+ return nil
51
+ elsif vdi_pools.size > 1
52
+ print_red_alert "#{vdi_pools.size} VDI Pools found by name '#{name}'"
53
+ print_error "\n"
54
+ puts_error as_pretty_table(vdi_pools, [:id, :name], {color:red})
55
+ print_red_alert "Try using ID instead"
56
+ print_error reset,"\n"
57
+ return nil
58
+ else
59
+ return vdi_pools[0]
60
+ end
61
+ end
62
+
63
+ def format_vdi_pool_status(vdi_pool, return_color=cyan)
64
+ out = ""
65
+ status_string = vdi_pool['status'].to_s.downcase
66
+ if status_string
67
+ if ['available'].include?(status_string)
68
+ out << "#{green}#{status_string.upcase}"
69
+ elsif ['unavailable'].include?(status_string)
70
+ out << "#{red}#{status_string.upcase}"
71
+ else
72
+ out << "#{return_color}#{status_string.upcase}"
73
+ end
74
+ end
75
+ out + return_color
76
+ end
77
+
78
+ ## VDI Allocations
79
+
80
+ def vdi_allocations_interface
81
+ raise "#{self.class} has not defined @vdi_allocations_interface" if @vdi_allocations_interface.nil?
82
+ @vdi_allocations_interface
83
+ end
84
+
85
+ def vdi_allocation_object_key
86
+ 'vdiAllocation'
87
+ end
88
+
89
+ def vdi_allocation_list_key
90
+ 'vdiAllocations'
91
+ end
92
+
93
+ def find_vdi_allocation_by_id(id)
94
+ begin
95
+ json_response = vdi_allocations_interface.get(id.to_i)
96
+ return json_response[vdi_allocation_object_key]
97
+ rescue RestClient::Exception => e
98
+ if e.response && e.response.code == 404
99
+ print_red_alert "VDI Allocation not found by id '#{id}'"
100
+ else
101
+ raise e
102
+ end
103
+ end
104
+ end
105
+
106
+ def format_vdi_allocation_status(vdi_allocation, return_color=cyan)
107
+ out = ""
108
+ status_string = vdi_allocation['status'].to_s.downcase
109
+ if status_string
110
+ if ['available'].include?(status_string)
111
+ out << "#{green}#{status_string.upcase}"
112
+ # elsif ['preparing'].include?(status_string)
113
+ # out << "#{yellow}#{status_string.upcase}"
114
+ # elsif ['reserved', 'shutdown'].include?(status_string)
115
+ # out << "#{yellow}#{status_string.upcase}"
116
+ elsif ['failed'].include?(status_string)
117
+ out << "#{red}#{status_string.upcase}"
118
+ else
119
+ out << "#{return_color}#{status_string.upcase}"
120
+ end
121
+ end
122
+ out + return_color
123
+ end
124
+
125
+ def get_available_vdi_apps(refresh=false)
126
+ if !@available_vdi_apps || refresh
127
+ @available_vdi_apps = @vdi_apps_interface.list({max:-1})['vdiApps'] # || []
128
+ end
129
+ return @available_vdi_apps
130
+ end
131
+
132
+ def get_vdi_app_by_name_or_code(name)
133
+ return get_available_vdi_apps().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
134
+ end
135
+
136
+ ## VDI Apps
137
+
138
+ def vdi_apps_interface
139
+ raise "#{self.class} has not defined @vdi_apps_interface" if @vdi_apps_interface.nil?
140
+ @vdi_apps_interface
141
+ end
142
+
143
+ def vdi_app_object_key
144
+ 'vdiApp'
145
+ end
146
+
147
+ def vdi_app_list_key
148
+ 'vdiApps'
149
+ end
150
+
151
+ def find_vdi_app_by_name_or_id(val)
152
+ if val.to_s =~ /\A\d{1,}\Z/
153
+ return find_vdi_app_by_id(val)
154
+ else
155
+ return find_vdi_app_by_name(val)
156
+ end
157
+ end
158
+
159
+ def find_vdi_app_by_id(id)
160
+ begin
161
+ json_response = vdi_apps_interface.get(id.to_i)
162
+ return json_response[vdi_app_object_key]
163
+ rescue RestClient::Exception => e
164
+ if e.response && e.response.code == 404
165
+ print_red_alert "VDI App not found by id '#{id}'"
166
+ else
167
+ raise e
168
+ end
169
+ end
170
+ end
171
+
172
+ def find_vdi_app_by_name(name)
173
+ json_response = vdi_apps_interface.list({name: name.to_s})
174
+ vdi_apps = json_response[vdi_app_list_key]
175
+ if vdi_apps.empty?
176
+ print_red_alert "VDI App not found by name '#{name}'"
177
+ return nil
178
+ elsif vdi_apps.size > 1
179
+ print_red_alert "#{vdi_apps.size} VDI App found by name '#{name}'"
180
+ print_error "\n"
181
+ puts_error as_pretty_table(vdi_apps, {"ID" => 'id', "NAME" => 'name'}, {color:red})
182
+ print_red_alert "Try using ID instead"
183
+ print_error reset,"\n"
184
+ return nil
185
+ else
186
+ return vdi_apps[0]
187
+ end
188
+ end
189
+
190
+
191
+ ## VDI Gateways
192
+
193
+ def vdi_gateways_interface
194
+ raise "#{self.class} has not defined @vdi_gateways_interface" if @vdi_gateways_interface.nil?
195
+ @vdi_gateways_interface
196
+ end
197
+
198
+ def vdi_gateway_object_key
199
+ 'vdiGateway'
200
+ end
201
+
202
+ def vdi_gateway_list_key
203
+ 'vdiGateways'
204
+ end
205
+
206
+ def find_vdi_gateway_by_name_or_id(val)
207
+ if val.to_s =~ /\A\d{1,}\Z/
208
+ return find_vdi_gateway_by_id(val)
209
+ else
210
+ return find_vdi_gateway_by_name(val)
211
+ end
212
+ end
213
+
214
+ def find_vdi_gateway_by_id(id)
215
+ begin
216
+ json_response = vdi_gateways_interface.get(id.to_i)
217
+ return json_response[vdi_gateway_object_key]
218
+ rescue RestClient::Exception => e
219
+ if e.response && e.response.code == 404
220
+ print_red_alert "VDI Gateway not found by id '#{id}'"
221
+ else
222
+ raise e
223
+ end
224
+ end
225
+ end
226
+
227
+ def find_vdi_gateway_by_name(name)
228
+ json_response = vdi_gateways_interface.list({name: name.to_s})
229
+ vdi_gateways = json_response[vdi_gateway_list_key]
230
+ if vdi_gateways.empty?
231
+ print_red_alert "VDI Gateway not found by name '#{name}'"
232
+ return nil
233
+ elsif vdi_gateways.size > 1
234
+ print_red_alert "#{vdi_gateways.size} VDI Gateway found by name '#{name}'"
235
+ print_error "\n"
236
+ puts_error as_pretty_table(vdi_gateways, {"ID" => 'id', "NAME" => 'name'}, {color:red})
237
+ print_red_alert "Try using ID instead"
238
+ print_error reset,"\n"
239
+ return nil
240
+ else
241
+ return vdi_gateways[0]
242
+ end
243
+ end
244
+
245
+
246
+ end