morpheus-cli 5.4.2 → 5.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +4 -1
  3. data/lib/morpheus/api/catalog_item_types_interface.rb +20 -0
  4. data/lib/morpheus/api/instances_interface.rb +28 -0
  5. data/lib/morpheus/api/ping_interface.rb +2 -0
  6. data/lib/morpheus/api/setup_interface.rb +4 -0
  7. data/lib/morpheus/api/snapshots_interface.rb +19 -0
  8. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +88 -0
  9. data/lib/morpheus/cli/commands/clusters.rb +59 -46
  10. data/lib/morpheus/cli/commands/hosts.rb +12 -0
  11. data/lib/morpheus/cli/commands/instances.rb +250 -1
  12. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -0
  13. data/lib/morpheus/cli/commands/network_static_routes_command.rb +5 -0
  14. data/lib/morpheus/cli/commands/networks_command.rb +2 -2
  15. data/lib/morpheus/cli/commands/ping.rb +3 -5
  16. data/lib/morpheus/cli/commands/policies_command.rb +1 -1
  17. data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -0
  18. data/lib/morpheus/cli/commands/remote.rb +16 -10
  19. data/lib/morpheus/cli/commands/security_groups.rb +2 -2
  20. data/lib/morpheus/cli/commands/service_plans_command.rb +1 -1
  21. data/lib/morpheus/cli/commands/setup.rb +1 -1
  22. data/lib/morpheus/cli/commands/snapshots.rb +139 -0
  23. data/lib/morpheus/cli/commands/tasks.rb +5 -5
  24. data/lib/morpheus/cli/commands/user_settings_command.rb +1 -1
  25. data/lib/morpheus/cli/commands/virtual_images.rb +4 -1
  26. data/lib/morpheus/cli/mixins/provisioning_helper.rb +80 -0
  27. data/lib/morpheus/cli/option_types.rb +26 -11
  28. data/lib/morpheus/cli/version.rb +1 -1
  29. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d81fbae375d0d103b21c67cbbe12688b7d6977674b275047acf8e5dc9f2e155f
4
- data.tar.gz: f926189bc1792af28a86c1652a9b0b4268581d759fff857697e559e862aa09fb
3
+ metadata.gz: 1115efb46c7480c6a3814183c5748f27ce92d8be5ca935116fac0a26d66a58aa
4
+ data.tar.gz: a47a2aa8cb3d36dfff5de6e811c2948e54e54771d3e00c47ca377db50b77fbbf
5
5
  SHA512:
6
- metadata.gz: d5d832fc40ea3d0da75e4acfcd445fb59509b78fee5b87c81fa401237ed6ee8476a8a5de9fa11ce6bf2b1cac28f292bc0c6a5a9ef4345ca3c08a99baf084bee6
7
- data.tar.gz: 216b534d057fe67350a816ee00e45a4d9218f21a9a4ebeeadad764a9b12821720658bf56be6b873e63143c58be61064d20c88550cd4a4a88780748499fe2f386
6
+ metadata.gz: ab05b111e694eded06459369814d4dcf462766a48a861831a004e428324b7181b570b8df6b6c8097f5be6bc5fc3be2d2ea59ac44ae4003cc444b53e49d2a3665
7
+ data.tar.gz: b4760ef297c3a3dd9b19b71c0d4702885803dc5ae107a2cf538c074fd6a17191303910b28e119560113ce6f50208e250b6c07659e003da80c8c6c068cfad26ed
@@ -347,7 +347,6 @@ class Morpheus::APIClient
347
347
  end
348
348
 
349
349
  def auth
350
- # Morpheus::AuthInterface.new(common_interface_options).setopts(@options)
351
350
  Morpheus::AuthInterface.new({url: @base_url, client_id: @client_id, verify_ssl: @verify_ssl}).setopts(@options)
352
351
  end
353
352
 
@@ -889,6 +888,10 @@ class Morpheus::APIClient
889
888
  Morpheus::NetworkStaticRoutesInterface.new(common_interface_options).setopts(@options)
890
889
  end
891
890
 
891
+ def snapshots
892
+ Morpheus::SnapshotsInterface.new(common_interface_options).setopts(@options)
893
+ end
894
+
892
895
  def rest(endpoint)
