morpheus-cli 4.2.21 → 5.2.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/api_client.rb +30 -0
- data/lib/morpheus/api/billing_interface.rb +34 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
- data/lib/morpheus/api/deploy_interface.rb +1 -1
- data/lib/morpheus/api/deployments_interface.rb +20 -1
- data/lib/morpheus/api/forgot_password_interface.rb +17 -0
- data/lib/morpheus/api/instances_interface.rb +16 -2
- data/lib/morpheus/api/rest_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +14 -0
- data/lib/morpheus/api/service_catalog_interface.rb +89 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +7 -3
- data/lib/morpheus/cli/apps.rb +6 -27
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/catalog_item_types_command.rb +622 -0
- data/lib/morpheus/cli/cli_command.rb +70 -21
- data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
- data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
- data/lib/morpheus/cli/containers_command.rb +14 -24
- data/lib/morpheus/cli/cypher_command.rb +6 -2
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +341 -28
- data/lib/morpheus/cli/deploys.rb +206 -41
- data/lib/morpheus/cli/error_handler.rb +7 -0
- data/lib/morpheus/cli/forgot_password.rb +133 -0
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/health_command.rb +59 -2
- data/lib/morpheus/cli/hosts.rb +265 -34
- data/lib/morpheus/cli/instances.rb +186 -100
- data/lib/morpheus/cli/invoices_command.rb +33 -16
- data/lib/morpheus/cli/jobs_command.rb +28 -6
- data/lib/morpheus/cli/library_option_lists_command.rb +15 -7
- data/lib/morpheus/cli/library_option_types_command.rb +5 -2
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +12 -7
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +100 -4
- data/lib/morpheus/cli/network_pools_command.rb +14 -6
- data/lib/morpheus/cli/option_types.rb +271 -22
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/remote.rb +35 -12
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +453 -113
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/storage_providers_command.rb +40 -56
- data/lib/morpheus/cli/tasks.rb +29 -32
- data/lib/morpheus/cli/usage_command.rb +203 -0
- data/lib/morpheus/cli/user_settings_command.rb +1 -0
- data/lib/morpheus/cli/users.rb +12 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +429 -254
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +34 -41
- data/lib/morpheus/formatters.rb +75 -7
- data/lib/morpheus/terminal.rb +6 -2
- metadata +14 -2
data/lib/morpheus/cli/groups.rb
CHANGED
@@ -52,7 +52,7 @@ class Morpheus::Cli::Groups
|
|
52
52
|
end
|
53
53
|
json_response = @groups_interface.list(params)
|
54
54
|
exit_code, err = 0, nil
|
55
|
-
render_response(json_response, options) do
|
55
|
+
render_response(json_response, options, "groups") do
|
56
56
|
groups = json_response['groups']
|
57
57
|
subtitles = []
|
58
58
|
subtitles += parse_list_subtitles(options)
|
@@ -30,6 +30,7 @@ class Morpheus::Cli::HealthCommand
|
|
30
30
|
opts.on('-a', '--all', "Display all details: CPU, Memory, Database, etc." ) do
|
31
31
|
options[:details] = true
|
32
32
|
options[:show_cpu] = true
|
33
|
+
options[:show_threads] = true
|
33
34
|
options[:show_memory] = true
|
34
35
|
options[:show_database] = true
|
35
36
|
options[:show_elastic] = true
|
@@ -47,6 +48,9 @@ class Morpheus::Cli::HealthCommand
|
|
47
48
|
opts.on('--cpu', "Display CPU details" ) do
|
48
49
|
options[:show_cpu] = true
|
49
50
|
end
|
51
|
+
opts.on('--threads', "Display Thread details" ) do
|
52
|
+
options[:show_threads] = true
|
53
|
+
end
|
50
54
|
opts.on('--memory', "Display Memory details" ) do
|
51
55
|
options[:show_memory] = true
|
52
56
|
end
|
@@ -184,6 +188,59 @@ class Morpheus::Cli::HealthCommand
|
|
184
188
|
end
|
185
189
|
end
|
186
190
|
|
191
|
+
# Threads ()
|
192
|
+
if options[:show_threads]
|
193
|
+
print_h2 "Threads", options
|
194
|
+
if health['threads'].nil?
|
195
|
+
print yellow,"No thread information returned.",reset,"\n\n"
|
196
|
+
else
|
197
|
+
print cyan
|
198
|
+
|
199
|
+
thread_summary_columns = {
|
200
|
+
"Thread Count" => lambda {|it| it['totalThreads'].size rescue '' },
|
201
|
+
"Busy Threads" => lambda {|it| it['busyThreads'].size rescue '' },
|
202
|
+
"Running Threads" => lambda {|it| it['runningThreads'].size rescue '' },
|
203
|
+
"Blocked Threads" => lambda {|it| it['blockedThreads'].size rescue '' },
|
204
|
+
}
|
205
|
+
print_description_list(thread_summary_columns, health['threads'], options)
|
206
|
+
|
207
|
+
|
208
|
+
thread_columns = [
|
209
|
+
{"Name".upcase => lambda {|it| it['name']} },
|
210
|
+
{"Status".upcase => lambda {|it|
|
211
|
+
# hrmm
|
212
|
+
status_string = (it['status'] || it['state']).to_s.downcase
|
213
|
+
status_color = cyan
|
214
|
+
# if status_string.include?('waiting')
|
215
|
+
# status_color = yellow
|
216
|
+
# end
|
217
|
+
"#{status_color}#{status_string.upcase}#{cyan}"
|
218
|
+
} },
|
219
|
+
# {"CPU Time" => lambda {|it| it['cpuTime'].to_s } },
|
220
|
+
# {"CPU Time" => lambda {|it| format_human_duration(it['cpuTime'].to_f / 1000) rescue '' } },
|
221
|
+
{"CPU Percent" => lambda {|it| it['cpuPercent'].to_i.to_s + '%' } }
|
222
|
+
]
|
223
|
+
|
224
|
+
if health['threads']['busyThreads'] && health['threads']['busyThreads'].size > 0
|
225
|
+
print_h2 "Busy Threads"
|
226
|
+
print cyan
|
227
|
+
print as_pretty_table(health['threads']['busyThreads'], thread_columns, options)
|
228
|
+
end
|
229
|
+
|
230
|
+
if health['threads']['runningThreads'] && health['threads']['runningThreads'].size > 0
|
231
|
+
print_h2 "Running Threads"
|
232
|
+
print cyan
|
233
|
+
print as_pretty_table(health['threads']['runningThreads'], thread_columns, options)
|
234
|
+
end
|
235
|
+
|
236
|
+
if health['threads']['blockedThreads'] && health['threads']['blockedThreads'].size > 0
|
237
|
+
print_h2 "Blocked Threads"
|
238
|
+
print cyan
|
239
|
+
print as_pretty_table(health['threads']['blockedThreads'], thread_columns, options)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
187
244
|
# Memory
|
188
245
|
if options[:show_memory]
|
189
246
|
if health['memory'].nil?
|
@@ -475,8 +532,8 @@ class Morpheus::Cli::HealthCommand
|
|
475
532
|
opts.footer = "List health logs. These are the logs of the morpheus appliance itself."
|
476
533
|
end
|
477
534
|
optparse.parse!(args)
|
478
|
-
if args.count
|
479
|
-
|
535
|
+
if args.count > 0
|
536
|
+
options[:phrase] = args.join(" ")
|
480
537
|
end
|
481
538
|
connect(options)
|
482
539
|
begin
|
data/lib/morpheus/cli/hosts.rb
CHANGED
@@ -16,10 +16,11 @@ class Morpheus::Cli::Hosts
|
|
16
16
|
include Morpheus::Cli::LogsHelper
|
17
17
|
set_command_name :hosts
|
18
18
|
set_command_description "View and manage hosts (servers)."
|
19
|
-
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize,
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize,
|
20
|
+
:run_workflow, :make_managed, :upgrade_agent, :snapshots, :software,
|
21
|
+
{:'types' => :list_types},
|
22
|
+
{:exec => :execution_request},
|
23
|
+
:wiki, :update_wiki
|
23
24
|
alias_subcommand :details, :get
|
24
25
|
set_default_subcommand :list
|
25
26
|
|
@@ -53,9 +54,6 @@ class Morpheus::Cli::Hosts
|
|
53
54
|
params = {}
|
54
55
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
55
56
|
opts.banner = subcommand_usage()
|
56
|
-
opts.on( '-a', '--account ACCOUNT', "Account Name or ID" ) do |val|
|
57
|
-
options[:account] = val
|
58
|
-
end
|
59
57
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
60
58
|
options[:group] = val
|
61
59
|
end
|
@@ -81,6 +79,17 @@ class Morpheus::Cli::Hosts
|
|
81
79
|
# params[:clusterId] = val
|
82
80
|
options[:cluster] = val
|
83
81
|
end
|
82
|
+
opts.on( '--plan NAME', String, "Filter by Plan name(s)" ) do |val|
|
83
|
+
# commas used in names a lot so use --plan one --plan two
|
84
|
+
params['plan'] ||= []
|
85
|
+
params['plan'] << val
|
86
|
+
end
|
87
|
+
opts.on( '--plan-id ID', String, "Filter by Plan id(s)" ) do |val|
|
88
|
+
params['planId'] = parse_id_list(val)
|
89
|
+
end
|
90
|
+
opts.on( '--plan-code CODE', String, "Filter by Plan code(s)" ) do |val|
|
91
|
+
params['planCode'] = parse_id_list(val)
|
92
|
+
end
|
84
93
|
opts.on( '', '--vm', "Show only virtual machines" ) do |val|
|
85
94
|
params[:vm] = true
|
86
95
|
end
|
@@ -105,8 +114,16 @@ class Morpheus::Cli::Hosts
|
|
105
114
|
opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
|
106
115
|
options[:created_by] = val
|
107
116
|
end
|
108
|
-
opts.on('--
|
109
|
-
options[:
|
117
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
118
|
+
options[:account] = val
|
119
|
+
end
|
120
|
+
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
121
|
+
val.split(",").each do |value_pair|
|
122
|
+
k,v = value_pair.strip.split("=")
|
123
|
+
options[:tags] ||= {}
|
124
|
+
options[:tags][k] ||= []
|
125
|
+
options[:tags][k] << (v || '')
|
126
|
+
end
|
110
127
|
end
|
111
128
|
opts.on('--tag-compliant', "Displays only servers that are valid according to applied tag policies. Does not show servers that do not have tag policies." ) do
|
112
129
|
params[:tagCompliant] = true
|
@@ -114,11 +131,21 @@ class Morpheus::Cli::Hosts
|
|
114
131
|
opts.on('--non-tag-compliant', "Displays only servers with tag compliance warnings." ) do
|
115
132
|
params[:tagCompliant] = false
|
116
133
|
end
|
117
|
-
|
134
|
+
opts.on('--stats', "Display values for memory and storage usage used / max values." ) do
|
135
|
+
options[:stats] = true
|
136
|
+
end
|
137
|
+
opts.on('-a', '--details', "Display all details: hostname, private ip, plan, stats, etc." ) do
|
138
|
+
options[:details] = true
|
139
|
+
end
|
140
|
+
build_standard_list_options(opts, options)
|
118
141
|
opts.footer = "List hosts."
|
119
142
|
end
|
120
143
|
optparse.parse!(args)
|
121
144
|
connect(options)
|
145
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
146
|
+
if args.count > 0
|
147
|
+
options[:phrase] = args.join(" ")
|
148
|
+
end
|
122
149
|
begin
|
123
150
|
params.merge!(parse_list_options(options))
|
124
151
|
account = nil
|
@@ -159,6 +186,11 @@ class Morpheus::Cli::Hosts
|
|
159
186
|
params['clusterId'] = cluster['id']
|
160
187
|
end
|
161
188
|
end
|
189
|
+
if options[:tags] && !options[:tags].empty?
|
190
|
+
options[:tags].each do |k,v|
|
191
|
+
params['tags.' + k] = v
|
192
|
+
end
|
193
|
+
end
|
162
194
|
|
163
195
|
@servers_interface.setopts(options)
|
164
196
|
if options[:dry_run]
|
@@ -190,6 +222,9 @@ class Morpheus::Cli::Hosts
|
|
190
222
|
multi_tenant = json_response['multiTenant'] == true
|
191
223
|
title = "Morpheus Hosts"
|
192
224
|
subtitles = []
|
225
|
+
if account
|
226
|
+
subtitles << "Tenant: #{account['name']}".strip
|
227
|
+
end
|
193
228
|
if group
|
194
229
|
subtitles << "Group: #{group['name']}".strip
|
195
230
|
end
|
@@ -230,7 +265,7 @@ class Morpheus::Cli::Hosts
|
|
230
265
|
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
231
266
|
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
232
267
|
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
233
|
-
if options[:details]
|
268
|
+
if options[:details] || options[:stats]
|
234
269
|
if stats['maxMemory'] && stats['maxMemory'].to_i != 0
|
235
270
|
memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
|
236
271
|
end
|
@@ -240,31 +275,76 @@ class Morpheus::Cli::Hosts
|
|
240
275
|
end
|
241
276
|
row = {
|
242
277
|
id: server['id'],
|
243
|
-
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
244
278
|
name: server['name'],
|
279
|
+
external_name: server['externalName'],
|
280
|
+
hostname: server['hostname'],
|
245
281
|
platform: server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A',
|
246
|
-
cloud: server['zone'] ? server['zone']['name'] : '',
|
247
282
|
type: server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged',
|
283
|
+
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
284
|
+
owner: server['owner'] ? server['owner']['username'] : server['owner'],
|
285
|
+
cloud: server['zone'] ? server['zone']['name'] : '',
|
286
|
+
plan: server['plan'] ? server['plan']['name'] : '',
|
287
|
+
ip: server['externalIp'],
|
288
|
+
internal_ip: server['internalIp'],
|
248
289
|
nodes: server['containers'] ? server['containers'].size : '',
|
249
|
-
status: format_server_status(server, cyan),
|
290
|
+
# status: format_server_status(server, cyan),
|
291
|
+
status: (options[:details]||options[:all_fields]) ? format_server_status(server, cyan) : format_server_status_friendly(server, cyan),
|
250
292
|
power: format_server_power_state(server, cyan),
|
251
293
|
cpu: cpu_usage_str + cyan,
|
252
294
|
memory: memory_usage_str + cyan,
|
253
|
-
storage: storage_usage_str + cyan
|
295
|
+
storage: storage_usage_str + cyan,
|
296
|
+
created: format_local_dt(server['dateCreated']),
|
297
|
+
updated: format_local_dt(server['lastUpdated']),
|
254
298
|
}
|
255
299
|
row
|
256
300
|
}
|
257
|
-
columns = [:id, :name, :type, :cloud, :nodes, :status, :power]
|
258
|
-
|
259
|
-
|
301
|
+
# columns = [:id, :name, :type, :cloud, :ip, :internal_ip, :nodes, :status, :power]
|
302
|
+
columns = {
|
303
|
+
"ID" => :id,
|
304
|
+
"Name" => :name,
|
305
|
+
"External Name" => :external_name,
|
306
|
+
"Hostname" => :hostname,
|
307
|
+
"Type" => :type,
|
308
|
+
"Owner" => :owner,
|
309
|
+
"Tenant" => :tenant,
|
310
|
+
"Cloud" => :cloud,
|
311
|
+
"Plan" => :plan,
|
312
|
+
"IP" => :ip,
|
313
|
+
"Private IP" => :internal_ip,
|
314
|
+
"Nodes" => :nodes,
|
315
|
+
"Status" => :status,
|
316
|
+
"Power" => :power,
|
317
|
+
"CPU" => :cpu,
|
318
|
+
"Memory" => :memory,
|
319
|
+
"Storage" => :storage,
|
320
|
+
"Created" => :created,
|
321
|
+
"Updated" => :updated,
|
322
|
+
}
|
323
|
+
if options[:details] != true
|
324
|
+
columns.delete("External Name")
|
325
|
+
columns.delete("Hostname")
|
326
|
+
columns.delete("Plan")
|
327
|
+
columns.delete("Private IP")
|
328
|
+
columns.delete("Owner")
|
329
|
+
columns.delete("Tenant")
|
330
|
+
columns.delete("Power")
|
331
|
+
columns.delete("Created")
|
332
|
+
columns.delete("Updated")
|
333
|
+
end
|
334
|
+
# hide External Name if there are none
|
335
|
+
if !servers.find {|it| it['externalName'] && it['externalName'] != it['name']}
|
336
|
+
columns.delete("External Name")
|
260
337
|
end
|
261
|
-
|
262
|
-
|
263
|
-
if options[:include_fields]
|
264
|
-
columns = options[:include_fields]
|
338
|
+
if !multi_tenant
|
339
|
+
columns.delete("Tenant")
|
265
340
|
end
|
341
|
+
# columns += [:cpu, :memory, :storage]
|
342
|
+
# # custom pretty table columns ...
|
343
|
+
# if options[:include_fields]
|
344
|
+
# columns = options[:include_fields]
|
345
|
+
# end
|
266
346
|
print cyan
|
267
|
-
print as_pretty_table(rows, columns
|
347
|
+
print as_pretty_table(rows, columns.upcase_keys!, options)
|
268
348
|
print reset
|
269
349
|
print_results_pagination(json_response)
|
270
350
|
end
|
@@ -281,7 +361,7 @@ class Morpheus::Cli::Hosts
|
|
281
361
|
options = {}
|
282
362
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
283
363
|
opts.banner = subcommand_usage("[options]")
|
284
|
-
opts.on( '
|
364
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
285
365
|
options[:account] = val
|
286
366
|
end
|
287
367
|
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
@@ -392,6 +472,9 @@ class Morpheus::Cli::Hosts
|
|
392
472
|
options = {}
|
393
473
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
394
474
|
opts.banner = subcommand_usage("[name]")
|
475
|
+
opts.on( nil, '--costs', "Display Cost and Price" ) do
|
476
|
+
options[:include_costs] = true
|
477
|
+
end
|
395
478
|
opts.on('--refresh [SECONDS]', String, "Refresh until status is provisioned,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
396
479
|
options[:refresh_until_status] ||= "provisioned,failed"
|
397
480
|
if !val.to_s.empty?
|
@@ -453,22 +536,37 @@ class Morpheus::Cli::Hosts
|
|
453
536
|
title = "Host Details"
|
454
537
|
print_h1 title, [], options
|
455
538
|
print cyan
|
456
|
-
|
539
|
+
server_columns = {
|
457
540
|
"ID" => 'id',
|
458
541
|
"Name" => 'name',
|
542
|
+
"Hostname" => 'hostname',
|
459
543
|
"Description" => 'description',
|
460
|
-
"
|
544
|
+
"Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
|
545
|
+
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
461
546
|
#"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
462
547
|
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
548
|
+
"IP" => lambda {|it| it['externalIp'] },
|
549
|
+
"Private IP" => lambda {|it| it['internalIp'] },
|
463
550
|
"Type" => lambda {|it| it['computeServerType'] ? it['computeServerType']['name'] : 'unmanaged' },
|
464
551
|
"Platform" => lambda {|it| it['serverOs'] ? it['serverOs']['name'].upcase : 'N/A' },
|
465
552
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
553
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
554
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
466
555
|
"Agent" => lambda {|it| it['agentInstalled'] ? "#{server['agentVersion'] || ''} updated at #{format_local_dt(server['lastAgentUpdate'])}" : '(not installed)' },
|
467
|
-
"Status" => lambda {|it| format_server_status(it) },
|
468
556
|
"Nodes" => lambda {|it| it['containers'] ? it['containers'].size : 0 },
|
469
|
-
"
|
470
|
-
|
471
|
-
|
557
|
+
# "Status" => lambda {|it| format_server_status(it) },
|
558
|
+
# "Power" => lambda {|it| format_server_power_state(it) },
|
559
|
+
"Status" => lambda {|it| format_server_status_friendly(it) }, # combo
|
560
|
+
}
|
561
|
+
server_columns.delete("Hostname") if server['hostname'].to_s.empty? || server['hostname'] == server['name']
|
562
|
+
server_columns.delete("IP") if server['externalIp'].to_s.empty?
|
563
|
+
server_columns.delete("Private IP") if server['internalIp'].to_s.empty?
|
564
|
+
# server_columns.delete("Tenant") if multi_tenant != true
|
565
|
+
server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
|
566
|
+
server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
|
567
|
+
|
568
|
+
print_description_list(server_columns, server)
|
569
|
+
|
472
570
|
if server['statusMessage']
|
473
571
|
print_h2 "Status Message", options
|
474
572
|
if server['status'] == 'failed'
|
@@ -485,6 +583,16 @@ class Morpheus::Cli::Hosts
|
|
485
583
|
|
486
584
|
print_h2 "Host Usage", options
|
487
585
|
print_stats_usage(stats)
|
586
|
+
|
587
|
+
if options[:include_costs]
|
588
|
+
print_h2 "Host Cost"
|
589
|
+
cost_columns = {
|
590
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
591
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
592
|
+
}
|
593
|
+
print_description_list(cost_columns, server)
|
594
|
+
end
|
595
|
+
|
488
596
|
print reset, "\n"
|
489
597
|
|
490
598
|
|
@@ -1781,6 +1889,102 @@ class Morpheus::Cli::Hosts
|
|
1781
1889
|
end
|
1782
1890
|
end
|
1783
1891
|
|
1892
|
+
def snapshots(args)
|
1893
|
+
options = {}
|
1894
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1895
|
+
opts.banner = subcommand_usage("[host]")
|
1896
|
+
# no pagination yet
|
1897
|
+
# build_standard_list_options(opts, options)
|
1898
|
+
build_standard_get_options(opts, options)
|
1899
|
+
end
|
1900
|
+
optparse.parse!(args)
|
1901
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
1902
|
+
connect(options)
|
1903
|
+
begin
|
1904
|
+
server = find_host_by_name_or_id(args[0])
|
1905
|
+
return 1 if server.nil?
|
1906
|
+
params = {}
|
1907
|
+
@servers_interface.setopts(options)
|
1908
|
+
if options[:dry_run]
|
1909
|
+
print_dry_run @servers_interface.dry.snapshots(server['id'], params)
|
1910
|
+
return
|
1911
|
+
end
|
1912
|
+
json_response = @servers_interface.snapshots(server['id'], params)
|
1913
|
+
snapshots = json_response['snapshots']
|
1914
|
+
render_response(json_response, options, 'snapshots') do
|
1915
|
+
print_h1 "Snapshots: #{server['name']}", [], options
|
1916
|
+
if snapshots.empty?
|
1917
|
+
print cyan,"No snapshots found",reset,"\n"
|
1918
|
+
else
|
1919
|
+
snapshot_column_definitions = {
|
1920
|
+
"ID" => lambda {|it| it['id'] },
|
1921
|
+
"Name" => lambda {|it| it['name'] },
|
1922
|
+
"Description" => lambda {|it| it['snapshotType'] ? (it['snapshotType']['name'] || it['snapshotType']['code']) : '' },
|
1923
|
+
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
1924
|
+
"Status" => lambda {|it| format_snapshot_status(it) }
|
1925
|
+
}
|
1926
|
+
print cyan
|
1927
|
+
print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
|
1928
|
+
print_results_pagination({size: snapshots.size, total: snapshots.size})
|
1929
|
+
end
|
1930
|
+
print reset, "\n"
|
1931
|
+
end
|
1932
|
+
return 0
|
1933
|
+
rescue RestClient::Exception => e
|
1934
|
+
print_rest_exception(e, options)
|
1935
|
+
exit 1
|
1936
|
+
end
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
def software(args)
|
1940
|
+
options = {}
|
1941
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1942
|
+
opts.banner = subcommand_usage("[host]")
|
1943
|
+
build_standard_list_options(opts, options)
|
1944
|
+
end
|
1945
|
+
optparse.parse!(args)
|
1946
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
1947
|
+
connect(options)
|
1948
|
+
begin
|
1949
|
+
server = find_host_by_name_or_id(args[0])
|
1950
|
+
return 1 if server.nil?
|
1951
|
+
params = {}
|
1952
|
+
params.merge!(parse_list_options(options))
|
1953
|
+
@servers_interface.setopts(options)
|
1954
|
+
if options[:dry_run]
|
1955
|
+
print_dry_run @servers_interface.dry.software(server['id'], params)
|
1956
|
+
return
|
1957
|
+
end
|
1958
|
+
json_response = @servers_interface.software(server['id'], params)
|
1959
|
+
software = json_response['software']
|
1960
|
+
render_response(json_response, options, 'software') do
|
1961
|
+
print_h1 "Software: #{server['name']}", [], options
|
1962
|
+
if software.empty?
|
1963
|
+
print cyan,"No software found",reset,"\n"
|
1964
|
+
else
|
1965
|
+
software_column_definitions = {
|
1966
|
+
# "ID" => lambda {|it| it['id'] },
|
1967
|
+
"Name" => lambda {|it| it['name'] },
|
1968
|
+
"Version" => lambda {|it| it['packageVersion'] },
|
1969
|
+
"Publisher" => lambda {|it| it['packagePublisher'] },
|
1970
|
+
# "Release" => lambda {|it| it['packageRelease'] },
|
1971
|
+
# "Type" => lambda {|it| it['packageType'] },
|
1972
|
+
# "Architecture" => lambda {|it| it['architecture'] },
|
1973
|
+
# "Install Date" => lambda {|it| format_local_dt(it['installDate']) },
|
1974
|
+
}
|
1975
|
+
print cyan
|
1976
|
+
print as_pretty_table(software, software_column_definitions.upcase_keys!, options)
|
1977
|
+
print_results_pagination({size: software.size, total: software.size})
|
1978
|
+
end
|
1979
|
+
print reset, "\n"
|
1980
|
+
end
|
1981
|
+
return 0
|
1982
|
+
rescue RestClient::Exception => e
|
1983
|
+
print_rest_exception(e, options)
|
1984
|
+
exit 1
|
1985
|
+
end
|
1986
|
+
end
|
1987
|
+
|
1784
1988
|
private
|
1785
1989
|
|
1786
1990
|
def find_host_by_id(id)
|
@@ -1897,16 +2101,43 @@ class Morpheus::Cli::Hosts
|
|
1897
2101
|
|
1898
2102
|
def format_server_status(server, return_color=cyan)
|
1899
2103
|
out = ""
|
1900
|
-
status_string = server['status']
|
1901
|
-
|
1902
|
-
|
2104
|
+
status_string = server['status'].to_s.downcase
|
2105
|
+
if status_string == 'provisioned'
|
2106
|
+
out = "#{cyan}#{status_string.upcase}#{return_color}"
|
2107
|
+
elsif status_string == 'provisioning'
|
2108
|
+
out = "#{cyan}#{status_string.upcase}#{cyan}"
|
2109
|
+
elsif status_string == 'failed' or status_string == 'error'
|
2110
|
+
out = "#{red}#{status_string.upcase}#{return_color}"
|
2111
|
+
else
|
2112
|
+
out = "#{yellow}#{status_string.upcase}#{return_color}"
|
2113
|
+
end
|
2114
|
+
out
|
2115
|
+
end
|
2116
|
+
|
2117
|
+
def format_server_status_friendly(server, return_color=cyan)
|
2118
|
+
out = ""
|
2119
|
+
status_string = server['status'].to_s.downcase
|
2120
|
+
if status_string == 'provisioned'
|
2121
|
+
# out = format_server_power_state(server, return_color)
|
2122
|
+
# make it looks like format_instance_status
|
2123
|
+
if server['powerState'] == 'on'
|
2124
|
+
out << "#{green}RUNNING#{return_color}"
|
2125
|
+
elsif server['powerState'] == 'off'
|
2126
|
+
out << "#{red}STOPPED#{return_color}"
|
2127
|
+
else
|
2128
|
+
out << "#{white}#{server['powerState'].to_s.upcase}#{return_color}"
|
2129
|
+
end
|
2130
|
+
else
|
2131
|
+
out = format_server_status(server, return_color)
|
2132
|
+
end
|
1903
2133
|
out
|
1904
2134
|
end
|
2135
|
+
|
1905
2136
|
|
1906
2137
|
def make_managed_option_types(connected=true)
|
1907
2138
|
[
|
1908
2139
|
#{'fieldName' => 'account', 'fieldLabel' => 'Account', 'type' => 'select', 'optionSource' => 'accounts', 'required' => true},
|
1909
|
-
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'
|
2140
|
+
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'},
|
1910
2141
|
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false},
|
1911
2142
|
{'fieldName' => 'serverOs', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false},
|
1912
2143
|
]
|