morpheus-cli 8.0.11.1 → 8.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/migrations_interface.rb +49 -0
- data/lib/morpheus/cli/commands/benchmark_command.rb +3 -4
- data/lib/morpheus/cli/commands/clouds.rb +29 -22
- data/lib/morpheus/cli/commands/cluster_types.rb +179 -0
- data/lib/morpheus/cli/commands/clusters.rb +37 -22
- data/lib/morpheus/cli/commands/hosts.rb +37 -3
- data/lib/morpheus/cli/commands/instances.rb +25 -0
- data/lib/morpheus/cli/commands/migrations.rb +453 -0
- data/lib/morpheus/cli/commands/networks_command.rb +1 -1
- data/lib/morpheus/cli/mixins/processes_helper.rb +136 -0
- data/lib/morpheus/cli/mixins/rest_command.rb +2 -2
- data/lib/morpheus/cli/option_types.rb +5 -3
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/routes.rb +2 -1
- data/test/cli/migrations_test.rb +39 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30f5740960bec8ff3b96aa8e7da68862d310d4375fc7c48c11fd31841ac5310c
|
|
4
|
+
data.tar.gz: ae66b58b6702afeed4e30edc44b019a1e73e2ea11179f0ab6507edf250275977
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 795b92277a1dbc2ad7ec6a933469fcf0ab77f8c7e8d261b5502e218f3a72cfda0856bff14d94b043b4f3371ec2cbd89d8522df6c57b87477d75949e70b975436
|
|
7
|
+
data.tar.gz: cfdc201519632bf6f6b51155611b35ffe4c299733bda2c16c19109bae37174112439aa728ecebcff42c1646496060698952af332a444d7a32ab46b5e260789f7
|
data/Dockerfile
CHANGED
|
@@ -1022,6 +1022,10 @@ class Morpheus::APIClient
|
|
|
1022
1022
|
Morpheus::LibraryOperatingSystemsInterface.new(common_interface_options).setopts(@options)
|
|
1023
1023
|
end
|
|
1024
1024
|
|
|
1025
|
+
def migrations
|
|
1026
|
+
Morpheus::MigrationsInterface.new(common_interface_options).setopts(@options)
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1025
1029
|
def rest(endpoint)
|
|
1026
1030
|
Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
|
|
1027
1031
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'morpheus/api/rest_interface'
|
|
2
|
+
|
|
3
|
+
class Morpheus::MigrationsInterface < Morpheus::RestInterface
|
|
4
|
+
|
|
5
|
+
def base_path
|
|
6
|
+
"/api/migrations"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def source_clouds(params={}, headers={})
|
|
10
|
+
execute(method: :get, url: "#{base_path}/source-clouds", params: params, headers: headers)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def target_clouds(params={}, headers={})
|
|
14
|
+
execute(method: :get, url: "#{base_path}/target-clouds", params: params, headers: headers)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def source_servers(params={}, headers={})
|
|
18
|
+
execute(method: :get, url: "#{base_path}/source-servers", params: params, headers: headers)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def source_networks(params={}, headers={})
|
|
22
|
+
execute(method: :get, url: "#{base_path}/source-networks", params: params, headers: headers)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def target_networks(params={}, headers={})
|
|
26
|
+
execute(method: :get, url: "#{base_path}/target-networks", params: params, headers: headers)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def source_storage(params={}, headers={})
|
|
30
|
+
execute(method: :get, url: "#{base_path}/source-storage", params: params, headers: headers)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def target_storage(params={}, headers={})
|
|
34
|
+
execute(method: :get, url: "#{base_path}/target-storage", params: params, headers: headers)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# def target_pools(params={}, headers={})
|
|
38
|
+
# execute(method: :get, url: "#{base_path}/target-pools", params: params, headers: headers)
|
|
39
|
+
# end
|
|
40
|
+
|
|
41
|
+
# def target_groups(params={}, headers={})
|
|
42
|
+
# execute(method: :get, url: "#{base_path}/target-groups", params: params, headers: headers)
|
|
43
|
+
# end
|
|
44
|
+
|
|
45
|
+
def run(id, payload={}, params={}, headers={})
|
|
46
|
+
execute(method: :post, url: "#{base_path}/#{CGI::escape(id.to_s)}/run", params: params, payload: payload, headers: headers)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -353,10 +353,9 @@ EOT
|
|
|
353
353
|
out << "#{benchmark_name.ljust(30, ' ')}"
|
|
354
354
|
# exit: 0
|
|
355
355
|
exit_code = benchmark_record.exit_code
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
out << "\
|
|
359
|
-
out << "\terror: #{bad_benchmark.error.to_s.ljust(12, ' ')}"
|
|
356
|
+
if benchmark_record.exit_code && benchmark_record.exit_code != 0
|
|
357
|
+
out << "\texit: #{benchmark_record.exit_code.to_s.ljust(2, ' ')}"
|
|
358
|
+
out << "\terror: #{benchmark_record.error.to_s.ljust(12, ' ')}"
|
|
360
359
|
else
|
|
361
360
|
out << "\texit: 0 "
|
|
362
361
|
end
|
|
@@ -4,6 +4,7 @@ class Morpheus::Cli::Clouds
|
|
|
4
4
|
include Morpheus::Cli::CliCommand
|
|
5
5
|
include Morpheus::Cli::InfrastructureHelper
|
|
6
6
|
include Morpheus::Cli::ProvisioningHelper
|
|
7
|
+
include Morpheus::Cli::WhoamiHelper
|
|
7
8
|
|
|
8
9
|
register_subcommands :list, :count, :get, :add, :update, :remove, :refresh, :security_groups, :apply_security_groups
|
|
9
10
|
register_subcommands :types, :type
|
|
@@ -1250,12 +1251,7 @@ EOT
|
|
|
1250
1251
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1251
1252
|
opts.banner = subcommand_usage( "[cloud] [name] [options]")
|
|
1252
1253
|
build_option_type_options(opts, options, add_cloud_affinity_group_option_types)
|
|
1253
|
-
|
|
1254
|
-
# options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
|
|
1255
|
-
# end
|
|
1256
|
-
# opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
|
1257
|
-
# options[:no_refresh] = true
|
|
1258
|
-
# end
|
|
1254
|
+
add_perms_options(opts, options, ['plans'])
|
|
1259
1255
|
build_standard_add_options(opts, options)
|
|
1260
1256
|
opts.footer = "Add affinity group to a cloud.\n" +
|
|
1261
1257
|
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
@@ -1294,10 +1290,10 @@ EOT
|
|
|
1294
1290
|
# end
|
|
1295
1291
|
|
|
1296
1292
|
# perms
|
|
1297
|
-
perms = prompt_permissions(options
|
|
1293
|
+
perms = prompt_permissions(options, is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
1298
1294
|
|
|
1299
|
-
affinity_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].
|
|
1300
|
-
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].
|
|
1295
|
+
affinity_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].empty?
|
|
1296
|
+
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].empty? || perms['tenantPermissions']['accounts'].empty?
|
|
1301
1297
|
affinity_group['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
1302
1298
|
|
|
1303
1299
|
payload = {'affinityGroup' => affinity_group}
|
|
@@ -1337,10 +1333,8 @@ EOT
|
|
|
1337
1333
|
options = {}
|
|
1338
1334
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1339
1335
|
opts.banner = subcommand_usage( "[cloud] [affinity group] [options]")
|
|
1340
|
-
opts
|
|
1341
|
-
|
|
1342
|
-
end
|
|
1343
|
-
add_perms_options(opts, options, ['groupDefaults'])
|
|
1336
|
+
build_option_type_options(opts, options, update_cloud_affinity_group_option_types)
|
|
1337
|
+
add_perms_options(opts, options, ['plans'])
|
|
1344
1338
|
build_standard_update_options(opts, options)
|
|
1345
1339
|
opts.footer = "Update a cloud affinity group.\n" +
|
|
1346
1340
|
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
@@ -1370,19 +1364,25 @@ EOT
|
|
|
1370
1364
|
end
|
|
1371
1365
|
else
|
|
1372
1366
|
payload = {'affinityGroup' => {}}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1367
|
+
options[:params] ||= {}
|
|
1368
|
+
options[:params].merge!({:cloudId => cloud['id'],:zoneId => cloud['id']})
|
|
1369
|
+
option_types = update_cloud_affinity_group_option_types
|
|
1370
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(option_types, options[:options], @api_client, options[:params])
|
|
1371
|
+
v_prompt.deep_compact!.booleanize!
|
|
1372
|
+
payload.deep_merge!({'affinityGroup' => v_prompt})
|
|
1373
|
+
|
|
1374
|
+
perms = prompt_permissions(options.merge({:no_prompt => true}), is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
1375
|
+
|
|
1376
1376
|
perms_payload = {}
|
|
1377
|
-
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].nil?
|
|
1378
|
-
perms_payload['tenantPermissions'] = perms['tenantPermissions'] if !perms['tenantPermissions'].nil?
|
|
1379
|
-
|
|
1380
|
-
payload['affinityGroup']['permissions'] = perms_payload
|
|
1377
|
+
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].nil? && !perms['resourcePermissions'].empty?
|
|
1378
|
+
perms_payload['tenantPermissions'] = perms['tenantPermissions'] if !perms['tenantPermissions'].nil? && !perms['tenantPermissions']['accounts'].empty?
|
|
1379
|
+
|
|
1380
|
+
payload['affinityGroup']['permissions'] = perms_payload if !perms_payload.empty?
|
|
1381
1381
|
payload['affinityGroup']['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
1382
1382
|
|
|
1383
1383
|
# support -O OPTION switch on top of everything
|
|
1384
1384
|
if options[:options]
|
|
1385
|
-
payload.deep_merge!({'affinityGroup' => options[:options].reject {|k,v| k.is_a?(Symbol) }})
|
|
1385
|
+
payload.deep_merge!({'affinityGroup' => options[:options].reject {|k,v| k.is_a?(Symbol) || payload['affinityGroup'].key?(k) }})
|
|
1386
1386
|
end
|
|
1387
1387
|
|
|
1388
1388
|
if payload['affinityGroup'].nil? || payload['affinityGroup'].empty?
|
|
@@ -1599,7 +1599,14 @@ EOT
|
|
|
1599
1599
|
{'fieldName' => 'affinityType', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Keep Separate', 'value' => 'KEEP_SEPARATE'}, {'name' => 'Keep Together', 'value' => 'KEEP_TOGETHER'}], 'description' => 'Choose affinity type.', 'required' => true, 'defaultValue' => 'KEEP_SEPARATE'},
|
|
1600
1600
|
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'defaultValue' => true},
|
|
1601
1601
|
{'fieldName' => 'pool.id', 'fieldLabel' => 'Cluster', 'type' => 'select', 'optionSourceType' => 'vmware', 'optionSource' => 'vmwareZonePoolClusters', 'description' => 'Select cluster for the affinity group.', 'required' => true},
|
|
1602
|
-
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => '
|
|
1602
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers', 'description' => 'Select servers to be in the affinity group.'},
|
|
1603
|
+
]
|
|
1604
|
+
end
|
|
1605
|
+
|
|
1606
|
+
def update_cloud_affinity_group_option_types
|
|
1607
|
+
[
|
|
1608
|
+
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox'},
|
|
1609
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers', 'description' => 'Select servers to be in the affinity group.'},
|
|
1603
1610
|
]
|
|
1604
1611
|
end
|
|
1605
1612
|
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class Morpheus::Cli::ClusterTypes
|
|
4
|
+
include Morpheus::Cli::CliCommand
|
|
5
|
+
|
|
6
|
+
set_command_description "View cluster types."
|
|
7
|
+
set_command_name :'cluster-types'
|
|
8
|
+
register_subcommands :list, :get
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# This is a hidden command, documenting clusters list-types and clusters get-type
|
|
12
|
+
set_command_hidden
|
|
13
|
+
|
|
14
|
+
def connect(opts)
|
|
15
|
+
@api_client = establish_remote_appliance_connection(opts)
|
|
16
|
+
@clusters_interface = @api_client.clusters
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def handle(args)
|
|
20
|
+
handle_subcommand(args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def list(args)
|
|
24
|
+
options = {}
|
|
25
|
+
params = {}
|
|
26
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
27
|
+
opts.banner = "Usage: #{prog_name} clusters list-types [search]"
|
|
28
|
+
#opts.banner = subcommand_usage("[search]")
|
|
29
|
+
# opts.on('--optionTypes [true|false]', String, "Include optionTypes in the response. Default is false.") do |val|
|
|
30
|
+
# params['optionTypes'] = (val.to_s == '' || val.to_s == 'on' || val.to_s == 'true')
|
|
31
|
+
# end
|
|
32
|
+
build_standard_list_options(opts, options)
|
|
33
|
+
opts.footer = "List cluster types."
|
|
34
|
+
end
|
|
35
|
+
optparse.parse!(args)
|
|
36
|
+
connect(options)
|
|
37
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
|
38
|
+
if args.count > 0
|
|
39
|
+
options[:phrase] = args.join(" ")
|
|
40
|
+
end
|
|
41
|
+
params.merge!(parse_list_options(options))
|
|
42
|
+
@clusters_interface.setopts(options)
|
|
43
|
+
if options[:dry_run]
|
|
44
|
+
print_dry_run @clusters_interface.dry.cluster_types(params)
|
|
45
|
+
return
|
|
46
|
+
end
|
|
47
|
+
json_response = @clusters_interface.cluster_types(params)
|
|
48
|
+
render_response(json_response, options, "clusterTypes") do
|
|
49
|
+
cluster_types = json_response["clusterTypes"]
|
|
50
|
+
print_h1 "Morpheus Cluster Types", parse_list_subtitles(options), options
|
|
51
|
+
if cluster_types.empty?
|
|
52
|
+
print cyan,"No cluster types found.",reset,"\n"
|
|
53
|
+
else
|
|
54
|
+
list_columns = {
|
|
55
|
+
"ID" => 'id',
|
|
56
|
+
"NAME" => 'name',
|
|
57
|
+
"CODE" => 'code',
|
|
58
|
+
"DESCRIPTION" => lambda {|it| truncate_string(it['description'], options[:wrap] ? nil : 100) },
|
|
59
|
+
}
|
|
60
|
+
print as_pretty_table(cluster_types, list_columns, options)
|
|
61
|
+
print_results_pagination(json_response)
|
|
62
|
+
end
|
|
63
|
+
print reset,"\n"
|
|
64
|
+
end
|
|
65
|
+
return 0, nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def get(args)
|
|
69
|
+
params = {}
|
|
70
|
+
options = {}
|
|
71
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
72
|
+
opts.banner = "Usage: #{prog_name} clusters get-type [type] "
|
|
73
|
+
# opts.banner = subcommand_usage("[type]")
|
|
74
|
+
# opts.on('--optionTypes [true|false]', String, "Include optionTypes in the response. Default is true.") do |val|
|
|
75
|
+
# params['optionTypes'] = (val.to_s == '' || val.to_s == 'on' || val.to_s == 'true')
|
|
76
|
+
# end
|
|
77
|
+
build_standard_get_options(opts, options)
|
|
78
|
+
opts.footer = <<-EOT
|
|
79
|
+
Get details about a specific cluster type.
|
|
80
|
+
[type] is required. This is the name or id of a cluster type.
|
|
81
|
+
EOT
|
|
82
|
+
end
|
|
83
|
+
optparse.parse!(args)
|
|
84
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
85
|
+
id = args.join(" ")
|
|
86
|
+
connect(options)
|
|
87
|
+
params.merge!(parse_query_options(options))
|
|
88
|
+
cluster_type = nil
|
|
89
|
+
|
|
90
|
+
# /api/cluster-types/$id does not exist, this loads them all.
|
|
91
|
+
# todo: fix api to support /api/cluster-types/$id
|
|
92
|
+
cluster_type = find_cluster_type_by_name_or_id(id)
|
|
93
|
+
if cluster_type.nil?
|
|
94
|
+
raise_command_error("cluster type not found for name or id '#{id}'") if cluster_type.nil?
|
|
95
|
+
end
|
|
96
|
+
id = cluster_type['id']
|
|
97
|
+
# /api/cluster-types does not return optionTypes by default, use ?optionTypes=true
|
|
98
|
+
@clusters_interface.setopts(options)
|
|
99
|
+
if options[:dry_run]
|
|
100
|
+
# print_dry_run @clusters_interface.dry.get_type(id, params)
|
|
101
|
+
print_dry_run @clusters_interface.dry.cluster_types(params)
|
|
102
|
+
return
|
|
103
|
+
end
|
|
104
|
+
# json_response = @clusters_interface.get(id, params)
|
|
105
|
+
# cluster_type = json_response[cluster_type_object_key]
|
|
106
|
+
json_response = cluster_type
|
|
107
|
+
render_response(json_response, options) do
|
|
108
|
+
print_h1 "Cluster Type Details", [], options
|
|
109
|
+
print cyan
|
|
110
|
+
show_columns = list_columns = {
|
|
111
|
+
"ID" => 'id',
|
|
112
|
+
"Name" => 'name',
|
|
113
|
+
"Code" => 'code',
|
|
114
|
+
"Description" => 'description',
|
|
115
|
+
}
|
|
116
|
+
print_description_list(show_columns, cluster_type)
|
|
117
|
+
|
|
118
|
+
if cluster_type['optionTypes'] && cluster_type['optionTypes'].size > 0
|
|
119
|
+
print_h2 "Configuration Options"
|
|
120
|
+
opt_columns = [
|
|
121
|
+
# {"ID" => lambda {|it| it['id'] } },
|
|
122
|
+
{"FIELD NAME" => lambda {|it| (it['fieldContext'] && it['fieldContext'] != 'domain') ? [it['fieldContext'], it['fieldName']].join('.') : it['fieldName'] } },
|
|
123
|
+
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
|
124
|
+
{"TYPE" => lambda {|it| it['type'] } },
|
|
125
|
+
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
|
126
|
+
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
|
127
|
+
# {"DESCRIPTION" => lambda {|it| it['description'] }, # do it!
|
|
128
|
+
]
|
|
129
|
+
print as_pretty_table(cluster_type['optionTypes'], opt_columns)
|
|
130
|
+
else
|
|
131
|
+
# print cyan,"No option types found for this cluster type.","\n",reset
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
controller_types = cluster_type['controllerTypes'] || []
|
|
135
|
+
if controller_types && controller_types.size > 0
|
|
136
|
+
print_h2 "Controller Types"
|
|
137
|
+
print as_pretty_table(controller_types, [:name, :code], options)
|
|
138
|
+
else
|
|
139
|
+
# print cyan,"No worker types found for this cluster type.","\n",reset
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
worker_types = cluster_type['workerTypes'] || []
|
|
143
|
+
if worker_types && worker_types.size > 0
|
|
144
|
+
print_h2 "Worker Types"
|
|
145
|
+
print as_pretty_table(worker_types, [:name, :code], options)
|
|
146
|
+
else
|
|
147
|
+
# print cyan,"No worker types found for this cluster type.","\n",reset
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
print reset,"\n"
|
|
151
|
+
end
|
|
152
|
+
return 0, nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
protected
|
|
156
|
+
|
|
157
|
+
def find_cluster_type_by_name_or_id(val)
|
|
158
|
+
(val.to_s =~ /\A\d{1,}\Z/) ? find_cluster_type_by_id(val) : find_cluster_type_by_name(val)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def find_cluster_type_by_id(id)
|
|
162
|
+
get_cluster_types.find { |it| it['id'] == id.to_i }
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def find_cluster_type_by_name(name)
|
|
166
|
+
get_cluster_types.find { |it| it['name'].downcase == name.downcase || it['code'].downcase == name.downcase }
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def cluster_types_for_dropdown
|
|
170
|
+
get_cluster_types.collect {|it| {'id' => it['id'], 'name' => it['name'], 'code' => it['code'], 'value' => it['code']} }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def get_cluster_types(refresh=false)
|
|
174
|
+
if !@cluster_types || refresh
|
|
175
|
+
@cluster_types = @clusters_interface.cluster_types()['clusterTypes']
|
|
176
|
+
end
|
|
177
|
+
@cluster_types
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -9,6 +9,7 @@ class Morpheus::Cli::Clusters
|
|
|
9
9
|
include Morpheus::Cli::ExecutionRequestHelper
|
|
10
10
|
|
|
11
11
|
register_subcommands :list, :count, :get, :view, :add, :update, :remove, :logs, :history, {:'history-details' => :history_details}, {:'history-event' => :history_event_details}
|
|
12
|
+
register_subcommands :list_types, :get_type
|
|
12
13
|
register_subcommands :list_workers, :add_worker, :remove_worker, :update_worker_count
|
|
13
14
|
register_subcommands :list_masters
|
|
14
15
|
register_subcommands :upgrade_cluster
|
|
@@ -3409,12 +3410,7 @@ class Morpheus::Cli::Clusters
|
|
|
3409
3410
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
3410
3411
|
opts.banner = subcommand_usage( "[cluster] [name] [options]")
|
|
3411
3412
|
build_option_type_options(opts, options, add_affinity_group_option_types)
|
|
3412
|
-
|
|
3413
|
-
# options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
|
|
3414
|
-
# end
|
|
3415
|
-
# opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
|
3416
|
-
# options[:no_refresh] = true
|
|
3417
|
-
# end
|
|
3413
|
+
add_perms_options(opts, options, ['plans'])
|
|
3418
3414
|
build_standard_add_options(opts, options)
|
|
3419
3415
|
opts.footer = "Add affinity group to a cluster.\n" +
|
|
3420
3416
|
"[cluster] is required. This is the name or id of an existing cluster.\n" +
|
|
@@ -3453,10 +3449,10 @@ class Morpheus::Cli::Clusters
|
|
|
3453
3449
|
# end
|
|
3454
3450
|
|
|
3455
3451
|
# perms
|
|
3456
|
-
perms = prompt_permissions(options
|
|
3452
|
+
perms = prompt_permissions(options, is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
3457
3453
|
|
|
3458
3454
|
affinity_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].nil?
|
|
3459
|
-
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].nil?
|
|
3455
|
+
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].nil? || perms['tenantPermissions']['accounts'].empty?
|
|
3460
3456
|
affinity_group['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
3461
3457
|
|
|
3462
3458
|
payload = {'affinityGroup' => affinity_group}
|
|
@@ -3496,10 +3492,8 @@ class Morpheus::Cli::Clusters
|
|
|
3496
3492
|
options = {}
|
|
3497
3493
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
3498
3494
|
opts.banner = subcommand_usage( "[cluster] [affinity group] [options]")
|
|
3499
|
-
opts
|
|
3500
|
-
|
|
3501
|
-
end
|
|
3502
|
-
# add_perms_options(opts, options, ['groupDefaults'])
|
|
3495
|
+
build_option_type_options(opts, options, update_affinity_group_option_types)
|
|
3496
|
+
add_perms_options(opts, options, ['plans'])
|
|
3503
3497
|
build_standard_update_options(opts, options)
|
|
3504
3498
|
opts.footer = "Update a cluster affinity group.\n" +
|
|
3505
3499
|
"[cluster] is required. This is the name or id of an existing cluster.\n" +
|
|
@@ -3529,19 +3523,25 @@ class Morpheus::Cli::Clusters
|
|
|
3529
3523
|
end
|
|
3530
3524
|
else
|
|
3531
3525
|
payload = {'affinityGroup' => {}}
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3526
|
+
options[:params] ||= {}
|
|
3527
|
+
options[:params].merge!({:serverGroupId => cluster['id']})
|
|
3528
|
+
option_types = update_affinity_group_option_types
|
|
3529
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(option_types, options[:options], @api_client, options[:params])
|
|
3530
|
+
v_prompt.deep_compact!.booleanize!
|
|
3531
|
+
payload.deep_merge!({'affinityGroup' => v_prompt})
|
|
3532
|
+
|
|
3533
|
+
perms = prompt_permissions(options.merge({:no_prompt => true}), is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
3534
|
+
|
|
3535
3535
|
perms_payload = {}
|
|
3536
|
-
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].nil?
|
|
3537
|
-
perms_payload['tenantPermissions'] = perms['tenantPermissions'] if !perms['tenantPermissions'].nil?
|
|
3538
|
-
|
|
3539
|
-
payload['affinityGroup']['permissions'] = perms_payload
|
|
3536
|
+
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].nil? && !perms['resourcePermissions'].empty?
|
|
3537
|
+
perms_payload['tenantPermissions'] = perms['tenantPermissions'] if !perms['tenantPermissions'].nil? && !perms['tenantPermissions']['accounts'].empty?
|
|
3538
|
+
|
|
3539
|
+
payload['affinityGroup']['permissions'] = perms_payload if !perms_payload.empty?
|
|
3540
3540
|
payload['affinityGroup']['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
3541
3541
|
|
|
3542
3542
|
# support -O OPTION switch on top of everything
|
|
3543
3543
|
if options[:options]
|
|
3544
|
-
payload.deep_merge!({'affinityGroup' => options[:options].reject {|k,v| k.is_a?(Symbol) }})
|
|
3544
|
+
payload.deep_merge!({'affinityGroup' => options[:options].reject {|k,v| k.is_a?(Symbol) || payload['affinityGroup'].key?(k) }})
|
|
3545
3545
|
end
|
|
3546
3546
|
|
|
3547
3547
|
if payload['affinityGroup'].nil? || payload['affinityGroup'].empty?
|
|
@@ -4413,6 +4413,14 @@ class Morpheus::Cli::Clusters
|
|
|
4413
4413
|
end
|
|
4414
4414
|
end
|
|
4415
4415
|
|
|
4416
|
+
def list_types(args)
|
|
4417
|
+
Morpheus::Cli::ClusterTypes.new.list(args)
|
|
4418
|
+
end
|
|
4419
|
+
|
|
4420
|
+
def get_type(args)
|
|
4421
|
+
Morpheus::Cli::ClusterTypes.new.get(args)
|
|
4422
|
+
end
|
|
4423
|
+
|
|
4416
4424
|
private
|
|
4417
4425
|
|
|
4418
4426
|
def print_clusters_table(clusters, opts={})
|
|
@@ -4621,7 +4629,7 @@ class Morpheus::Cli::Clusters
|
|
|
4621
4629
|
end
|
|
4622
4630
|
|
|
4623
4631
|
def find_cluster_type_by_id(id)
|
|
4624
|
-
get_cluster_types.find { |it| it['id'] == id }
|
|
4632
|
+
get_cluster_types.find { |it| it['id'] == id.to_i }
|
|
4625
4633
|
end
|
|
4626
4634
|
|
|
4627
4635
|
def find_cluster_type_by_name(name)
|
|
@@ -5260,7 +5268,14 @@ class Morpheus::Cli::Clusters
|
|
|
5260
5268
|
{'fieldName' => 'affinityType', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => [{'name' => 'Keep Separate', 'value' => 'KEEP_SEPARATE'}, {'name' => 'Keep Together', 'value' => 'KEEP_TOGETHER'}], 'description' => 'Choose affinity type.', 'required' => true, 'defaultValue' => 'KEEP_SEPARATE'},
|
|
5261
5269
|
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'defaultValue' => true},
|
|
5262
5270
|
# {'fieldName' => 'pool.id', 'fieldLabel' => 'Cluster', 'type' => 'select', 'optionSourceType' => 'vmware', 'optionSource' => 'vmwareZonePoolClusters', 'description' => 'Select cluster for the affinity group.', 'required' => true},
|
|
5263
|
-
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => '
|
|
5271
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers', 'description' => 'Select servers to be in the affinity group.'},
|
|
5272
|
+
]
|
|
5273
|
+
end
|
|
5274
|
+
|
|
5275
|
+
def update_affinity_group_option_types
|
|
5276
|
+
[
|
|
5277
|
+
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox'},
|
|
5278
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers', 'description' => 'Select servers to be in the affinity group.'},
|
|
5264
5279
|
]
|
|
5265
5280
|
end
|
|
5266
5281
|
|
|
@@ -75,6 +75,9 @@ class Morpheus::Cli::Hosts
|
|
|
75
75
|
# params[:clusterId] = val
|
|
76
76
|
options[:cluster] = val
|
|
77
77
|
end
|
|
78
|
+
opts.on( '--parent HOST', "Parent Host / Hypervisor Name or ID" ) do |val|
|
|
79
|
+
options[:parent_server_id] = val
|
|
80
|
+
end
|
|
78
81
|
opts.on( '--plan NAME', String, "Filter by Plan name(s)" ) do |val|
|
|
79
82
|
# commas used in names a lot so use --plan one --plan two
|
|
80
83
|
params['plan'] ||= []
|
|
@@ -188,6 +191,13 @@ class Morpheus::Cli::Hosts
|
|
|
188
191
|
params['clusterId'] = cluster['id']
|
|
189
192
|
end
|
|
190
193
|
end
|
|
194
|
+
parent_hosts = nil
|
|
195
|
+
if options[:parent_server_id]
|
|
196
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
197
|
+
find_host_by_name_or_id(parent_server_id)
|
|
198
|
+
end
|
|
199
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
200
|
+
end
|
|
191
201
|
params['labels'] = options[:labels] if options[:labels]
|
|
192
202
|
if options[:tags] && !options[:tags].empty?
|
|
193
203
|
options[:tags].each do |k,v|
|
|
@@ -233,6 +243,9 @@ class Morpheus::Cli::Hosts
|
|
|
233
243
|
elsif params['clusterId']
|
|
234
244
|
subtitles << "Cluster: #{params['clusterId']}".strip
|
|
235
245
|
end
|
|
246
|
+
if parent_hosts
|
|
247
|
+
subtitles << "Parent Host: #{parent_hosts.collect {|it| it['name'] }.join(", ")}".strip
|
|
248
|
+
end
|
|
236
249
|
subtitles += parse_list_subtitles(options)
|
|
237
250
|
print_h1 title, subtitles, options
|
|
238
251
|
if servers.empty?
|
|
@@ -379,6 +392,13 @@ class Morpheus::Cli::Hosts
|
|
|
379
392
|
opts.on( '-i', '--ip IPADDRESS', "Filter by IP Address" ) do |val|
|
|
380
393
|
params[:ip] = val
|
|
381
394
|
end
|
|
395
|
+
opts.on( '--cluster CLUSTER', '--cluster CLUSTER', "Filter by Cluster Name or ID" ) do |val|
|
|
396
|
+
# params[:clusterId] = val
|
|
397
|
+
options[:cluster] = val
|
|
398
|
+
end
|
|
399
|
+
opts.on( '--parent HOST', "Parent Host / Hypervisor Name or ID" ) do |val|
|
|
400
|
+
options[:parent_server_id] = val
|
|
401
|
+
end
|
|
382
402
|
opts.on('--vm', "Show only virtual machines" ) do
|
|
383
403
|
params[:vm] = true
|
|
384
404
|
end
|
|
@@ -403,9 +423,6 @@ class Morpheus::Cli::Hosts
|
|
|
403
423
|
opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
|
|
404
424
|
options[:created_by] = val
|
|
405
425
|
end
|
|
406
|
-
opts.on('--details', "Display more details: memory and storage usage used / max values." ) do
|
|
407
|
-
options[:details] = true
|
|
408
|
-
end
|
|
409
426
|
opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
|
|
410
427
|
options[:phrase] = phrase
|
|
411
428
|
end
|
|
@@ -443,6 +460,23 @@ class Morpheus::Cli::Hosts
|
|
|
443
460
|
params['createdBy'] = created_by_ids
|
|
444
461
|
# params['ownerId'] = created_by_ids # 4.2.1+
|
|
445
462
|
end
|
|
463
|
+
cluster = nil
|
|
464
|
+
if options[:cluster]
|
|
465
|
+
if options[:cluster].to_s =~ /\A\d{1,}\Z/
|
|
466
|
+
params['clusterId'] = options[:cluster]
|
|
467
|
+
else
|
|
468
|
+
cluster = find_cluster_by_name_or_id(options[:cluster])
|
|
469
|
+
return 1 if cluster.nil?
|
|
470
|
+
params['clusterId'] = cluster['id']
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
parent_hosts = nil
|
|
474
|
+
if options[:parent_server_id]
|
|
475
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
476
|
+
find_host_by_name_or_id(parent_server_id)
|
|
477
|
+
end
|
|
478
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
479
|
+
end
|
|
446
480
|
@servers_interface.setopts(options)
|
|
447
481
|
if options[:dry_run]
|
|
448
482
|
print_dry_run @servers_interface.dry.list(params)
|
|
@@ -83,6 +83,9 @@ class Morpheus::Cli::Instances
|
|
|
83
83
|
opts.on( '-H', '--host HOST', "Host Name or ID" ) do |val|
|
|
84
84
|
options[:host] = val
|
|
85
85
|
end
|
|
86
|
+
opts.on( '--parent HOST', "Parent Host / Hypervisor Name or ID" ) do |val|
|
|
87
|
+
options[:parent_server_id] = val
|
|
88
|
+
end
|
|
86
89
|
opts.on( '--owner USER', "Owner Username or ID" ) do |val|
|
|
87
90
|
options[:owner] = val
|
|
88
91
|
end
|
|
@@ -175,6 +178,14 @@ class Morpheus::Cli::Instances
|
|
|
175
178
|
params['serverId'] = host['id']
|
|
176
179
|
end
|
|
177
180
|
|
|
181
|
+
parent_hosts = nil
|
|
182
|
+
if options[:parent_server_id]
|
|
183
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
184
|
+
find_host_by_name_or_id(parent_server_id)
|
|
185
|
+
end
|
|
186
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
187
|
+
end
|
|
188
|
+
|
|
178
189
|
account = nil
|
|
179
190
|
#todo: user = find_available_user_option(owner_id)
|
|
180
191
|
|
|
@@ -224,6 +235,9 @@ class Morpheus::Cli::Instances
|
|
|
224
235
|
if host
|
|
225
236
|
subtitles << "Host: #{host['name']}".strip
|
|
226
237
|
end
|
|
238
|
+
if parent_hosts
|
|
239
|
+
subtitles << "Parent Host: #{parent_hosts.collect {|it| it['name'] }.join(", ")}".strip
|
|
240
|
+
end
|
|
227
241
|
if options[:owner]
|
|
228
242
|
subtitles << "Created By: #{options[:owner]}"
|
|
229
243
|
end
|
|
@@ -315,6 +329,9 @@ class Morpheus::Cli::Instances
|
|
|
315
329
|
opts.on( '-H', '--host HOST', "Host Name or ID" ) do |val|
|
|
316
330
|
options[:host] = val
|
|
317
331
|
end
|
|
332
|
+
opts.on( '--parent HOST', "Parent Host (Hypervisor) Name or ID" ) do |val|
|
|
333
|
+
options[:parent_server_id] = val
|
|
334
|
+
end
|
|
318
335
|
opts.on( '--owner USER', "Owner Username or ID" ) do |val|
|
|
319
336
|
options[:owner] = val
|
|
320
337
|
end
|
|
@@ -350,6 +367,14 @@ class Morpheus::Cli::Instances
|
|
|
350
367
|
params['serverId'] = host['id']
|
|
351
368
|
end
|
|
352
369
|
|
|
370
|
+
parent_hosts = nil
|
|
371
|
+
if options[:parent_server_id]
|
|
372
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
373
|
+
find_host_by_name_or_id(parent_server_id)
|
|
374
|
+
end
|
|
375
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
376
|
+
end
|
|
377
|
+
|
|
353
378
|
account = nil
|
|
354
379
|
if options[:owner]
|
|
355
380
|
created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:owner])
|