893
896
  Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
894
897
  end
@@ -6,4 +6,24 @@ class Morpheus::CatalogItemTypesInterface < Morpheus::RestInterface
6
6
  "/api/catalog-item-types"
7
7
  end
8
8
 
9
+ # NOT json, multipart file upload
10
+ # def update_logo(id, logo_file)
11
+ # url = "#{base_path}/#{id}/update-logo"
12
+ # headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
13
+ # payload = {}
14
+ # payload[:logo] = logo_file
15
+ # payload[:multipart] = true
16
+ # execute(method: :post, url: url, headers: headers, payload: payload)
17
+ # end
18
+
19
+ # NOT json, multipart file upload, uses PUT update endpoint
20
+ def update_logo(id, logo_file)
21
+ url = "#{base_path}/#{id}"
22
+ headers = { :params => {}, :authorization => "Bearer #{@access_token}"}
23
+ payload = {}
24
+ payload["catalogItemType"] = {"logo" => logo_file}
25
+ payload[:multipart] = true
26
+ execute(method: :put, url: url, headers: headers, payload: payload)
27
+ end
28
+
9
29
  end
@@ -262,6 +262,34 @@ class Morpheus::InstancesInterface < Morpheus::APIClient
262
262
  execute(opts)
263
263
  end
264
264
 
265
+ def revert_to_snapshot(id, snapshot_id, payload={})
266
+ url = "#{@base_url}/api/instances/#{id}/revert-snapshot/#{snapshot_id}"
267
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
268
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
269
+ execute(opts)
270
+ end
271
+
272
+ def remove_all_container_snapshots(id, container_id, payload={})
273
+ url = "#{@base_url}/api/instances/#{id}/delete-container-snapshots/#{container_id}"
274
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
275
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
276
+ execute(opts)
277
+ end
278
+
279
+ def remove_all_instance_snapshots(id, payload={})
280
+ url = "#{@base_url}/api/instances/#{id}/delete-all-snapshots"
281
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
282
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
283
+ execute(opts)
284
+ end
285
+
286
+ def create_linked_clone(id, snapshot_id, payload={})
287
+ url = "#{@base_url}/api/instances/#{id}/linked-clone/#{snapshot_id}"
288
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
289
+ opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
290
+ execute(opts)
291
+ end
292
+
265
293
  def service_plans(params={})
266
294
  url = "#{@base_url}/api/instances/service-plans"
267
295
  headers = { params: params, authorization: "Bearer #{@access_token}" }
@@ -14,6 +14,8 @@ class Morpheus::PingInterface < Morpheus::APIClient
14
14
 
15
15
  def get(params={})
16
16
  headers = {params: params}
17
+ # use access token if authenticated
18
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
17
19
  execute(method: :get, url: "/api/ping", headers: headers)
18
20
  end
19
21
 
@@ -14,12 +14,16 @@ class Morpheus::SetupInterface < Morpheus::APIClient
14
14
 
15
15
  def get(params={})
16
16
  headers = {params: params}
17
+ # use access token if authenticated
18
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
17
19
  execute(method: :get, url: "/api/setup", headers: headers)
18
20
  end
19
21
 
20
22
  #this should go away and just use
21
23
  def check(params={}, timeout=5)
22
24
  headers = {params: params}
25
+ # use access token if authenticated
26
+ headers[:authorization] = "Bearer #{@access_token}" if @access_token
23
27
  execute(method: :get, url: "/api/setup/check", headers: headers, timeout: timeout)
24
28
  end
25
29
 
