morpheus-cli 8.0.6 → 8.0.8

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.
@@ -3,6 +3,7 @@ require 'morpheus/cli/cli_command'
3
3
  class Morpheus::Cli::Hosts
4
4
  include Morpheus::Cli::CliCommand
5
5
  include Morpheus::Cli::AccountsHelper
6
+ include Morpheus::Cli::ProcessesHelper
6
7
  include Morpheus::Cli::ProvisioningHelper
7
8
  include Morpheus::Cli::LogsHelper
8
9
  set_command_name :hosts
@@ -13,7 +14,8 @@ class Morpheus::Cli::Hosts
13
14
  {:exec => :execution_request},
14
15
  :wiki, :update_wiki,
15
16
  :maintenance, :leave_maintenance, :placement,
16
- :list_devices, :assign_device, :detach_device, :attach_device
17
+ :list_devices, :assign_device, :detach_device, :attach_device,
18
+ :snapshot
17
19
  alias_subcommand :details, :get
18
20
  set_default_subcommand :list
19
21
 
@@ -538,8 +540,9 @@ class Morpheus::Cli::Hosts
538
540
  "Nodes" => lambda {|it| it['containers'] ? it['containers'].size : 0 },
539
541
  # "Status" => lambda {|it| format_server_status(it) },
540
542
  # "Power" => lambda {|it| format_server_power_state(it) },
541
- "Status" => lambda {|it| format_server_status_friendly(it) }, # combo
542
- "Managed" => lambda {|it| it['computeServerType'] ? it['computeServerType']['managed'] : ''}
543
+ "Managed" => lambda {|it| it['computeServerType'] ? it['computeServerType']['managed'] : ''},
544
+ "Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : ''},
545
+ "Status" => lambda {|it| format_server_status_friendly(it) } # combo
543
546
  }
544
547
  server_columns.delete("Hostname") if server['hostname'].to_s.empty? || server['hostname'] == server['name']
545
548
  server_columns.delete("IP") if server['externalIp'].to_s.empty?
@@ -548,6 +551,7 @@ class Morpheus::Cli::Hosts
548
551
  server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
549
552
  server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
550
553
  server_columns.delete("Labels") if server['labels'].nil? || server['labels'].empty?
554
+ server_columns.delete("Instance") if server['instance'].nil?
551
555
 
552
556
  print_description_list(server_columns, server)
553
557
 
@@ -1477,33 +1481,56 @@ class Morpheus::Cli::Hosts
1477
1481
  def upgrade_agent(args)
1478
1482
  options = {}
1479
1483
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1480
- opts.banner = subcommand_usage("[name]")
1481
- build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
1484
+ opts.banner = subcommand_usage("[host]")
1485
+ opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
1486
+ options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
1487
+ end
1488
+ opts.on(nil, '--no-refresh', "Do not refresh" ) do
1489
+ options[:no_refresh] = true
1490
+ end
1491
+ build_standard_update_options(opts, options, [:auto_confirm])
1492
+ opts.footer = <<-EOT
1493
+ Upgrade agent for a host.
1494
+ [host] is required. This is the name or id of a host.
1495
+ EOT
1482
1496
  end
1483
1497
  optparse.parse!(args)
1484
- if args.count < 1
1485
- puts optparse
1486
- exit 1
1487
- end
1498
+ verify_args!(args:args, optparse:optparse, count:1)
1488
1499
  connect(options)
