morpheus-cli 9.0.2 → 9.1.0
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/affinity_groups_interface.rb +46 -0
- data/lib/morpheus/api/api_client.rb +13 -0
- data/lib/morpheus/api/clouds_interface.rb +42 -0
- data/lib/morpheus/api/clusters_interface.rb +7 -1
- data/lib/morpheus/api/distributed_workers_interface.rb +41 -0
- data/lib/morpheus/api/host_vm_groups_interface.rb +37 -0
- data/lib/morpheus/cli/commands/affinity_groups_command.rb +554 -0
- data/lib/morpheus/cli/commands/backups_command.rb +1 -1
- data/lib/morpheus/cli/commands/clouds.rb +421 -29
- data/lib/morpheus/cli/commands/clusters.rb +37 -39
- data/lib/morpheus/cli/commands/distributed_workers_command.rb +282 -0
- data/lib/morpheus/cli/commands/host_vm_groups_command.rb +423 -0
- data/lib/morpheus/cli/mixins/affinity_helper.rb +118 -0
- data/lib/morpheus/cli/mixins/infrastructure_helper.rb +137 -0
- data/lib/morpheus/cli/option_types.rb +36 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/test/api/affinity_groups_interface_test.rb +43 -0
- data/test/api/clouds_interface_test.rb +67 -0
- data/test/api/host_vm_groups_interface_test.rb +35 -0
- data/test/cli/affinity_groups_cloud_cluster_scope_test.rb +270 -0
- data/test/cli/affinity_groups_cluster_scope_test.rb +171 -0
- data/test/cli/affinity_groups_test.rb +57 -0
- data/test/cli/affinity_groups_violations_scope_test.rb +141 -0
- data/test/cli/affinity_helper_test.rb +367 -0
- data/test/cli/backups_test.rb +212 -0
- data/test/cli/clusters_uuid_test.rb +131 -0
- data/test/cli/distributed_workers_test.rb +68 -0
- data/test/cli/host_vm_groups_cluster_scope_test.rb +187 -0
- data/test/cli/host_vm_groups_test.rb +63 -0
- data/test/cli/infrastructure_helper_cluster_resolver_test.rb +250 -0
- metadata +37 -2
|
@@ -6,6 +6,7 @@ class Morpheus::Cli::Clouds
|
|
|
6
6
|
include Morpheus::Cli::InfrastructureHelper
|
|
7
7
|
include Morpheus::Cli::ProvisioningHelper
|
|
8
8
|
include Morpheus::Cli::WhoamiHelper
|
|
9
|
+
include Morpheus::Cli::AffinityHelper
|
|
9
10
|
|
|
10
11
|
register_subcommands :list, :count, :get, :add, :update, :remove, :refresh, :security_groups, :apply_security_groups
|
|
11
12
|
register_subcommands :types, :type
|
|
@@ -14,6 +15,7 @@ class Morpheus::Cli::Clouds
|
|
|
14
15
|
register_subcommands :wiki, :update_wiki
|
|
15
16
|
register_subcommands({:'update-logo' => :update_logo,:'update-dark-logo' => :update_dark_logo})
|
|
16
17
|
register_subcommands :list_affinity_groups, :get_affinity_group, :update_affinity_group, :add_affinity_group, :remove_affinity_group
|
|
18
|
+
register_subcommands :list_host_vm_groups, :get_host_vm_group, :add_host_vm_group, :update_host_vm_group, :remove_host_vm_group
|
|
17
19
|
#register_subcommands :firewall_disable, :firewall_enable
|
|
18
20
|
alias_subcommand :details, :get
|
|
19
21
|
set_default_subcommand :list
|
|
@@ -1181,7 +1183,7 @@ EOT
|
|
|
1181
1183
|
def list_affinity_groups(args)
|
|
1182
1184
|
options = {}
|
|
1183
1185
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1184
|
-
opts.banner = subcommand_usage(
|
|
1186
|
+
opts.banner = subcommand_usage("[cloud]")
|
|
1185
1187
|
build_standard_list_options(opts, options)
|
|
1186
1188
|
opts.footer = "List affinity groups for a cloud.\n" +
|
|
1187
1189
|
"[cloud] is required. This is the name or id of an existing cloud."
|
|
@@ -1190,35 +1192,42 @@ EOT
|
|
|
1190
1192
|
optparse.parse!(args)
|
|
1191
1193
|
verify_args!(args:args, optparse:optparse, count:1)
|
|
1192
1194
|
connect(options)
|
|
1193
|
-
|
|
1195
|
+
|
|
1194
1196
|
cloud = find_cloud_by_name_or_id(args[0])
|
|
1195
1197
|
return 1 if cloud.nil?
|
|
1196
1198
|
params = {}
|
|
1197
1199
|
params.merge!(parse_list_options(options))
|
|
1200
|
+
@clouds_interface.setopts(options)
|
|
1201
|
+
if options[:dry_run]
|
|
1202
|
+
print_dry_run @clouds_interface.dry.list_affinity_groups(cloud['id'], params)
|
|
1203
|
+
return
|
|
1204
|
+
end
|
|
1198
1205
|
json_response = @clouds_interface.list_affinity_groups(cloud['id'], params)
|
|
1199
1206
|
render_response(json_response, options, 'affinityGroups') do
|
|
1200
1207
|
affinity_groups = json_response['affinityGroups']
|
|
1201
|
-
print_h1 "
|
|
1208
|
+
print_h1 "Cloud Affinity Groups: \#{cloud['name']}", parse_list_subtitles(options), options
|
|
1202
1209
|
if affinity_groups.empty?
|
|
1203
|
-
print cyan,"No affinity groups found.",reset,"\n"
|
|
1204
|
-
else
|
|
1210
|
+
print cyan, "No affinity groups found.", reset, "\n"
|
|
1211
|
+
else
|
|
1205
1212
|
columns = {
|
|
1206
|
-
"ID"
|
|
1207
|
-
"Name"
|
|
1208
|
-
"Type"
|
|
1209
|
-
"
|
|
1210
|
-
"
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
+
"ID" => 'id',
|
|
1214
|
+
"Name" => 'name',
|
|
1215
|
+
"Type" => lambda {|it| format_affinity_type(it['affinityType']) },
|
|
1216
|
+
"VM Group" => lambda {|it| it['vmGroup'] ? (it['vmGroup']['name'] || it['vmGroup']['id']) : '' },
|
|
1217
|
+
"Host Group" => lambda {|it| it['hostGroup'] ? (it['hostGroup']['name'] || it['hostGroup']['id']) : '' },
|
|
1218
|
+
"Resource Pool" => lambda {|it| it['pool'] ? (it['pool']['name'] || it['pool']['id']) : '' },
|
|
1219
|
+
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
|
1220
|
+
"Servers" => lambda {|it| (it['servers'] || []).size },
|
|
1213
1221
|
}.upcase_keys!
|
|
1214
1222
|
print as_pretty_table(affinity_groups, columns, options)
|
|
1215
1223
|
print_results_pagination(json_response)
|
|
1216
1224
|
end
|
|
1217
|
-
print reset,"\n"
|
|
1225
|
+
print reset, "\n"
|
|
1218
1226
|
end
|
|
1219
1227
|
return 0, nil
|
|
1220
1228
|
end
|
|
1221
1229
|
|
|
1230
|
+
|
|
1222
1231
|
def get_affinity_group(args)
|
|
1223
1232
|
options = {}
|
|
1224
1233
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
@@ -1278,6 +1287,18 @@ EOT
|
|
|
1278
1287
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1279
1288
|
opts.banner = subcommand_usage( "[cloud] [name] [options]")
|
|
1280
1289
|
build_option_type_options(opts, options, add_cloud_affinity_group_option_types)
|
|
1290
|
+
opts.on('--vm-group ID', String, "VM Group id (for VM-to-Host rules)") do |val|
|
|
1291
|
+
options[:options] ||= {}
|
|
1292
|
+
options[:options]['vmGroup'] = {'id' => val.to_i}
|
|
1293
|
+
end
|
|
1294
|
+
opts.on('--host-group ID', String, "Host Group id (for VM-to-Host rules)") do |val|
|
|
1295
|
+
options[:options] ||= {}
|
|
1296
|
+
options[:options]['hostGroup'] = {'id' => val.to_i}
|
|
1297
|
+
end
|
|
1298
|
+
opts.on('--servers ID1,ID2', Array, "Server ids (for VM-to-VM rules)") do |val|
|
|
1299
|
+
options[:options] ||= {}
|
|
1300
|
+
options[:options]['servers'] = val.map {|s| {'id' => s.to_i}}
|
|
1301
|
+
end
|
|
1281
1302
|
add_perms_options(opts, options, ['plans'])
|
|
1282
1303
|
build_standard_add_options(opts, options)
|
|
1283
1304
|
opts.footer = "Add affinity group to a cloud.\n" +
|
|
@@ -1308,19 +1329,74 @@ EOT
|
|
|
1308
1329
|
option_types = add_cloud_affinity_group_option_types
|
|
1309
1330
|
affinity_group = Morpheus::Cli::OptionTypes.prompt(option_types, options[:options], @api_client, options[:params])
|
|
1310
1331
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1332
|
+
preset_servers = options[:options] && options[:options].key?('servers')
|
|
1333
|
+
preset_vmhost = options[:options] && options[:options].key?('vmGroup') && options[:options].key?('hostGroup')
|
|
1334
|
+
|
|
1335
|
+
form_opts = @clouds_interface.affinity_group_form_options(cloud['id']) rescue {}
|
|
1336
|
+
# Capability gate: AffinityGroupsController#formOptions derives
|
|
1337
|
+
# supportsCombinedRules from zoneType.hasHostVmGroups. Use the flag
|
|
1338
|
+
# itself -- the presence of groups is not the same as support for them.
|
|
1339
|
+
supports_combined = form_opts['supportsCombinedRules'] == true
|
|
1340
|
+
|
|
1341
|
+
# Cluster-in-cloud: the 'pool.id' option type above already prompts for
|
|
1342
|
+
# the cluster. Re-query form-options narrowed by that pool so the group
|
|
1343
|
+
# pickers only offer groups from the cluster the rule will belong to.
|
|
1344
|
+
pool_id = affinity_group['pool'].is_a?(Hash) ? affinity_group['pool']['id'] : nil
|
|
1345
|
+
if pool_id && supports_combined
|
|
1346
|
+
form_opts = (@clouds_interface.affinity_group_form_options(cloud['id'], {'poolId' => pool_id}) rescue form_opts)
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1349
|
+
available_vm_groups = filter_by_pool(form_opts['availableVmGroups'] || [], pool_id)
|
|
1350
|
+
available_host_groups = filter_by_pool(form_opts['availableHostGroups'] || [], pool_id)
|
|
1313
1351
|
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1352
|
+
if !supports_combined && preset_vmhost
|
|
1353
|
+
print yellow, "This cloud does not support VM-to-Host affinity rules.", reset, "\n"
|
|
1354
|
+
end
|
|
1355
|
+
|
|
1356
|
+
unless preset_servers || preset_vmhost
|
|
1357
|
+
if supports_combined && !available_vm_groups.empty? && !available_host_groups.empty?
|
|
1358
|
+
shape = Morpheus::Cli::OptionTypes.prompt([{
|
|
1359
|
+
'fieldName' => 'shape', 'fieldLabel' => 'Rule Shape', 'type' => 'select',
|
|
1360
|
+
'required' => true, 'defaultValue' => 'vmToVm',
|
|
1361
|
+
'selectOptions' => [
|
|
1362
|
+
{'name' => 'VM-to-VM (pick servers)', 'value' => 'vmToVm'},
|
|
1363
|
+
{'name' => 'VM-to-Host (pick groups)', 'value' => 'vmToHost'},
|
|
1364
|
+
]
|
|
1365
|
+
}], options[:options], @api_client, options[:params])['shape']
|
|
1366
|
+
else
|
|
1367
|
+
shape = 'vmToVm'
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1370
|
+
if shape == 'vmToHost'
|
|
1371
|
+
vm_group_id = Morpheus::Cli::OptionTypes.prompt([{
|
|
1372
|
+
'fieldName' => 'vmGroup', 'fieldLabel' => 'VM Group', 'type' => 'select', 'required' => true,
|
|
1373
|
+
'selectOptions' => available_vm_groups.map {|g| {'name' => g['name'], 'value' => g['id']} }
|
|
1374
|
+
}], options[:options], @api_client, options[:params])['vmGroup']
|
|
1375
|
+
host_group_id = Morpheus::Cli::OptionTypes.prompt([{
|
|
1376
|
+
'fieldName' => 'hostGroup', 'fieldLabel' => 'Host Group', 'type' => 'select', 'required' => true,
|
|
1377
|
+
'selectOptions' => available_host_groups.map {|g| {'name' => g['name'], 'value' => g['id']} }
|
|
1378
|
+
}], options[:options], @api_client, options[:params])['hostGroup']
|
|
1379
|
+
affinity_group['vmGroup'] = {'id' => vm_group_id.to_i}
|
|
1380
|
+
affinity_group['hostGroup'] = {'id' => host_group_id.to_i}
|
|
1381
|
+
else
|
|
1382
|
+
server_prompt = Morpheus::Cli::OptionTypes.prompt([{
|
|
1383
|
+
'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead',
|
|
1384
|
+
'optionSource' => 'searchServers', 'searchParameter' => 'phrase',
|
|
1385
|
+
'description' => 'Select servers to be in the affinity group.'
|
|
1386
|
+
}], options[:options], @api_client, options[:params])
|
|
1387
|
+
affinity_group['servers'] = server_prompt['servers'] if server_prompt['servers']
|
|
1388
|
+
end
|
|
1389
|
+
else
|
|
1390
|
+
affinity_group['servers'] = options[:options]['servers'] if preset_servers
|
|
1391
|
+
affinity_group['vmGroup'] = options[:options]['vmGroup'] if preset_vmhost
|
|
1392
|
+
affinity_group['hostGroup'] = options[:options]['hostGroup'] if preset_vmhost
|
|
1393
|
+
end
|
|
1318
1394
|
|
|
1319
1395
|
# perms
|
|
1320
1396
|
perms = prompt_permissions(options, is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
1321
1397
|
|
|
1322
|
-
affinity_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].
|
|
1323
|
-
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].
|
|
1398
|
+
affinity_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].nil?
|
|
1399
|
+
affinity_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].nil? || perms['tenantPermissions']['accounts'].empty?
|
|
1324
1400
|
affinity_group['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
1325
1401
|
|
|
1326
1402
|
payload = {'affinityGroup' => affinity_group}
|
|
@@ -1351,7 +1427,7 @@ EOT
|
|
|
1351
1427
|
end
|
|
1352
1428
|
return 0
|
|
1353
1429
|
rescue RestClient::Exception => e
|
|
1354
|
-
|
|
1430
|
+
handle_affinity_rest_exception(e, options)
|
|
1355
1431
|
exit 1
|
|
1356
1432
|
end
|
|
1357
1433
|
end
|
|
@@ -1502,6 +1578,295 @@ EOT
|
|
|
1502
1578
|
return 0, nil
|
|
1503
1579
|
end
|
|
1504
1580
|
|
|
1581
|
+
def list_host_vm_groups(args)
|
|
1582
|
+
options = {}
|
|
1583
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1584
|
+
opts.banner = subcommand_usage("[cloud]")
|
|
1585
|
+
build_standard_list_options(opts, options)
|
|
1586
|
+
opts.footer = "List host/VM groups for a cloud.\n" +
|
|
1587
|
+
"[cloud] is required. This is the name or id of an existing cloud."
|
|
1588
|
+
end
|
|
1589
|
+
optparse.parse!(args)
|
|
1590
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
1591
|
+
connect(options)
|
|
1592
|
+
|
|
1593
|
+
cloud = find_cloud_by_name_or_id(args[0])
|
|
1594
|
+
return 1 if cloud.nil?
|
|
1595
|
+
params = {}
|
|
1596
|
+
params.merge!(parse_list_options(options))
|
|
1597
|
+
@clouds_interface.setopts(options)
|
|
1598
|
+
if options[:dry_run]
|
|
1599
|
+
print_dry_run @clouds_interface.dry.list_host_vm_groups(cloud['id'], params)
|
|
1600
|
+
return
|
|
1601
|
+
end
|
|
1602
|
+
json_response = @clouds_interface.list_host_vm_groups(cloud['id'], params)
|
|
1603
|
+
render_response(json_response, options, 'hostVmGroups') do
|
|
1604
|
+
rows = json_response['hostVmGroups'] || []
|
|
1605
|
+
print_h1 "Cloud Host/VM Groups: \#{cloud['name']}", parse_list_subtitles(options), options
|
|
1606
|
+
if rows.empty?
|
|
1607
|
+
print cyan, "No host/VM groups found.", reset, "\n"
|
|
1608
|
+
else
|
|
1609
|
+
columns = {
|
|
1610
|
+
"ID" => 'id',
|
|
1611
|
+
"Name" => 'name',
|
|
1612
|
+
"Type" => lambda {|it| format_host_vm_group_type(it['type']) },
|
|
1613
|
+
"Resource Pool" => lambda {|it| it['pool'] ? (it['pool']['name'] || it['pool']['id']) : '' },
|
|
1614
|
+
"Servers" => lambda {|it| (it['servers'] || []).size },
|
|
1615
|
+
}.upcase_keys!
|
|
1616
|
+
print as_pretty_table(rows, columns, options)
|
|
1617
|
+
print_results_pagination(json_response)
|
|
1618
|
+
end
|
|
1619
|
+
print reset, "\n"
|
|
1620
|
+
end
|
|
1621
|
+
return 0, nil
|
|
1622
|
+
end
|
|
1623
|
+
|
|
1624
|
+
def get_host_vm_group(args)
|
|
1625
|
+
options = {}
|
|
1626
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1627
|
+
opts.banner = subcommand_usage("[cloud] [host-vm-group]")
|
|
1628
|
+
build_standard_get_options(opts, options)
|
|
1629
|
+
opts.footer = "Get details about a cloud host/VM group.\n" +
|
|
1630
|
+
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
1631
|
+
"[host-vm-group] is required. This is the name or id of an existing host/VM group."
|
|
1632
|
+
end
|
|
1633
|
+
optparse.parse!(args)
|
|
1634
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
|
1635
|
+
connect(options)
|
|
1636
|
+
|
|
1637
|
+
cloud = find_cloud_by_name_or_id(args[0])
|
|
1638
|
+
return 1 if cloud.nil?
|
|
1639
|
+
host_vm_group = find_cloud_host_vm_group_by_name_or_id(cloud['id'], args[1])
|
|
1640
|
+
if host_vm_group.nil?
|
|
1641
|
+
print_red_alert "Host/VM Group not found for '\#{args[1]}'"
|
|
1642
|
+
exit 1
|
|
1643
|
+
end
|
|
1644
|
+
|
|
1645
|
+
params = {}
|
|
1646
|
+
params.merge!(parse_query_options(options))
|
|
1647
|
+
@clouds_interface.setopts(options)
|
|
1648
|
+
if options[:dry_run]
|
|
1649
|
+
print_dry_run @clouds_interface.dry.get_host_vm_group(cloud['id'], host_vm_group['id'], params)
|
|
1650
|
+
return
|
|
1651
|
+
end
|
|
1652
|
+
json_response = @clouds_interface.get_host_vm_group(cloud['id'], host_vm_group['id'], params)
|
|
1653
|
+
render_response(json_response, options, 'hostVmGroup') do
|
|
1654
|
+
row = json_response['hostVmGroup']
|
|
1655
|
+
print_h1 "Host/VM Group Details", [], options
|
|
1656
|
+
columns = {
|
|
1657
|
+
"ID" => 'id',
|
|
1658
|
+
"Name" => 'name',
|
|
1659
|
+
"Type" => lambda {|it| format_host_vm_group_type(it['type']) },
|
|
1660
|
+
"Resource Pool" => lambda {|it| it['pool'] ? (it['pool']['name'] || it['pool']['id']) : '' },
|
|
1661
|
+
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
|
1662
|
+
"Servers" => lambda {|it| (it['servers'] || []).size },
|
|
1663
|
+
"Source" => 'source',
|
|
1664
|
+
}
|
|
1665
|
+
print_description_list(columns, row)
|
|
1666
|
+
if row['servers'] && row['servers'].size > 0
|
|
1667
|
+
print_h2 "Servers", options
|
|
1668
|
+
print as_pretty_table(row['servers'], [:id, :name], options)
|
|
1669
|
+
end
|
|
1670
|
+
print reset, "\n"
|
|
1671
|
+
end
|
|
1672
|
+
return 0, nil
|
|
1673
|
+
end
|
|
1674
|
+
|
|
1675
|
+
def add_host_vm_group(args)
|
|
1676
|
+
options = {}
|
|
1677
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1678
|
+
opts.banner = subcommand_usage("[cloud] [name] [options]")
|
|
1679
|
+
build_option_type_options(opts, options, add_cloud_host_vm_group_option_types)
|
|
1680
|
+
opts.on('--servers ID1,ID2', Array, "Server ids to add to the group") do |val|
|
|
1681
|
+
options[:options] ||= {}
|
|
1682
|
+
options[:options]['servers'] = val.map {|s| {'id' => s.to_i}}
|
|
1683
|
+
end
|
|
1684
|
+
add_perms_options(opts, options, ['plans'])
|
|
1685
|
+
build_standard_add_options(opts, options)
|
|
1686
|
+
opts.footer = "Add host/VM group to a cloud.\n" +
|
|
1687
|
+
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
1688
|
+
"[name] is required. This is the name of the new host/VM group."
|
|
1689
|
+
end
|
|
1690
|
+
optparse.parse!(args)
|
|
1691
|
+
verify_args!(args:args, optparse:optparse, min:1, max:2)
|
|
1692
|
+
connect(options)
|
|
1693
|
+
|
|
1694
|
+
begin
|
|
1695
|
+
cloud = find_cloud_by_name_or_id(args[0])
|
|
1696
|
+
return 1 if cloud.nil?
|
|
1697
|
+
if args[1]
|
|
1698
|
+
options[:options] ||= {}
|
|
1699
|
+
options[:options]['name'] = args[1]
|
|
1700
|
+
end
|
|
1701
|
+
if options[:payload]
|
|
1702
|
+
payload = options[:payload]
|
|
1703
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
|
1704
|
+
else
|
|
1705
|
+
options[:params] ||= {}
|
|
1706
|
+
options[:params].merge!({:cloudId => cloud['id'], :zoneId => cloud['id']})
|
|
1707
|
+
host_vm_group = Morpheus::Cli::OptionTypes.prompt(add_cloud_host_vm_group_option_types, options[:options], @api_client, options[:params])
|
|
1708
|
+
|
|
1709
|
+
unless options[:options] && options[:options].key?('servers')
|
|
1710
|
+
# poolId narrows availableServers to the chosen cluster: HOST_GROUP
|
|
1711
|
+
# matches the cluster pool exactly, VM_GROUP walks descendant pools.
|
|
1712
|
+
form_params = {'hostVmGroupType' => host_vm_group['type']}
|
|
1713
|
+
hvg_pool_id = host_vm_group['pool'].is_a?(Hash) ? host_vm_group['pool']['id'] : nil
|
|
1714
|
+
form_params['poolId'] = hvg_pool_id if hvg_pool_id
|
|
1715
|
+
form_opts = @clouds_interface.host_vm_group_form_options(cloud['id'], form_params) rescue {}
|
|
1716
|
+
available = form_opts['availableServers'] || []
|
|
1717
|
+
if available.empty?
|
|
1718
|
+
server_prompt = Morpheus::Cli::OptionTypes.prompt([{
|
|
1719
|
+
'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead',
|
|
1720
|
+
'optionSource' => 'searchServers', 'searchParameter' => 'phrase',
|
|
1721
|
+
'description' => 'Select servers to add to the group.'
|
|
1722
|
+
}], options[:options], @api_client, options[:params])
|
|
1723
|
+
host_vm_group['servers'] = server_prompt['servers'] if server_prompt['servers']
|
|
1724
|
+
else
|
|
1725
|
+
print cyan, "Available Servers:", reset, "\n"
|
|
1726
|
+
available.each {|s| print " \#{s['id']}\t\#{s['name']}\n" }
|
|
1727
|
+
raw = Morpheus::Cli::OptionTypes.prompt([{
|
|
1728
|
+
'fieldName' => 'servers', 'fieldLabel' => 'Servers (comma-separated IDs)', 'type' => 'text',
|
|
1729
|
+
'description' => 'Server IDs to include, comma-separated'
|
|
1730
|
+
}], options[:options], @api_client, options[:params])['servers']
|
|
1731
|
+
selected_ids = raw.to_s.split(',').map(&:strip).reject(&:empty?).map(&:to_i)
|
|
1732
|
+
host_vm_group['servers'] = selected_ids.map {|id| {'id' => id}}
|
|
1733
|
+
end
|
|
1734
|
+
else
|
|
1735
|
+
host_vm_group['servers'] = options[:options]['servers']
|
|
1736
|
+
end
|
|
1737
|
+
|
|
1738
|
+
perms = prompt_permissions(options, is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
1739
|
+
host_vm_group['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].nil?
|
|
1740
|
+
host_vm_group['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].nil? || perms['tenantPermissions']['accounts'].empty?
|
|
1741
|
+
host_vm_group['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
1742
|
+
|
|
1743
|
+
payload = {'hostVmGroup' => host_vm_group}
|
|
1744
|
+
end
|
|
1745
|
+
|
|
1746
|
+
@clouds_interface.setopts(options)
|
|
1747
|
+
if options[:dry_run]
|
|
1748
|
+
print_dry_run @clouds_interface.dry.create_host_vm_group(cloud['id'], payload)
|
|
1749
|
+
return
|
|
1750
|
+
end
|
|
1751
|
+
json_response = @clouds_interface.create_host_vm_group(cloud['id'], payload)
|
|
1752
|
+
render_response(json_response, options, 'hostVmGroup') do
|
|
1753
|
+
row = json_response['hostVmGroup']
|
|
1754
|
+
print_green_success "Added host/VM group to cloud \#{cloud['name']}"
|
|
1755
|
+
end
|
|
1756
|
+
return 0, nil
|
|
1757
|
+
rescue RestClient::Exception => e
|
|
1758
|
+
print_rest_exception(e, options)
|
|
1759
|
+
exit 1
|
|
1760
|
+
end
|
|
1761
|
+
end
|
|
1762
|
+
|
|
1763
|
+
def update_host_vm_group(args)
|
|
1764
|
+
options = {}
|
|
1765
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1766
|
+
opts.banner = subcommand_usage("[cloud] [host-vm-group] [options]")
|
|
1767
|
+
build_option_type_options(opts, options, update_cloud_host_vm_group_option_types)
|
|
1768
|
+
opts.on('--servers ID1,ID2', Array, "Server ids") do |val|
|
|
1769
|
+
options[:options] ||= {}
|
|
1770
|
+
options[:options]['servers'] = val.map {|s| {'id' => s.to_i}}
|
|
1771
|
+
end
|
|
1772
|
+
add_perms_options(opts, options, ['plans'])
|
|
1773
|
+
build_standard_update_options(opts, options)
|
|
1774
|
+
opts.footer = "Update a cloud host/VM group.\n" +
|
|
1775
|
+
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
1776
|
+
"[host-vm-group] is required. This is the name or id of an existing host/VM group."
|
|
1777
|
+
end
|
|
1778
|
+
optparse.parse!(args)
|
|
1779
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
|
1780
|
+
connect(options)
|
|
1781
|
+
|
|
1782
|
+
begin
|
|
1783
|
+
cloud = find_cloud_by_name_or_id(args[0])
|
|
1784
|
+
return 1 if cloud.nil?
|
|
1785
|
+
host_vm_group = find_cloud_host_vm_group_by_name_or_id(cloud['id'], args[1])
|
|
1786
|
+
if host_vm_group.nil?
|
|
1787
|
+
print_red_alert "Host/VM Group not found for '\#{args[1]}'"
|
|
1788
|
+
return 1
|
|
1789
|
+
end
|
|
1790
|
+
|
|
1791
|
+
if options[:payload]
|
|
1792
|
+
payload = options[:payload]
|
|
1793
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
|
1794
|
+
else
|
|
1795
|
+
payload = {'hostVmGroup' => {}}
|
|
1796
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_cloud_host_vm_group_option_types, options[:options], @api_client, {})
|
|
1797
|
+
payload.deep_merge!({'hostVmGroup' => v_prompt})
|
|
1798
|
+
|
|
1799
|
+
perms = prompt_permissions(options, is_master_account ? ['plans'] : ['plans', 'visibility', 'tenants'])
|
|
1800
|
+
payload['hostVmGroup']['permissions'] = perms['resourcePermissions'] if perms['resourcePermissions']
|
|
1801
|
+
payload['hostVmGroup']['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
|
1802
|
+
|
|
1803
|
+
if options[:options]
|
|
1804
|
+
payload.deep_merge!({'hostVmGroup' => options[:options].reject {|k,v| k.is_a?(Symbol) || payload['hostVmGroup'].key?(k) }})
|
|
1805
|
+
end
|
|
1806
|
+
if payload['hostVmGroup'].empty?
|
|
1807
|
+
raise_command_error "Specify at least one option to update.\n\#{optparse}"
|
|
1808
|
+
end
|
|
1809
|
+
end
|
|
1810
|
+
|
|
1811
|
+
@clouds_interface.setopts(options)
|
|
1812
|
+
if options[:dry_run]
|
|
1813
|
+
print_dry_run @clouds_interface.dry.update_host_vm_group(cloud['id'], host_vm_group['id'], payload)
|
|
1814
|
+
return
|
|
1815
|
+
end
|
|
1816
|
+
json_response = @clouds_interface.update_host_vm_group(cloud['id'], host_vm_group['id'], payload)
|
|
1817
|
+
render_response(json_response, options, 'hostVmGroup') do
|
|
1818
|
+
updated = json_response['hostVmGroup'] || host_vm_group
|
|
1819
|
+
print_green_success "Updated host/VM group \#{updated['name']}"
|
|
1820
|
+
end
|
|
1821
|
+
return 0, nil
|
|
1822
|
+
rescue RestClient::Exception => e
|
|
1823
|
+
print_rest_exception(e, options)
|
|
1824
|
+
exit 1
|
|
1825
|
+
end
|
|
1826
|
+
end
|
|
1827
|
+
|
|
1828
|
+
def remove_host_vm_group(args)
|
|
1829
|
+
options = {}
|
|
1830
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
1831
|
+
opts.banner = subcommand_usage("[cloud] [host-vm-group]")
|
|
1832
|
+
build_standard_remove_options(opts, options)
|
|
1833
|
+
opts.footer = "Delete a host/VM group from a cloud.\n" +
|
|
1834
|
+
"[cloud] is required. This is the name or id of an existing cloud.\n" +
|
|
1835
|
+
"[host-vm-group] is required. This is the name or id of an existing host/VM group."
|
|
1836
|
+
end
|
|
1837
|
+
optparse.parse!(args)
|
|
1838
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
|
1839
|
+
connect(options)
|
|
1840
|
+
|
|
1841
|
+
cloud = find_cloud_by_name_or_id(args[0])
|
|
1842
|
+
return 1 if cloud.nil?
|
|
1843
|
+
host_vm_group = find_cloud_host_vm_group_by_name_or_id(cloud['id'], args[1])
|
|
1844
|
+
if host_vm_group.nil?
|
|
1845
|
+
print_red_alert "Host/VM Group not found for '\#{args[1]}'"
|
|
1846
|
+
return 1
|
|
1847
|
+
end
|
|
1848
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes.confirm("Are you sure you would like to remove the cloud host/VM group '\#{host_vm_group['name'] || host_vm_group['id']}'?", options)
|
|
1849
|
+
return 9, "aborted command"
|
|
1850
|
+
end
|
|
1851
|
+
|
|
1852
|
+
@clouds_interface.setopts(options)
|
|
1853
|
+
if options[:dry_run]
|
|
1854
|
+
print_dry_run @clouds_interface.dry.destroy_host_vm_group(cloud['id'], host_vm_group['id'])
|
|
1855
|
+
return
|
|
1856
|
+
end
|
|
1857
|
+
begin
|
|
1858
|
+
json_response = @clouds_interface.destroy_host_vm_group(cloud['id'], host_vm_group['id'])
|
|
1859
|
+
render_response(json_response, options) do
|
|
1860
|
+
print_green_success "Removed host/VM group \#{host_vm_group['name']}"
|
|
1861
|
+
end
|
|
1862
|
+
return 0, nil
|
|
1863
|
+
rescue RestClient::Exception => e
|
|
1864
|
+
print_rest_exception(e, options)
|
|
1865
|
+
exit 1
|
|
1866
|
+
end
|
|
1867
|
+
end
|
|
1868
|
+
|
|
1869
|
+
|
|
1505
1870
|
private
|
|
1506
1871
|
|
|
1507
1872
|
def cloud_list_column_definitions(options)
|
|
@@ -1624,22 +1989,49 @@ EOT
|
|
|
1624
1989
|
def add_cloud_affinity_group_option_types
|
|
1625
1990
|
[
|
|
1626
1991
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
|
1627
|
-
|
|
1992
|
+
affinity_type_option_type(required: true, default: 'KEEP_SEPARATE'),
|
|
1628
1993
|
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'defaultValue' => true},
|
|
1629
|
-
{'fieldName' => 'pool.id', 'fieldLabel' => 'Cluster', 'type' => 'select', 'optionSourceType' => 'vmware',
|
|
1630
|
-
|
|
1994
|
+
{'fieldName' => 'pool.id', 'fieldLabel' => 'Cluster', 'type' => 'select', 'optionSourceType' => 'vmware',
|
|
1995
|
+
'optionSource' => 'vmwareZonePoolClusters', 'description' => 'Select cluster for the affinity group.', 'required' => true},
|
|
1996
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers',
|
|
1997
|
+
'searchParameter' => 'phrase', 'description' => 'Select servers to be in the affinity group.'},
|
|
1631
1998
|
]
|
|
1632
1999
|
end
|
|
1633
2000
|
|
|
1634
2001
|
def update_cloud_affinity_group_option_types
|
|
1635
2002
|
[
|
|
2003
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text'},
|
|
2004
|
+
affinity_type_option_type,
|
|
1636
2005
|
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox'},
|
|
1637
|
-
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers',
|
|
2006
|
+
{'fieldName' => 'servers', 'fieldLabel' => 'Server', 'type' => 'multiTypeahead', 'optionSource' => 'searchServers',
|
|
2007
|
+
'searchParameter' => 'phrase', 'description' => 'Select servers to be in the affinity group.'},
|
|
1638
2008
|
]
|
|
1639
2009
|
end
|
|
1640
2010
|
|
|
1641
|
-
def
|
|
1642
|
-
|
|
2011
|
+
def find_cloud_host_vm_group_by_name_or_id(cloud_id, val)
|
|
2012
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
2013
|
+
@clouds_interface.get_host_vm_group(cloud_id, val)['hostVmGroup'] rescue nil
|
|
2014
|
+
else
|
|
2015
|
+
@clouds_interface.list_host_vm_groups(cloud_id, {name: val})['hostVmGroups'] && @clouds_interface.list_host_vm_groups(cloud_id, {name: val})['hostVmGroups'][0]
|
|
2016
|
+
end
|
|
2017
|
+
end
|
|
2018
|
+
|
|
2019
|
+
def add_cloud_host_vm_group_option_types
|
|
2020
|
+
[
|
|
2021
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
|
2022
|
+
host_vm_group_type_option_type(required: true, default: 'HOST_GROUP'),
|
|
2023
|
+
# A cloud-scoped host/VM group must belong to a single cluster --
|
|
2024
|
+
# HostVmGroupsController#save rejects servers that span clusters. Same
|
|
2025
|
+
# picker the cloud-scoped affinity group form uses.
|
|
2026
|
+
{'fieldName' => 'pool.id', 'fieldLabel' => 'Cluster', 'type' => 'select', 'optionSourceType' => 'vmware',
|
|
2027
|
+
'optionSource' => 'vmwareZonePoolClusters', 'description' => 'Select cluster for the host/VM group.', 'required' => true},
|
|
2028
|
+
]
|
|
2029
|
+
end
|
|
2030
|
+
|
|
2031
|
+
def update_cloud_host_vm_group_option_types
|
|
2032
|
+
[
|
|
2033
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text'},
|
|
2034
|
+
]
|
|
1643
2035
|
end
|
|
1644
|
-
|
|
2036
|
+
|
|
1645
2037
|
end
|