@@ -0,0 +1,19 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ # Snapshots API interface.
4
+ class Morpheus::SnapshotsInterface < Morpheus::APIClient
5
+
6
+ def get(snapshot_id)
7
+ url = "#{@base_url}/api/snapshots/#{snapshot_id}"
8
+ headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
9
+ opts = {method: :get, url: url, headers: headers}
10
+ execute(opts)
11
+ end
12
+
13
+ def remove(snapshot_id, payload={})
14
+ url = "#{@base_url}/api/snapshots/#{snapshot_id}"
15
+ headers = {:authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
16
+ opts = {method: :delete, url: url, headers: headers, payload: payload.to_json}
17
+ execute(opts)
18
+ end
19
+ end
@@ -13,6 +13,7 @@ class Morpheus::Cli::CatalogItemTypesCommand
13
13
  set_command_description "Self Service: View and manage catalog item types"
14
14
 
15
15
  register_subcommands :list, :get, :add, :update, :remove
16
+ register_subcommands({:'update-logo' => :update_logo})
16
17
 
17
18
  def connect(opts)
18
19
  @api_client = establish_remote_appliance_connection(opts)
@@ -222,6 +223,7 @@ EOT
222
223
  def add(args)
223
224
  options = {}
224
225
  params = {}
226
+ logo_file = nil
225
227
  optparse = Morpheus::Cli::OptionParser.new do |opts|
226
228
  opts.banner = subcommand_usage("[name] [options]")
227
229
  # opts.on('-t', '--type [instance|blueprint|workflow]', "Item Type, default is instance.") do |val|
@@ -229,6 +231,19 @@ EOT
229
231
  # options[:options]['type'] = val.to_s.downcase
230
232
  # end
231
233
  build_option_type_options(opts, options, add_catalog_item_type_option_types)
234
+ opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
235
+ filename = val
236
+ logo_file = nil
237
+ if filename == 'null'
238
+ filename = 'null' # clear it
239
+ else
240
+ filename = File.expand_path(filename)
241
+ if !File.exists?(filename)
242
+ raise_command_error "File not found: #{filename}"
243
+ end
244
+ logo_file = File.new(filename, 'rb')
245
+ end
246
+ end
232
247
  opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
233
248
  options[:config_file] = val.to_s
234
249
  file_content = nil
@@ -330,6 +345,16 @@ EOT
330
345
  return 0, nil
331
346
  end
332
347
  json_response = @catalog_item_types_interface.create(payload)
348
+ if json_response['success']
349
+ if logo_file
350
+ begin
351
+ @catalog_item_types_interface.update_logo(json_response['catalogItemType']['id'], logo_file)
352
+ rescue RestClient::Exception => e
353
+ print_red_alert "Failed to save logo!"
354
+ print_rest_exception(e, options)
355
+ end
356
+ end
357
+ end
333
358
  catalog_item_type = json_response[catalog_item_type_object_key]
334
359
  render_response(json_response, options, catalog_item_type_object_key) do
335
360
  print_green_success "Added catalog item type #{catalog_item_type['name']}"
@@ -342,9 +367,23 @@ EOT
342
367
  options = {}
343
368
  params = {}
344
369
  payload = {}
370
+ logo_file = nil
345
371
  optparse = Morpheus::Cli::OptionParser.new do |opts|
346
372
  opts.banner = subcommand_usage("[type] [options]")
347
373
  build_option_type_options(opts, options, update_catalog_item_type_option_types)
374
+ opts.on('--logo FILE', String, "Upload a custom logo icon") do |val|
375
+ filename = val
376
+ logo_file = nil
377
+ if filename == 'null'
378
+ filename = 'null' # clear it
379
+ else
380
+ filename = File.expand_path(filename)
381
+ if !File.exists?(filename)
382
+ raise_command_error "File not found: #{filename}"
383
+ end
384
+ logo_file = File.new(filename, 'rb')
385
+ end
386
+ end
348
387
  opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
349
388
  options[:config_file] = val.to_s
350
389
  file_content = nil
@@ -445,6 +484,16 @@ EOT
445
484
  return
446
485
  end
447
486
  json_response = @catalog_item_types_interface.update(catalog_item_type['id'], payload)
487
+ if json_response['success']
488
+ if logo_file
489
+ begin
490
+ @catalog_item_types_interface.update_logo(json_response['catalogItemType']['id'], logo_file)
491
+ rescue RestClient::Exception => e
492
+ print_red_alert "Failed to save logo!"
493
+ print_rest_exception(e, options)
494
+ end
495
+ end
496
+ end
448
497
  catalog_item_type = json_response[catalog_item_type_object_key]
449
498
  render_response(json_response, options, catalog_item_type_object_key) do
450
499
  print_green_success "Updated catalog item type #{catalog_item_type['name']}"
@@ -453,6 +502,45 @@ EOT
453
502
  return 0, nil
454
503
  end
455
504
 
505
+ def update_logo(args)
506
+ options = {}
507
+ params = {}
508
+ filename = nil
509
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
510
+ opts.banner = subcommand_usage("[type] [file]")
511
+ build_common_options(opts, options, [:json, :dry_run, :remote])
512
+ opts.footer = "Update the logo for a catalog item type." + "\n" +
513
+ "[type] is required. This is the name or id of a catalog item type." + "\n" +
514
+ "[file] is required. This is the path of the logo file"
515
+ end
516
+ optparse.parse!(args)
517
+ verify_args!(args:args, optparse:optparse, count:2)
518
+ connect(options)
519
+ catalog_item_type = find_catalog_item_type_by_name_or_id(args[0])
520
+ return 1 if catalog_item_type.nil?
521
+ filename = args[1]
522
+ logo_file = nil
523
+ if filename == 'null'
524
+ filename = 'null' # clear it
525
+ else
526
+ filename = File.expand_path(filename)
527
+ if !File.exists?(filename)
528
+ raise_command_error "File not found: #{filename}"
529
+ end
530
+ logo_file = File.new(filename, 'rb')
531
+ end
532
+ @catalog_item_types_interface.setopts(options)
533
+ if options[:dry_run]
534
+ print_dry_run @catalog_item_types_interface.dry.update_logo(catalog_item_type['id'], logo_file)
535
+ return
536
+ end
537
+ json_response = @catalog_item_types_interface.update_logo(catalog_item_type['id'], logo_file)
538
+ render_response(json_response, options, catalog_item_type_object_key) do
539
+ print_green_success "Updated catalog item type #{catalog_item_type['name']} logo"
540
+ return _get(catalog_item_type["id"], {}, options)
541
+ end
542
+ end
543
+
456
544
  def remove(args)
457
545
  options = {}
458
546
  params = {}
@@ -547,11 +547,7 @@ class Morpheus::Cli::Clusters
547
547
  available_layouts = layouts_for_dropdown(cloud['id'], cluster_type['id'])
548
548
 
549
549
  if !available_layouts.empty?
550
- if available_layouts.count > 1 && !options[:no_prompt]
551
- layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'selectOptions' => available_layouts, 'required' => true, 'description' => 'Select Layout.'}],options[:options],@api_client,{})['layout']
552
- else
553
- layout_id = available_layouts.first['id']
554
- end
550
+ layout_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'selectOptions' => available_layouts, 'required' => true, 'description' => 'Select Layout.'}],options[:options],@api_client,{})['layout']
555
551
  layout = find_layout_by_name_or_id(layout_id)