1489
- begin
1490
- host = find_host_by_name_or_id(args[0])
1491
- @servers_interface.setopts(options)
1492
- if options[:dry_run]
1493
- print_dry_run @servers_interface.dry.upgrade(host['id'])
1494
- return
1495
- end
1496
- json_response = @servers_interface.upgrade(host['id'])
1497
- if options[:json]
1498
- print JSON.pretty_generate(json_response)
1499
- print "\n"
1500
+
1501
+ host = find_host_by_name_or_id(args[0])
1502
+ return 1 if host.nil?
1503
+
1504
+ payload = {}
1505
+ if options[:payload]
1506
+ payload = options[:payload]
1507
+ payload.deep_merge!({'server' => parse_passed_options(options)})
1508
+ else
1509
+ payload.deep_merge!({'server' => parse_passed_options(options)})
1510
+ end
1511
+
1512
+ @servers_interface.setopts(options)
1513
+ if options[:dry_run]
1514
+ print_dry_run @servers_interface.dry.upgrade(host['id'], payload)
1515
+ return
1516
+ end
1517
+ json_response = @servers_interface.upgrade(host['id'], payload)
1518
+ render_response(json_response, options) do
1519
+ #get([host['id']])
1520
+ if json_response['success']
1521
+ if json_response['msg'] == nil
1522
+ print_green_success "Upgrading agent on host #{host['name']}..."
1523
+ else
1524
+ print_green_success json_response['msg']
1525
+ end
1526
+ execution_id = json_response['executionId']
1527
+ if !options[:no_refresh] && execution_id
1528
+ wait_for_execution_request(json_response['executionId'], options.merge({waiting_status:['new', 'pending', 'executing']}))
1529
+ end
1500
1530
  else
1501
- puts "Host #{host['name']} upgrading..." unless options[:quiet]
1531
+ # never reached because unsuccessful requests raise an exception
1532
+ print_red_alert "API Request failed: #{json_response['msg']}"
1502
1533
  end
1503
- return
1504
- rescue RestClient::Exception => e
1505
- print_rest_exception(e, options)
1506
- exit 1
1507
1534
  end
1508
1535
  end
1509
1536
 
@@ -2020,13 +2047,18 @@ EOT
2020
2047
  def snapshots(args)
2021
2048
  options = {}
2022
2049
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2023
- opts.banner = subcommand_usage("[host]")
2050
+ opts.banner = subcommand_usage("[host] [snapshot]")
2024
2051
  # no pagination yet
2025
2052
  # build_standard_list_options(opts, options)
2026
- build_standard_get_options(opts, options)
2053
+ build_standard_list_options(opts, options, [:details])
2054
+ opts.footer = <<-EOT
2055
+ List snapshots for a host.
2056
+ [host] is required. This is the name or id of a host.
2057
+ [snapshot] is optional. This is the name or id of a snapshot.
2058
+ EOT
2027
2059
  end
2028
2060
  optparse.parse!(args)
2029
- verify_args!(args:args, optparse:optparse, count:1)
2061
+ verify_args!(args:args, optparse:optparse, min:1)
2030
2062
  connect(options)
2031
2063
  begin
2032
2064
  server = find_host_by_name_or_id(args[0])
@@ -2038,25 +2070,52 @@ EOT
2038
2070
  return
2039
2071
  end
2040
2072
  json_response = @servers_interface.snapshots(server['id'], params)
2041
- snapshots = json_response['snapshots']
2073
+ snapshots = json_response['snapshots']
2074
+ # [snapshots] is done with post api filtering by id or name or externalId
2075
+ if args[1]
2076
+ if args[1] =~ /\A\d{1,}\Z/
2077
+ snapshots = snapshots.select {|it| it['id'].to_s == args[1] }
2078
+ else
2079
+ # match beginning of name of externalId
2080
+ snapshots = snapshots.select {|it| it['name'].to_s.index(args[1]) == 0 || it['externalId'].to_s.index(args[1]) == 0 }
2081
+ end
2082
+ json_response['snapshots'] = snapshots # update response for -j filtering too
2083
+ end
2042
2084
  render_response(json_response, options, 'snapshots') do
2043
2085
  print_h1 "Snapshots: #{server['name']}", [], options
2044
2086
  if snapshots.empty?
2045
- print cyan,"No snapshots found",reset,"\n"
2087
+ if args[1]
2088
+ print cyan,"No snapshots found for '#{args[1]}'",reset,"\n"
2089
+ elsif
2090
+ print cyan,"No snapshots found",reset,"\n"
2091
+ end
2092
+ print reset, "\n"
2046
2093
  else