556
552
  end
557
553
  end
@@ -560,17 +556,25 @@ class Morpheus::Cli::Clusters
560
556
 
561
557
  # Provision Type
562
558
  provision_type = (layout && layout['provisionType'] ? layout['provisionType'] : nil) || get_provision_type_for_zone_type(cloud['zoneType']['id'])
559
+ provision_type = @provision_types_interface.get(provision_type['id'])['provisionType'] if !provision_type.nil?
563
560
 
564
561
  api_params = {zoneId: cloud['id'], siteId: group['id'], layoutId: layout['id'], groupTypeId: cluster_type['id'], provisionType: provision_type['code'], provisionTypeId: provision_type['id']}
565
562
 
566
563
  # Controller type
567
- server_types = @server_types_interface.list({max:1, computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes']
564
+ server_types = @server_types_interface.list({computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes'].reject {|it| it['provisionType']['code'] == 'manual'}
568
565
  controller_provision_type = nil
569
566
  resource_pool = nil
570
567
 
571
568
  if !server_types.empty?
572
569
  controller_type = server_types.first
573
- controller_provision_type = controller_type['provisionType'] ? (@provision_types_interface.get(controller_type['provisionType']['id'])['provisionType'] rescue nil) : nil
570
+
571
+ if controller_type['provisionType']
572
+ if provision_type && provision_type['id'] == controller_type['provisionType']['id']
573
+ controller_provision_type = provision_type
574
+ else
575
+ controller_provision_type = @provision_types_interface.get(controller_type['provisionType']['id'])['provisionType'] rescue nil
576
+ end
577
+ end
574
578
 
575
579
  if controller_provision_type && resource_pool = prompt_resource_pool(group, cloud, nil, controller_provision_type, options)
576
580
  server_payload['config']['resourcePoolId'] = resource_pool['id']
@@ -585,21 +589,23 @@ class Morpheus::Cli::Clusters
585
589
  service_plan = prompt_service_plan(api_params, options)
586
590
 
587
591
  if service_plan
588
- server_payload['plan'] = {'id' => service_plan['id'], 'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, options)}
592
+ server_payload['plan'] = {'id' => service_plan['id'], 'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, provision_type, options)}
589
593
  api_params['planId'] = service_plan['id']
590
594
  end
591
595
 
592
596
  # Multi-disk / prompt for volumes
593
- volumes = options[:volumes] || prompt_volumes(service_plan, options.merge({'defaultAddFirstDataVolume': true}), @api_client, api_params)
594
-
595
- if !volumes.empty?
596
- server_payload['volumes'] = volumes
597
+ if provision_type['hasVolumes']
598
+ volumes = options[:volumes] || prompt_volumes(service_plan, options.merge({'defaultAddFirstDataVolume': true}), @api_client, api_params)
599
+ if !volumes.empty?
600
+ server_payload['volumes'] = volumes
601
+ end
597
602
  end
598
603
 
599
604
  # Options / Custom Config
600
605
  option_type_list =
601
- ((controller_type['optionTypes'].reject { |type| !type['enabled'] || type['fieldComponent'] } rescue []) + layout['optionTypes'] +
602
- (cluster_type['optionTypes'].reject { |type| !type['enabled'] || !type['creatable'] || type['fieldComponent'] } rescue [])).sort { |type| type['displayOrder'] }
606
+ ((controller_type.nil? ? [] : controller_type['optionTypes'].reject { |type| !type['enabled'] || type['fieldComponent'] } rescue []) +
607
+ layout['optionTypes'] +
608
+ (cluster_type['optionTypes'].reject { |type| !type['enabled'] || !type['creatable'] || type['fieldComponent'] } rescue []))
603
609
 
604
610
  # KLUDGE: google zone required for network selection
605
611
  if option_type = option_type_list.find {|type| type['code'] == 'computeServerType.googleLinux.googleZoneId'}
@@ -625,11 +631,13 @@ class Morpheus::Cli::Clusters
625
631
  cluster_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(load_layout_options(cluster_payload), options[:options], @api_client, api_params, options[:no_prompt], true))
626
632
 
627
633
  # Server options
628
- server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, api_params, options[:no_prompt], true))
634
+ server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options].deep_merge({:context_map => {'domain' => ''}}), @api_client, api_params, options[:no_prompt], true))
629
635
 
630
636
  # Worker count
631
- default_node_count = layout['computeServers'] ? (layout['computeServers'].find {|it| it['nodeType'] == 'worker'} || {'nodeCount' => 3})['nodeCount'] : 3
632
- server_payload['config']['nodeCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => "config.nodeCount", 'type' => 'number', 'fieldLabel' => "#{['docker', 'kvm-cluster'].include?(cluster_type['code']) ? 'Host' : 'Worker'} Count", 'required' => true, 'defaultValue' => default_node_count > 0 ? default_node_count : 3}], options[:options], @api_client, api_params, options[:no_prompt])['config']['nodeCount']
637
+ if !['manual', 'external'].include?(provision_type['code'])
638
+ default_node_count = layout['computeServers'] ? (layout['computeServers'].find {|it| it['nodeType'] == 'worker'} || {'nodeCount' => 3})['nodeCount'] : 3
639
+ server_payload['config']['nodeCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => "config.nodeCount", 'type' => 'number', 'fieldLabel' => "#{['docker-cluster', 'kvm-cluster'].include?(cluster_type['code']) ? 'Host' : 'Worker'} Count", 'required' => true, 'defaultValue' => default_node_count > 0 ? default_node_count : 3}], options[:options], @api_client, api_params, options[:no_prompt])['config']['nodeCount']
640
+ end
633
641
 
634
642
  # Create User
635
643
  if !options[:createUser].nil?
@@ -657,10 +665,12 @@ class Morpheus::Cli::Clusters
657
665
  server_payload['hostname'] = options[:hostname] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'hostname', 'fieldLabel' => 'Hostname', 'type' => 'text', 'required' => true, 'description' => 'Hostname', 'defaultValue' => resourceName}], options[:options], @api_client, api_params)['hostname']