2047
- snapshot_column_definitions = {
2048
- "ID" => lambda {|it| it['id'] },
2049
- "Name" => lambda {|it| it['name'] },
2050
- "Description" => lambda {|it| it['description'] },
2051
- # "Type" => lambda {|it| it['snapshotType'] },
2052
- "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
2053
- "Status" => lambda {|it| format_snapshot_status(it) }
2054
- }
2055
- print cyan
2056
- print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
2057
- print_results_pagination({size: snapshots.size, total: snapshots.size})
2094
+ if options[:details]
2095
+ # this actually makes a request for each one here so don't go crazy...
2096
+ if snapshots.size > 3
2097
+ print cyan, "Showing first 3 snapshots. Use the ID to get more details.", reset, "\n"
2098
+ snapshots = snapshots.first(3)
2099
+ end
2100
+ snapshots.each do |snapshot|
2101
+ Morpheus::Cli::Snapshots.new.handle(["get", snapshot['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
2102
+ end
2103
+ else
2104
+ # Snapshots List
2105
+ snapshot_column_definitions = {
2106
+ "ID" => lambda {|it| it['id'] },
2107
+ "Name" => lambda {|it| it['name'] },
2108
+ "Description" => lambda {|it| it['description'] },
2109
+ # "Type" => lambda {|it| it['snapshotType'] },
2110
+ "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
2111
+ "Status" => lambda {|it| format_snapshot_status(it) }
2112
+ }
2113
+ print cyan
2114
+ print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
2115
+ print_results_pagination({size: snapshots.size, total: snapshots.size})
2116
+ print reset, "\n"
2117
+ end
2058
2118
  end
2059
- print reset, "\n"
2060
2119
  end
2061
2120
  return 0
2062
2121
  rescue RestClient::Exception => e
@@ -2419,6 +2478,94 @@ EOT
2419
2478
  return 0, nil
2420
2479
  end
2421
2480
 
2481
+ def snapshot(args)
2482
+ options = {}
2483
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
2484
+ opts.banner = subcommand_usage("[host]")
2485
+ opts.on( '--name VALUE', String, "Snapshot Name. Default is \"{name}.{timestamp}\"" ) do |val|
2486
+ options[:options]['name'] = val
2487
+ end
2488
+ opts.on( '--description VALUE', String, "Snapshot Description." ) do |val|
2489
+ options[:options]['description'] = val
2490
+ end
2491
+ opts.on('--memory-snapshot [on|off]', String, "Memory Snapshot? Whether to include the memory state in the snapshot.") do |val|
2492
+ options[:options]['memorySnapshot'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
2493
+ end
2494
+ opts.on('--for-export [on|off]', String, "For Export? Indicates the snapshot is intended for export to storage.") do |val|
2495
+ options[:options]['forExport'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
2496
+ end
2497
+ opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
2498
+ options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
2499
+ end
2500
+ opts.on(nil, '--no-refresh', "Do not refresh" ) do
2501
+ options[:no_refresh] = true
2502
+ end
2503
+ build_standard_add_options(opts, options, [:auto_confirm])
2504
+ opts.footer = <<-EOT
2505
+ Create a snapshot for a host.
2506
+ [host] is required. This is the name or id of a host
2507
+ EOT
2508
+ end
2509
+ optparse.parse!(args)
2510
+ verify_args!(args:args, optparse:optparse, count:1)
2511
+ connect(options)
2512
+ server = find_host_by_name_or_id(args[0])
2513
+ payload = {}
2514
+ if options[:payload]
2515
+ payload = options[:payload]
2516
+ payload.deep_merge!({'snapshot' => parse_passed_options(options)})
2517
+ else
2518
+ payload.deep_merge!({'snapshot' => parse_passed_options(options)})
2519
+ # prompt for name and description
2520
+ name = prompt_value({'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Snapshot Name', 'description' => "Snapshot Name. Default is \"{name}.{timestamp}\""}, options)
2521
+ payload['snapshot']['name'] = name if !name.to_s.empty?
2522
+ description = prompt_value({'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'description' => "Snapshot Description."}, options)
2523
+ payload['snapshot']['description'] = description if !description.to_s.empty?
2524
+ # need to GET provision type for some settings...
2525
+ provision_type = nil
2526
+ begin
2527
+ provision_type_id = server['computeServerType']['provisionTypeId'] rescue nil
2528
+ if provision_type_id
2529
+ provision_type = @provision_types_interface.get(provision_type_id)['provisionType']
2530
+ end
2531
+ rescue => ex
2532
+ Morpheus::Logging::DarkPrinter.puts "Failed to load provision type!" if Morpheus::Logging.debug?
2533
+ end
2534
+ if provision_type && provision_type['hasMemorySnapshots']
2535
+ # prompt for memorySnapshot
2536
+ memory_snapshot = prompt_value({'fieldName' => 'memorySnapshot', 'type' => 'checkbox', 'fieldLabel' => 'Memory Snapshot?', 'description' => "Snapshot Description."}, options)
2537
+ payload['snapshot']['memorySnapshot'] = memory_snapshot if !memory_snapshot.to_s.empty?
2538
+ end
2539
+ # convert "on" and "off" to true/false
2540
+ payload.booleanize!
2541
+ end
2542
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to snapshot the host '#{server['name']}'?", options)
2543
+ exit 1
2544
+ end
2545
+ @servers_interface.setopts(options)
2546
+ if options[:dry_run]
2547
+ print_dry_run @servers_interface.dry.snapshot(server['id'], payload)
2548
+ return
2549
+ end
2550
+ json_response = @servers_interface.snapshot(server['id'], payload)
2551
+ render_response(json_response, options) do
2552
+ print_green_success "Snapshot initiated."
2553
+ process_id = json_response['processIds'][0] rescue nil
2554
+ if process_id
2555
+ unless options[:no_refresh]
2556
+ process = wait_for_process_execution(process_id, options)
2557
+ snapshot_id = process['resultId']
2558
+ if snapshot_id
2559
+ Morpheus::Cli::Snapshots.new.handle(["get", snapshot_id] + (options[:remote] ? ["-r",options[:remote]] : []))
2560
+ end
2561
+ end
2562
+ else
2563
+ # puts "No process returned"
2564
+ end
2565
+ end
2566
+ return 0, nil
2567
+ end
2568
+
2422
2569
  ## Server Devices
2423
2570
 
2424
2571
  def list_devices(args)
@@ -2915,12 +2915,18 @@ class Morpheus::Cli::Instances
2915
2915
  options = {}
2916
2916
  optparse = Morpheus::Cli::OptionParser.new do |opts|
2917
2917
  opts.banner = subcommand_usage("[instance]")
2918
- opts.on( '--name VALUE', String, "Snapshot Name. Default is server name + timestamp" ) do |val|
2918
+ opts.on( '--name VALUE', String, "Snapshot Name. Default is \"{name}.{timestamp}\"" ) do |val|
2919
2919
  options[:options]['name'] = val
2920
2920
  end
2921
2921
  opts.on( '--description VALUE', String, "Snapshot Description." ) do |val|
2922
2922
  options[:options]['description'] = val
2923
2923
  end
2924
+ opts.on('--memory-snapshot [on|off]', String, "Memory Snapshot? Whether to include the memory state in the snapshot.") do |val|
2925
+ options[:options]['memorySnapshot'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
2926
+ end
2927
+ opts.on('--for-export [on|off]', String, "For Export? Indicates the snapshot is intended for export to storage.") do |val|
2928
+ options[:options]['forExport'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
2929
+ end
2924
2930
  opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
2925
2931
  options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
2926
2932
  end
@@ -2937,15 +2943,36 @@ EOT
2937
2943
  verify_args!(args:args, optparse:optparse, count:1)
2938
2944
  connect(options)
2939
2945
  instance = find_instance_by_name_or_id(args[0])
2940
- unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to snapshot the instance '#{instance['name']}'?", options)
2941
- exit 1
2942
- end
2946
+
2943
2947
  payload = {}
2944
2948
  if options[:payload]
2945
2949
  payload = options[:payload]
2946
2950
  payload.deep_merge!({'snapshot' => parse_passed_options(options)})
2947
2951
  else
2948
2952
  payload.deep_merge!({'snapshot' => parse_passed_options(options)})
2953
+ snapshot = payload['snapshot']
2954
+ # prompt for name and description
2955
+ name = prompt_value({'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Snapshot Name', 'description' => "Snapshot Name. Default is \"{name}.{timestamp}\""}, options)
2956
+ snapshot['name'] = name if !name.to_s.empty?
2957
+ description = prompt_value({'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'description' => "Snapshot Description."}, options)
2958
+ snapshot['description'] = description if !description.to_s.empty?
2959
+ # need to GET provision type for some settings...
2960
+ provision_type = nil
2961
+ begin
2962
+ provision_type = @provision_types_interface.get(instance['layout']['provisionTypeId'])['provisionType']
2963
+ rescue => ex
2964
+ Morpheus::Logging::DarkPrinter.puts "Failed to load provision type!" if Morpheus::Logging.debug?
2965
+ end
2966
+ if provision_type && provision_type['hasMemorySnapshots']
2967
+ # prompt for memorySnapshot
2968
+ memory_snapshot = prompt_value({'fieldName' => 'memorySnapshot', 'type' => 'checkbox', 'fieldLabel' => 'Memory Snapshot?', 'description' => "Snapshot Description."}, options)
2969
+ snapshot['memorySnapshot'] = memory_snapshot if !memory_snapshot.to_s.empty?
2970
+ end
2971
+ # convert "on" and "off" to true/false
2972
+ payload.booleanize!
2973
+ end
2974
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to snapshot the instance '#{instance['name']}'?", options)
2975
+ exit 1
2949
2976
  end
2950
2977
  @instances_interface.setopts(options)
2951
2978
  if options[:dry_run]
@@ -3470,17 +3497,18 @@ EOT
3470
3497
  def snapshots(args)
3471
3498
  options = {}
3472
3499
  optparse = Morpheus::Cli::OptionParser.new do |opts|
3473
- opts.banner = subcommand_usage("[instance]")
3500
+ opts.banner = subcommand_usage("[instance] [snapshot]")
3474
3501
  # no pagination yet
3475
3502
  # build_standard_list_options(opts, options)
3476
- build_standard_get_options(opts, options)
3503
+ build_standard_list_options(opts, options, [:details])
3477
3504
  opts.footer = <<-EOT
3478
3505
  List snapshots for an instance.
3479
3506
  [instance] is required. This is the name or id of an instance
3507
+ [snapshot] is optional. this is the name or id a snapshot to filter by.
3480
3508
  EOT
3481
3509
  end
3482
3510
  optparse.parse!(args)
3483
- verify_args!(args:args, optparse:optparse, count:1)
3511
+ verify_args!(args:args, optparse:optparse, min:1, max: 2)
3484
3512
  connect(options)
3485
3513
  begin
3486
3514
  instance = find_instance_by_name_or_id(args[0])
@@ -3491,25 +3519,52 @@ EOT
3491
3519
  return
3492
3520
  end
3493
3521
  json_response = @instances_interface.snapshots(instance['id'], params)
3494
- snapshots = json_response['snapshots']
3522
+ snapshots = json_response['snapshots']
3523
+ # [snapshots] is done with post api filtering by id or name or externalId
3524
+ if args[1]
3525
+ if args[1] =~ /\A\d{1,}\Z/
3526
+ snapshots = snapshots.select {|it| it['id'].to_s == args[1] }
3527
+ else
3528
+ # snapshots = snapshots.select {|it| it['name'] == args[1] || it['externalId'] == args[1] }
3529
+ # match beginning of name of externalId
3530
+ snapshots = snapshots.select {|it| it['name'].to_s.index(args[1]) == 0 || it['externalId'].to_s.index(args[1]) == 0 }
3531
+ end
3532
+ json_response['snapshots'] = snapshots # update response for -j filtering too
3533
+ end
3495
3534
  render_response(json_response, options, 'snapshots') do
3496
3535
  print_h1 "Snapshots: #{instance['name']} (#{instance['instanceType']['name']})", [], options
3497
3536
  if snapshots.empty?
3498
- print cyan,"No snapshots found",reset,"\n"
3537
+ if args[1]
3538
+ print cyan,"No snapshots found for '#{args[1]}'",reset,"\n"
3539
+ elsif
3540
+ print cyan,"No snapshots found",reset,"\n"
3541
+ end
3542
+ print reset, "\n"
3499
3543
  else
3500
- snapshot_column_definitions = {
3501
- "ID" => lambda {|it| it['id'] },
3502
- "Name" => lambda {|it| it['name'] },
3503
- "Description" => lambda {|it| it['description'] },
3504
- # "Type" => lambda {|it| it['snapshotType'] },
3505
- "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
3506
- "Status" => lambda {|it| format_snapshot_status(it) }
3507
- }
3508
- print cyan
3509
- print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
3510
- print_results_pagination({size: snapshots.size, total: snapshots.size})
3544
+ if options[:details]
3545
+ if snapshots.size > 3
3546
+ print cyan, "Showing first 3 snapshots. Use the ID to get more details.", reset, "\n"
3547
+ snapshots = snapshots.first(3) # this actually makes a request for each one here so don't go crazy...
3548
+ end
3549
+ snapshots.each do |snapshot|
3550
+ Morpheus::Cli::Snapshots.new.handle(["get", snapshot['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
3551
+ end
3552
+ else
3553
+ # Snapshots List
3554
+ snapshot_column_definitions = {
3555
+ "ID" => lambda {|it| it['id'] },
3556
+ "Name" => lambda {|it| it['name'] },
3557
+ "Description" => lambda {|it| it['description'] },
3558
+ # "Type" => lambda {|it| it['snapshotType'] },
3559
+ "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
3560
+ "Status" => lambda {|it| format_snapshot_status(it) }
3561
+ }
3562
+ print cyan
3563
+ print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
3564
+ print_results_pagination({size: snapshots.size, total: snapshots.size})
3565
+ print reset, "\n"
3566
+ end
3511
3567
  end
3512
- print reset, "\n"
3513
3568
  end
3514
3569
  return 0
3515
3570
  rescue RestClient::Exception => e
@@ -326,6 +326,7 @@ class Morpheus::Cli::License
326
326
  'Never'
327
327
  end
328
328
  },
329
+ "Version" => lambda {|it| it["licenseVersion"] },
329
330
  "Multi-Tenant" => lambda {|it| format_boolean it["multiTenant"] },
330
331
  "White Label" => lambda {|it| format_boolean it["whitelabel"] },
331
332
  "Stats Reporting" => lambda {|it| format_boolean it["reportStatus"] },
@@ -361,6 +362,7 @@ class Morpheus::Cli::License
361
362
  used_hosts = current_usage['hosts']
362
363
  used_mvm = current_usage['mvm']
363
364
  used_mvm_sockets = current_usage['mvmSockets']
365
+ used_sockets = current_usage['sockets'].to_f.round(1)
364
366
  used_iac = current_usage['iac']
365
367
  used_xaas = current_usage['xaas']
366
368
  used_executions = current_usage['executions']
@@ -373,6 +375,7 @@ class Morpheus::Cli::License
373
375
  max_hosts = license['maxHosts']
374
376
  max_mvm = license['maxMvm']
375
377
  max_mvm_sockets = license['maxMvmSockets']
378
+ max_sockets = license['maxSockets']
376
379
  max_iac = license['maxIac']
377
380
  max_xaas = license['maxXaas']
378
381
  max_executions = license['maxExecutions']
@@ -381,6 +384,7 @@ class Morpheus::Cli::License
381
384
  label_width = 20
382
385
  chart_opts = {max_bars: 20, unlimited_label: '0%', percent_sigdig: 0}
383
386
  out = ""
387
+ out << cyan + "Sockets".rjust(label_width, ' ') + ": " + generate_usage_bar(used_sockets, max_sockets, chart_opts) + cyan + used_sockets.to_s.rjust(8, ' ') + " / " + (max_sockets ? max_sockets.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
384
388
  out << cyan + "Managed Servers".rjust(label_width, ' ') + ": " + generate_usage_bar(used_managed_servers, max_managed_servers, chart_opts) + cyan + used_managed_servers.to_s.rjust(8, ' ') + " / " + (max_managed_servers ? max_managed_servers.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
385
389
  out << cyan + "Discovered Servers".rjust(label_width, ' ') + ": " + generate_usage_bar(used_discovered_servers, max_discovered_servers, chart_opts) + cyan + used_discovered_servers.to_s.rjust(8, ' ') + " / " + (max_discovered_servers ? max_discovered_servers.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
386
390
  out << cyan + "Hosts".rjust(label_width, ' ') + ": " + generate_usage_bar(used_hosts, max_hosts, chart_opts) + cyan + used_hosts.to_s.rjust(8, ' ') + " / " + (max_hosts ? max_hosts.to_s : unlimited_label).to_s.ljust(15, ' ') + "\n"
@@ -439,6 +443,7 @@ class Morpheus::Cli::License
439
443
  'Never'
440
444
  end
441
445
  },
446
+ "Version" => lambda {|it| it["licenseVersion"] },
442
447
  "Multi-Tenant" => lambda {|it| format_boolean it["multiTenant"] },
443
448
  "White Label" => lambda {|it| format_boolean it["whitelabel"] },
444
449
  "Stats Reporting" => lambda {|it| format_boolean it["reportStatus"] },
@@ -451,11 +456,12 @@ class Morpheus::Cli::License
451
456
  })
452
457
  else
453
458
  license_columns.merge!({
459
+ "Sockets" => 'maxSockets',
460
+ "HPE VM Sockets" => 'maxMvmSockets',
454
461
  "Managed Servers" => 'maxManagedServers',
455
462
  "Discovered Servers" => 'maxDiscoveredServers',
456
463
  "Hosts" => 'maxHosts',
457
464
  "HPE VM Hosts" => 'maxMvm',
458
- "HPE VM Sockets" => 'maxMvmSockets',
459
465
  "Iac Deployments" => 'maxIac',
460
466
  "Xaas Instances" => 'maxXaas',
461
467
  "Executions" => 'maxExecutions',
@@ -153,6 +153,7 @@ class Morpheus::Cli::ServicePlanCommand
153
153
  "Code" => lambda {|it| it['code']},
154
154
  "Display Order" => lambda {|it| it['sortOrder']},
155
155
  "Provision Type" => lambda {|it| it['provisionType'] ? it['provisionType']['name'] : ''},
156
+ "Server Type" => lambda {|it| it['serverType']},
156
157
  "Storage" => lambda {|it| printable_byte_size(it, it['maxStorage'], 'storageSizeType', 'GB')}
157
158
  }
158
159
 
@@ -77,11 +77,15 @@ class Morpheus::Cli::Snapshots
77
77
  "Snapshot Type" => 'snapshotType',
78
78
  "Cloud" => lambda {|it| format_name_and_id(it['zone']) },
79
79
  "Datastore" => lambda {|it| format_name_and_id(it['datastore']) },
80
+ "Memory Snapshot" => lambda {|it| format_boolean(it['memorySnapshot']) },
81
+ "For Export" => lambda {|it| format_boolean(it['forExport']) },
80
82
  "Parent Snapshot" => lambda {|it| format_name_and_id(it['parentSnapshot']) },
81
83
  "Active" => lambda {|it| format_boolean(it['currentlyActive']) },
82
84
  "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
83
85
  "Status" => lambda {|it| format_snapshot_status(it) }
84
86
  }
87
+ description_cols.delete("Memory Snapshot") if !snapshot['memorySnapshot']
88
+ description_cols.delete("For Export") if !snapshot['forExport']
85
89
  print_description_list(description_cols, snapshot)
86
90
 
87
91
  print reset, "\n"
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "8.0.6"
4
+ VERSION = "8.0.8"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.6
4
+ version: 8.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2025-05-22 00:00:00.000000000 Z
14
+ date: 2025-07-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: public_suffix