658
666
 
659
667
  # Workflow / Automation
660
- task_set_id = options[:taskSetId] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'taskSet', 'fieldLabel' => 'Workflow', 'type' => 'select', 'required' => false, 'optionSource' => 'taskSets'}], options[:options], @api_client, api_params.merge({'phase' => 'postProvision'}))['taskSet']
668
+ if provision_type['code'] != 'manual' && controller_type && controller_type['hasAutomation']
669
+ task_set_id = options[:taskSetId] || Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'taskSet', 'fieldLabel' => 'Workflow', 'type' => 'select', 'required' => false, 'optionSource' => 'taskSets'}], options[:options], @api_client, api_params.merge({'phase' => 'postProvision'}))['taskSet']
661
670
 
662
- if !task_set_id.nil?
663
- server_payload['taskSet'] = {'id' => task_set_id}
671
+ if !task_set_id.nil?
672
+ server_payload['taskSet'] = {'id' => task_set_id}
673
+ end
664
674
  end
665
675
 
666
676
  cluster_payload['server'] = server_payload
@@ -1172,7 +1182,7 @@ class Morpheus::Cli::Clusters
1172
1182
  service_plan = prompt_service_plan({zoneId: cloud_id, siteId: cluster['site']['id'], provisionTypeId: server_type['provisionType']['id'], groupTypeId: cluster_type['id'], }, options)
1173
1183
 
1174
1184
  if service_plan
1175
- server_payload['plan'] = {'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, options)}
1185
+ server_payload['plan'] = {'code' => service_plan['code'], 'options' => prompt_service_plan_options(service_plan, nil, options)}
1176
1186
  end
1177
1187
 
1178
1188
  if resource_pool = prompt_resource_pool(cluster, cloud, service_plan, server_type['provisionType'], options)
@@ -3713,34 +3723,37 @@ class Morpheus::Cli::Clusters
3713
3723
  service_plan
3714
3724
  end
3715
3725
 
3716
- def prompt_service_plan_options(service_plan, options)
3726
+ def prompt_service_plan_options(service_plan, provision_type, options)
3717
3727
  plan_options = {}
3718
-
3719
- # custom max memory
3720
- if service_plan['customMaxMemory']
3721
- if !options[:maxMemory]
3722
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'maxMemory', 'type' => 'number', 'fieldLabel' => 'Max Memory (MB)', 'required' => false, 'description' => 'This will override any memory requirement set on the virtual image', 'defaultValue' => service_plan['maxMemory'] ? service_plan['maxMemory'] / (1024 * 1024) : 10 }], options[:options])
3723
- plan_options['maxMemory'] = v_prompt['maxMemory'] * 1024 * 1024 if v_prompt['maxMemory']
3724
- else
3725
- plan_options['maxMemory'] = options[:maxMemory]
3728
+ hide_custom_options = provision_type && provision_type['code'] == 'manual'
3729
+
3730
+ if !hide_custom_options
3731
+ # custom max memory
3732
+ if service_plan['customMaxMemory']
3733
+ if !options[:maxMemory]
3734
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'maxMemory', 'type' => 'number', 'fieldLabel' => 'Max Memory (MB)', 'required' => false, 'description' => 'This will override any memory requirement set on the virtual image', 'defaultValue' => service_plan['maxMemory'] ? service_plan['maxMemory'] / (1024 * 1024) : 10 }], options[:options])
3735
+ plan_options['maxMemory'] = v_prompt['maxMemory'] * 1024 * 1024 if v_prompt['maxMemory']
3736
+ else
3737
+ plan_options['maxMemory'] = options[:maxMemory]
3738
+ end
3726
3739
  end
3727
- end
3728
3740
 
3729
- # custom cores: max cpu, max cores, cores per socket
3730
- if service_plan['customCores']
3731
- if options[:cpuCount].empty?
3732
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cpuCount', 'type' => 'number', 'fieldLabel' => 'CPU Count', 'required' => false, 'description' => 'Set CPU Count', 'defaultValue' => service_plan['maxCpu'] ? service_plan['maxCpu'] : 1 }], options[:options])
3733
- plan_options['cpuCount'] = v_prompt['cpuCount'] if v_prompt['cpuCount']
3734
- else
3735
- plan_options['cpuCount']
3736
- end
3737
- if options[:coreCount].empty?
3738
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coreCount', 'type' => 'number', 'fieldLabel' => 'Core Count', 'required' => false, 'description' => 'Set Core Count', 'defaultValue' => service_plan['maxCores'] ? service_plan['maxCores'] : 1 }], options[:options])
3739
- plan_options['coreCount'] = v_prompt['coreCount'] if v_prompt['coreCount']
3740
- end
3741
- if options[:coresPerSocket].empty? && service_plan['coresPerSocket']
3742
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coresPerSocket', 'type' => 'number', 'fieldLabel' => 'Cores Per Socket', 'required' => false, 'description' => 'Set Core Per Socket', 'defaultValue' => service_plan['coresPerSocket']}], options[:options])
3743
- plan_options['coresPerSocket'] = v_prompt['coresPerSocket'] if v_prompt['coresPerSocket']
3741
+ # custom cores: max cpu, max cores, cores per socket
3742
+ if service_plan['customCores']
3743
+ if options[:cpuCount].empty?
3744
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cpuCount', 'type' => 'number', 'fieldLabel' => 'CPU Count', 'required' => false, 'description' => 'Set CPU Count', 'defaultValue' => service_plan['maxCpu'] ? service_plan['maxCpu'] : 1 }], options[:options])
3745
+ plan_options['cpuCount'] = v_prompt['cpuCount'] if v_prompt['cpuCount']
3746
+ else
3747
+ plan_options['cpuCount']
3748
+ end
3749
+ if options[:coreCount].empty?
3750
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coreCount', 'type' => 'number', 'fieldLabel' => 'Core Count', 'required' => false, 'description' => 'Set Core Count', 'defaultValue' => service_plan['maxCores'] ? service_plan['maxCores'] : 1 }], options[:options])
3751
+ plan_options['coreCount'] = v_prompt['coreCount'] if v_prompt['coreCount']
3752
+ end
3753
+ if options[:coresPerSocket].empty? && service_plan['coresPerSocket']
3754
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'coresPerSocket', 'type' => 'number', 'fieldLabel' => 'Cores Per Socket', 'required' => false, 'description' => 'Set Core Per Socket', 'defaultValue' => service_plan['coresPerSocket']}], options[:options])
3755
+ plan_options['coresPerSocket'] = v_prompt['coresPerSocket'] if v_prompt['coresPerSocket']
3756
+ end
3744
3757
  end
3745
3758
  end
3746
3759
  plan_options
@@ -878,6 +878,12 @@ class Morpheus::Cli::Hosts
878
878
  payload['volumes'] = volumes
879
879
  end
880
880
 
881
+ # plan customizations
882
+ plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {})
883
+ if plan_opts && !plan_opts.empty?
884
+ payload['servicePlanOptions'] = plan_opts
885
+ end
886
+
881
887
  # prompt for network interfaces (if supported)
882
888
  if server_type["provisionType"] && server_type["provisionType"]["id"] && server_type["provisionType"]["hasNetworks"]
883
889
  begin
@@ -1252,6 +1258,12 @@ class Morpheus::Cli::Hosts
1252
1258
  payload[:volumes] = volumes
1253
1259
  end
1254
1260
 
1261
+ # plan customizations
1262
+ plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {}, server)
1263
+ if plan_opts && !plan_opts.empty?
1264
+ payload['servicePlanOptions'] = plan_opts
1265
+ end
1266
+
1255
1267
  # todo: reconfigure networks
1256
1268
  # need to get provision_type_id for network info
1257
1269
  # prompt for network interfaces (if supported)